aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/bcm/pinctrl-bcm2835.c27
-rw-r--r--drivers/pinctrl/pinctrl-rp1.c1380
2 files changed, 542 insertions, 865 deletions
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index c165674c5b4d..82c7074811ba 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -245,7 +245,7 @@ static const char * const irq_type_names[] = {
[IRQ_TYPE_LEVEL_LOW] = "level-low",
};
-static bool persist_gpio_outputs;
+static bool persist_gpio_outputs = true;
module_param(persist_gpio_outputs, bool, 0444);
MODULE_PARM_DESC(persist_gpio_outputs, "Enable GPIO_OUT persistence when pin is freed");
@@ -428,15 +428,32 @@ static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
unsigned long events;
unsigned offset;
unsigned gpio;
+ u32 levs, levs2;
events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4);
+ levs = bcm2835_gpio_rd(pc, GPLEV0 + bank * 4);
events &= mask;
events &= pc->enabled_irq_map[bank];
+ bcm2835_gpio_wr(pc, GPEDS0 + bank * 4, events);
+
+retry:
for_each_set_bit(offset, &events, 32) {
gpio = (32 * bank) + offset;
generic_handle_domain_irq(pc->gpio_chip.irq.domain,
gpio);
}
+ events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4);
+ levs2 = bcm2835_gpio_rd(pc, GPLEV0 + bank * 4);
+
+ events |= levs2 & ~levs & bcm2835_gpio_rd(pc, GPREN0 + bank * 4);
+ events |= ~levs2 & levs & bcm2835_gpio_rd(pc, GPFEN0 + bank * 4);
+ events &= mask;
+ events &= pc->enabled_irq_map[bank];
+ if (events) {
+ bcm2835_gpio_wr(pc, GPEDS0 + bank * 4, events);
+ levs = levs2;
+ goto retry;
+ }
}
static void bcm2835_gpio_irq_handler(struct irq_desc *desc)
@@ -676,11 +693,7 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
static void bcm2835_gpio_irq_ack(struct irq_data *data)
{
- struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
- struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
- unsigned gpio = irqd_to_hwirq(data);
-
- bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
+ /* Nothing to do - the main interrupt handler includes the ACK */
}
static int bcm2835_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
@@ -1426,7 +1439,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
- err = gpiochip_add_data(&pc->gpio_chip, pc);
+ err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
if (err) {
dev_err(dev, "could not add GPIO chip\n");
goto out_remove;
diff --git a/drivers/pinctrl/pinctrl-rp1.c b/drivers/pinctrl/pinctrl-rp1.c
index ffc2f0b460a6..08d435a6798d 100644
--- a/drivers/pinctrl/pinctrl-rp1.c
+++ b/drivers/pinctrl/pinctrl-rp1.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Driver for Raspberry Pi RP1 GPIO unit
+ * Driver for Raspberry Pi RP1 GPIO unit (pinctrl + GPIO)
*
* Copyright (C) 2023 Raspberry Pi Ltd.
*
@@ -8,142 +8,143 @@
* pinctrl-bcm2835.c, please see original file for copyright information
*/
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdesc.h>
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
#include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf-generic.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
-#include <linux/regmap.h>
-
-#include "pinmux.h"
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include "core.h"
#include "pinconf.h"
#include "pinctrl-utils.h"
#define MODULE_NAME "pinctrl-rp1"
-#define RP1_NUM_GPIOS 54
-#define RP1_NUM_BANKS 3
+#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_RW_OFFSET 0x0000
+#define RP1_XOR_OFFSET 0x1000
+#define RP1_SET_OFFSET 0x2000
+#define RP1_CLR_OFFSET 0x3000
-#define RP1_FSEL_COUNT 9
+#define RP1_GPIO_STATUS 0x0000
+#define RP1_GPIO_CTRL 0x0004
-#define RP1_FSEL_ALT0 0x00
-#define RP1_FSEL_GPIO 0x05
-#define RP1_FSEL_NONE 0x09
-#define RP1_FSEL_NONE_HW 0x1f
+#define RP1_GPIO_PCIE_INTE 0x011c
+#define RP1_GPIO_PCIE_INTS 0x0124
-#define RP1_PAD_DRIVE_2MA 0x0
-#define RP1_PAD_DRIVE_4MA 0x1
-#define RP1_PAD_DRIVE_8MA 0x2
-#define RP1_PAD_DRIVE_12MA 0x3
+#define RP1_GPIO_EVENTS_SHIFT_RAW 20
+#define RP1_GPIO_STATUS_FALLING BIT(20)
+#define RP1_GPIO_STATUS_RISING BIT(21)
+#define RP1_GPIO_STATUS_LOW BIT(22)
+#define RP1_GPIO_STATUS_HIGH BIT(23)
-enum {
- RP1_PUD_OFF = 0,
- RP1_PUD_DOWN = 1,
- RP1_PUD_UP = 2,
-};
+#define RP1_GPIO_EVENTS_SHIFT_FILTERED 24
+#define RP1_GPIO_STATUS_F_FALLING BIT(24)
+#define RP1_GPIO_STATUS_F_RISING BIT(25)
+#define RP1_GPIO_STATUS_F_LOW BIT(26)
+#define RP1_GPIO_STATUS_F_HIGH BIT(27)
-enum {
- RP1_DIR_OUTPUT = 0,
- RP1_DIR_INPUT = 1,
-};
+#define RP1_GPIO_CTRL_FUNCSEL_LSB 0
+#define RP1_GPIO_CTRL_FUNCSEL_MASK 0x0000001f
+#define RP1_GPIO_CTRL_OUTOVER_LSB 12
+#define RP1_GPIO_CTRL_OUTOVER_MASK 0x00003000
+#define RP1_GPIO_CTRL_OEOVER_LSB 14
+#define RP1_GPIO_CTRL_OEOVER_MASK 0x0000c000
+#define RP1_GPIO_CTRL_INOVER_LSB 16
+#define RP1_GPIO_CTRL_INOVER_MASK 0x00030000
+#define RP1_GPIO_CTRL_IRQEN_FALLING BIT(20)
+#define RP1_GPIO_CTRL_IRQEN_RISING BIT(21)
+#define RP1_GPIO_CTRL_IRQEN_LOW BIT(22)
+#define RP1_GPIO_CTRL_IRQEN_HIGH BIT(23)
+#define RP1_GPIO_CTRL_IRQEN_F_FALLING BIT(24)
+#define RP1_GPIO_CTRL_IRQEN_F_RISING BIT(25)
+#define RP1_GPIO_CTRL_IRQEN_F_LOW BIT(26)
+#define RP1_GPIO_CTRL_IRQEN_F_HIGH BIT(27)
+#define RP1_GPIO_CTRL_IRQRESET BIT(28)
+#define RP1_GPIO_CTRL_IRQOVER_LSB 30
+#define RP1_GPIO_CTRL_IRQOVER_MASK 0xc0000000
-enum {
- RP1_OUTOVER_PERI = 0,
- RP1_OUTOVER_INVPERI = 1,
- RP1_OUTOVER_LOW = 2,
- RP1_OUTOVER_HIGH = 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 0xf
-enum {
- RP1_OEOVER_PERI = 0,
- RP1_OEOVER_INVPERI = 1,
- RP1_OEOVER_DISABLE = 2,
- RP1_OEOVER_ENABLE = 3,
-};
+#define RP1_INT_EDGE_BOTH (RP1_INT_EDGE_FALLING | RP1_INT_EDGE_RISING)
+#define RP1_PUD_OFF 0
+#define RP1_PUD_DOWN 1
+#define RP1_PUD_UP 2
-enum {
- RP1_INOVER_PERI = 0,
- RP1_INOVER_INVPERI = 1,
- RP1_INOVER_LOW = 2,
- RP1_INOVER_HIGH = 3,
-};
+#define RP1_FSEL_COUNT 9
-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,
-};
+#define RP1_FSEL_ALT0 0x00
+#define RP1_FSEL_GPIO 0x05
+#define RP1_FSEL_NONE 0x09
+#define RP1_FSEL_NONE_HW 0x1f
-enum {
- RP1_INTE_SET = 0,
- RP1_INTE_CLR = 1,
-};
+#define RP1_DIR_OUTPUT 0
+#define RP1_DIR_INPUT 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,
-};
+#define RP1_OUTOVER_PERI 0
+#define RP1_OUTOVER_INVPERI 1
+#define RP1_OUTOVER_LOW 2
+#define RP1_OUTOVER_HIGH 3
-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,
-};
+#define RP1_OEOVER_PERI 0
+#define RP1_OEOVER_INVPERI 1
+#define RP1_OEOVER_DISABLE 2
+#define RP1_OEOVER_ENABLE 3
-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),
-};
+#define RP1_INOVER_PERI 0
+#define RP1_INOVER_INVPERI 1
+#define RP1_INOVER_LOW 2
+#define RP1_INOVER_HIGH 3
-static const struct reg_field rp1_inte_fields[] = {
- [RP1_INTE_SET] = REG_FIELD(0x2000, 0, 0),
- [RP1_INTE_CLR] = REG_FIELD(0x3000, 0, 0),
-};
+#define RP1_RIO_OUT 0x00
+#define RP1_RIO_OE 0x04
+#define RP1_RIO_IN 0x08
-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),
-};
+#define RP1_PAD_SLEWFAST_MASK 0x00000001
+#define RP1_PAD_SLEWFAST_LSB 0
+#define RP1_PAD_SCHMITT_MASK 0x00000002
+#define RP1_PAD_SCHMITT_LSB 1
+#define RP1_PAD_PULL_MASK 0x0000000c
+#define RP1_PAD_PULL_LSB 2
+#define RP1_PAD_DRIVE_MASK 0x00000030
+#define RP1_PAD_DRIVE_LSB 4
+#define RP1_PAD_IN_ENABLE_MASK 0x00000040
+#define RP1_PAD_IN_ENABLE_LSB 6
+#define RP1_PAD_OUT_DISABLE_MASK 0x00000080
+#define RP1_PAD_OUT_DISABLE_LSB 7
-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),
-};
+#define RP1_PAD_DRIVE_2MA 0x00000000
+#define RP1_PAD_DRIVE_4MA 0x00000010
+#define RP1_PAD_DRIVE_8MA 0x00000020
+#define RP1_PAD_DRIVE_12MA 0x00000030
+
+#define FLD_GET(r, f) (((r) & (f##_MASK)) >> (f##_LSB))
+#define FLD_SET(r, f, v) r = (((r) & ~(f##_MASK)) | ((v) << (f##_LSB)))
-#define FUNC(f) \
- [func_##f] = #f
+#define FUNC(f) [func_##f] = #f
#define RP1_MAX_FSEL 8
#define PIN(i, f0, f1, f2, f3, f4, f5, f6, f7, f8) \
[i] = { \
@@ -160,18 +161,37 @@ static const struct reg_field rp1_pad_fields[] = {
}, \
}
-#define LEGACY_MAP(n, f0, f1, f2, f3, f4, f5) \
- [n] = { \
- func_gpio, \
- func_gpio, \
- func_##f5, \
- func_##f4, \
- func_##f0, \
- func_##f1, \
- func_##f2, \
- func_##f3, \
+#define LEGACY_MAP(n, f0, f1, f2, f3, f4, f5) \
+ [n] = { \
+ func_gpio, func_gpio, func_##f5, func_##f4, \
+ func_##f0, func_##f1, func_##f2, func_##f3, \
}
+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;
+
+ void __iomem *gpio;
+ void __iomem *rio;
+ void __iomem *inte;
+ void __iomem *ints;
+ void __iomem *pad;
+ void __iomem *dummy;
+};
+
enum funcs {
func_alt0,
func_alt1,
@@ -184,9 +204,12 @@ enum funcs {
func_alt8,
func_none,
func_aaud,
+ func_dcd0,
func_dpi,
func_dsi0_te_ext,
func_dsi1_te_ext,
+ func_dsr0,
+ func_dtr0,
func_gpclk0,
func_gpclk1,
func_gpclk2,
@@ -210,6 +233,7 @@ enum funcs {
func_proc_rio,
func_pwm0,
func_pwm1,
+ func_ri0,
func_sd0,
func_sd1,
func_spi0,
@@ -240,34 +264,12 @@ struct rp1_pin_funcs {
u8 funcs[RP1_FSEL_COUNT];
};
-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;
+ void __iomem *dummy_base;
int irq[RP1_NUM_BANKS];
struct rp1_pin_info pins[RP1_NUM_GPIOS];
@@ -278,286 +280,66 @@ struct rp1_pinctrl {
raw_spinlock_t irq_lock[RP1_NUM_BANKS];
};
+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 },
+};
+
/* pins are just named GPIO0..GPIO53 */
#define RP1_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
static struct pinctrl_pin_desc rp1_gpio_pins[] = {
- RP1_GPIO_PIN(0),
- RP1_GPIO_PIN(1),
- RP1_GPIO_PIN(2),
- RP1_GPIO_PIN(3),
- RP1_GPIO_PIN(4),
- RP1_GPIO_PIN(5),
- RP1_GPIO_PIN(6),
- RP1_GPIO_PIN(7),
- RP1_GPIO_PIN(8),
- RP1_GPIO_PIN(9),
- RP1_GPIO_PIN(10),
- RP1_GPIO_PIN(11),
- RP1_GPIO_PIN(12),
- RP1_GPIO_PIN(13),
- RP1_GPIO_PIN(14),
- RP1_GPIO_PIN(15),
- RP1_GPIO_PIN(16),
- RP1_GPIO_PIN(17),
- RP1_GPIO_PIN(18),
- RP1_GPIO_PIN(19),
- RP1_GPIO_PIN(20),
- RP1_GPIO_PIN(21),
- RP1_GPIO_PIN(22),
- RP1_GPIO_PIN(23),
- RP1_GPIO_PIN(24),
- RP1_GPIO_PIN(25),
- RP1_GPIO_PIN(26),
- RP1_GPIO_PIN(27),
- RP1_GPIO_PIN(28),
- RP1_GPIO_PIN(29),
- RP1_GPIO_PIN(30),
- RP1_GPIO_PIN(31),
- RP1_GPIO_PIN(32),
- RP1_GPIO_PIN(33),
- RP1_GPIO_PIN(34),
- RP1_GPIO_PIN(35),
- RP1_GPIO_PIN(36),
- RP1_GPIO_PIN(37),
- RP1_GPIO_PIN(38),
- RP1_GPIO_PIN(39),
- RP1_GPIO_PIN(40),
- RP1_GPIO_PIN(41),
- RP1_GPIO_PIN(42),
- RP1_GPIO_PIN(43),
- RP1_GPIO_PIN(44),
- RP1_GPIO_PIN(45),
- RP1_GPIO_PIN(46),
- RP1_GPIO_PIN(47),
- RP1_GPIO_PIN(48),
- RP1_GPIO_PIN(49),
- RP1_GPIO_PIN(50),
- RP1_GPIO_PIN(51),
- RP1_GPIO_PIN(52),
- RP1_GPIO_PIN(53),
+ RP1_GPIO_PIN(0), RP1_GPIO_PIN(1), RP1_GPIO_PIN(2), RP1_GPIO_PIN(3),
+ RP1_GPIO_PIN(4), RP1_GPIO_PIN(5), RP1_GPIO_PIN(6), RP1_GPIO_PIN(7),
+ RP1_GPIO_PIN(8), RP1_GPIO_PIN(9), RP1_GPIO_PIN(10), RP1_GPIO_PIN(11),
+ RP1_GPIO_PIN(12), RP1_GPIO_PIN(13), RP1_GPIO_PIN(14), RP1_GPIO_PIN(15),
+ RP1_GPIO_PIN(16), RP1_GPIO_PIN(17), RP1_GPIO_PIN(18), RP1_GPIO_PIN(19),
+ RP1_GPIO_PIN(20), RP1_GPIO_PIN(21), RP1_GPIO_PIN(22), RP1_GPIO_PIN(23),
+ RP1_GPIO_PIN(24), RP1_GPIO_PIN(25), RP1_GPIO_PIN(26), RP1_GPIO_PIN(27),
+ RP1_GPIO_PIN(28), RP1_GPIO_PIN(29), RP1_GPIO_PIN(30), RP1_GPIO_PIN(31),
+ RP1_GPIO_PIN(32), RP1_GPIO_PIN(33), RP1_GPIO_PIN(34), RP1_GPIO_PIN(35),
+ RP1_GPIO_PIN(36), RP1_GPIO_PIN(37), RP1_GPIO_PIN(38), RP1_GPIO_PIN(39),
+ RP1_GPIO_PIN(40), RP1_GPIO_PIN(41), RP1_GPIO_PIN(42), RP1_GPIO_PIN(43),
+ RP1_GPIO_PIN(44), RP1_GPIO_PIN(45), RP1_GPIO_PIN(46), RP1_GPIO_PIN(47),
+ RP1_GPIO_PIN(48), RP1_GPIO_PIN(49), RP1_GPIO_PIN(50), RP1_GPIO_PIN(51),
+ RP1_GPIO_PIN(52), RP1_GPIO_PIN(53),
};
-#define PIN_ARRAY(...) \
- (const unsigned int []) {__VA_ARGS__}
-#define PIN_ARRAY_SIZE(...) \
- (sizeof((unsigned int[]) {__VA_ARGS__}) / sizeof(unsigned int))
-#define RP1_GROUP(name, ...) \
- PINCTRL_PINGROUP(#name, PIN_ARRAY(__VA_ARGS__), \
- PIN_ARRAY_SIZE(__VA_ARGS__))
-
-static const struct pingroup rp1_gpio_groups[] = {
- RP1_GROUP(uart0, 14, 15),
- RP1_GROUP(uart0_ctrl, 4, 5, 6, 7, 16, 17),
- RP1_GROUP(uart1, 0, 1),
- RP1_GROUP(uart1_ctrl, 2, 3),
- RP1_GROUP(uart2, 4, 5),
- RP1_GROUP(uart2_ctrl, 6, 7),
- RP1_GROUP(uart3, 8, 9),
- RP1_GROUP(uart3_ctrl, 10, 11),
- RP1_GROUP(uart4, 12, 13),
- RP1_GROUP(uart4_ctrl, 14, 15),
- RP1_GROUP(uart5_0, 30, 31),
- RP1_GROUP(uart5_0_ctrl, 32, 33),
- RP1_GROUP(uart5_1, 36, 37),
- RP1_GROUP(uart5_1_ctrl, 38, 39),
- RP1_GROUP(uart5_2, 40, 41),
- RP1_GROUP(uart5_2_ctrl, 42, 43),
- RP1_GROUP(uart5_3, 48, 49),
- RP1_GROUP(sd0, 22, 23, 24, 25, 26, 27),
- RP1_GROUP(sd1, 28, 29, 30, 31, 32, 33),
- RP1_GROUP(i2s0, 18, 19, 20, 21),
- RP1_GROUP(i2s0_dual, 18, 19, 20, 21, 22, 23),
- RP1_GROUP(i2s0_quad, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27),
- RP1_GROUP(i2s1, 18, 19, 20, 21),
- RP1_GROUP(i2s1_dual, 18, 19, 20, 21, 22, 23),
- RP1_GROUP(i2s1_quad, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27),
- RP1_GROUP(i2s2_0, 28, 29, 30, 31),
- RP1_GROUP(i2s2_0_dual, 28, 29, 30, 31, 32, 33),
- RP1_GROUP(i2s2_1, 42, 43, 44, 45),
- RP1_GROUP(i2s2_1_dual, 42, 43, 44, 45, 46, 47),
- RP1_GROUP(i2c4_0, 28, 29),
- RP1_GROUP(i2c4_1, 34, 35),
- RP1_GROUP(i2c4_2, 40, 41),
- RP1_GROUP(i2c4_3, 46, 47),
- RP1_GROUP(i2c6_0, 38, 39),
- RP1_GROUP(i2c6_1, 51, 52),
- RP1_GROUP(i2c5_0, 30, 31),
- RP1_GROUP(i2c5_1, 36, 37),
- RP1_GROUP(i2c5_2, 44, 45),
- RP1_GROUP(i2c5_3, 49, 50),
- RP1_GROUP(i2c0_0, 0, 1),
- RP1_GROUP(i2c0_1, 8, 9),
- RP1_GROUP(i2c1_0, 2, 3),
- RP1_GROUP(i2c1_1, 10, 11),
- RP1_GROUP(i2c2_0, 4, 5),
- RP1_GROUP(i2c2_1, 12, 13),
- RP1_GROUP(i2c3_0, 6, 7),
- RP1_GROUP(i2c3_1, 14, 15),
- RP1_GROUP(i2c3_2, 22, 23),
- RP1_GROUP(dpi_16bit, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19),
- RP1_GROUP(dpi_16bit_cpadhi, 0, 1, 2, 3, 4, 5, 6, 7, 8,
- 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24),
- RP1_GROUP(dpi_16bit_pad666, 0, 1, 2, 3, 5, 6, 7, 8, 9,
- 12, 13, 14, 15, 16, 17, 21, 22, 23, 24, 25),
- RP1_GROUP(dpi_18bit, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21),
- RP1_GROUP(dpi_18bit_cpadhi, 0, 1, 2, 3, 4, 5, 6, 7, 8,
- 9, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24,
- 25),
- RP1_GROUP(dpi_24bit, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 27),
- RP1_GROUP(spi0, 9, 10, 11),
- RP1_GROUP(spi0_quad, 0, 1, 9, 10, 11),
- RP1_GROUP(spi1, 19, 20, 21),
- RP1_GROUP(spi2, 1, 2, 3),
- RP1_GROUP(spi3, 5, 6, 7),
- RP1_GROUP(spi4, 9, 10, 11),
- RP1_GROUP(spi5, 13, 14, 15),
- RP1_GROUP(spi6_0, 28, 29, 30),
- RP1_GROUP(spi6_1, 40, 41, 42),
- RP1_GROUP(spi7_0, 46, 47, 48),
- RP1_GROUP(spi7_1, 49, 50, 51),
- RP1_GROUP(spi8_0, 37, 38, 39),
- RP1_GROUP(spi8_1, 49, 50, 51),
- RP1_GROUP(aaud_0, 12, 13),
- RP1_GROUP(aaud_1, 38, 39),
- RP1_GROUP(aaud_2, 40, 41),
- RP1_GROUP(aaud_3, 49, 50),
- RP1_GROUP(aaud_4, 51, 52),
- RP1_GROUP(vbus0_0, 28, 29),
- RP1_GROUP(vbus0_1, 34, 35),
- RP1_GROUP(vbus1, 42, 43),
- RP1_GROUP(vbus2, 50, 51),
- RP1_GROUP(vbus3, 52, 53),
- RP1_GROUP(mic_0, 25, 26, 27),
- RP1_GROUP(mic_1, 34, 35, 36),
- RP1_GROUP(mic_2, 37, 38, 39),
- RP1_GROUP(mic_3, 46, 47, 48),
- RP1_GROUP(ir, 2, 3),
+/* one pin per group */
+static const char *const rp1_gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6",
+ "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13",
+ "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20",
+ "gpio21", "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27",
+ "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34",
+ "gpio35", "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41",
+ "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48",
+ "gpio49", "gpio50", "gpio51", "gpio52", "gpio53",
};
-#define GRP_ARRAY(...) \
- (const char * []) {__VA_ARGS__}
-#define GRP_ARRAY_SIZE(...) \
- (sizeof((char *[]) {__VA_ARGS__}) / sizeof(char *))
-#define RP1_FNC(f, ...) \
- [func_##f] = PINCTRL_PINFUNCTION(#f, GRP_ARRAY(__VA_ARGS__), \
- GRP_ARRAY_SIZE(__VA_ARGS__))
-#define RP1_NULL_FNC(f) \
- [func_##f] = PINCTRL_PINFUNCTION(#f, NULL, 0)
-#define RP1_ALL_LEGACY_PINS \
- "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", \
- "gpio5", "gpio6", "gpio7", "gpio8", "gpio9", \
- "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", \
- "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", \
- "gpio20", "gpio21", "gpio22", "gpio32", "gpio24", \
- "gpio25", "gpio26", "gpio27"
-#define RP1_ALL_PINS RP1_ALL_LEGACY_PINS, \
- "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", \
- "gpio33", "gpio34", "gpio35", "gpio36", "gpio37", \
- "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", \
- "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", \
- "gpio48", "gpio49", "gpio50", "gpio51", "gpio52", \
- "gpio53"
-
-static const struct pinfunction rp1_func_names[] = {
- RP1_NULL_FNC(alt0),
- RP1_NULL_FNC(alt1),
- RP1_NULL_FNC(alt2),
- RP1_NULL_FNC(alt3),
- RP1_NULL_FNC(alt4),
- RP1_FNC(gpio, RP1_ALL_PINS),
- RP1_NULL_FNC(alt6),
- RP1_NULL_FNC(alt7),
- RP1_NULL_FNC(alt8),
- RP1_NULL_FNC(none),
- RP1_FNC(aaud, "aaud_0", "aaud_1", "aaud_2", "aaud_3", "aaud_4",
- "gpio12", "gpio13", "gpio38", "gpio39", "gpio40", "gpio41",
- "gpio49", "gpio50", "gpio51", "gpio52"),
- RP1_FNC(dpi, "dpi_16bit", "dpi_16bit_cpadhi",
- "dpi_16bit_pad666", "dpi_18bit, dpi_18bit_cpadhi",
- "dpi_24bit", RP1_ALL_LEGACY_PINS),
- RP1_FNC(dsi0_te_ext, "gpio16", "gpio38", "gpio46"),
- RP1_FNC(dsi1_te_ext, "gpio17", "gpio39", "gpio47"),
- RP1_FNC(gpclk0, "gpio4", "gpio20"),
- RP1_FNC(gpclk1, "gpio5", "gpio18", "gpio21"),
- RP1_FNC(gpclk2, "gpio6"),
- RP1_FNC(gpclk3, "gpio32", "gpio34", "gpio46"),
- RP1_FNC(gpclk4, "gpio33", "gpio43"),
- RP1_FNC(gpclk5, "gpio42", "gpio44", "gpio47"),
- RP1_FNC(i2c0, "i2c0_0", "i2c0_1", "gpio0", "gpio1", "gpio8", "gpio9"),
- RP1_FNC(i2c1, "i2c1_0", "i2c1_1", "gpio2", "gpio3", "gpio10", "gpio11"),
- RP1_FNC(i2c2, "i2c2_0", "i2c2_1", "gpio4", "gpio5", "gpio12", "gpio13"),
- RP1_FNC(i2c3, "i2c3_0", "i2c3_1", "i2c3_2", "gpio6", "gpio7", "gpio14",
- "gpio15", "gpio22", "gpio23"),
- RP1_FNC(i2c4, "i2c4_0", "i2c4_1", "i2c4_2", "i2c4_3", "gpio28",
- "gpio29", "gpio34", "gpio35", "gpio40", "gpio41", "gpio46",
- "gpio47"),
- RP1_FNC(i2c5, "i2c5_0", "i2c5_1", "i2c5_2", "i2c5_3", "gpio30",
- "gpio31", "gpio36", "gpio37", "gpio44", "gpio45", "gpio49",
- "gpio50"),
- RP1_FNC(i2c6, "i2c6_0", "i2c6_1", "gpio38", "gpio39", "gpio51",
- "gpio52"),
- RP1_FNC(i2s0, "i2s0", "i2s0_dual", "i2s0_quad", "gpio18", "gpio19",
- "gpio20", "gpio21", "gpio22", "gpio23", "gpio24", "gpio25",
- "gpio26", "gpio27"),
- RP1_FNC(i2s1, "i2s1", "i2s1_dual", "i2s1_quad", "gpio18", "gpio19",
- "gpio20", "gpio21", "gpio22", "gpio23", "gpio24", "gpio25",
- "gpio26", "gpio27"),
- RP1_FNC(i2s2, "i2s2_0", "i2s2_0_dual", "i2s2_1", "i2s2_1_dual",
- "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", "gpio33",
- "gpio42", "gpio43", "gpio44", "gpio45", "gpio46", "gpio47"),
- RP1_FNC(ir, "gpio2", "gpio3"),
- RP1_FNC(mic, "mic_0", "mic_1", "mic_2", "mic_3", "gpio25", "gpio26",
- "gpio27", "gpio34", "gpio35", "gpio36", "gpio37", "gpio38",
- "gpio39", "gpio46", "gpio47", "gpio48"),
- RP1_FNC(pcie_clkreq_n, "gpio36", "gpio37", "gpio48", "gpio53"),
- RP1_FNC(pio, RP1_ALL_LEGACY_PINS),
- RP1_FNC(proc_rio, RP1_ALL_PINS),
- RP1_FNC(pwm0, "gpio12", "gpio13", "gpio14", "gpio15", "gpio18",
- "gpio19"),
- RP1_FNC(pwm1, "gpio34", "gpio35", "gpio40", "gpio41", "gpio44",
- "gpio45", "gpio48"),
- RP1_FNC(sd0, "sd0", "gpio22", "gpio23", "gpio24", "gpio25", "gpio26",
- "gpio27"),
- RP1_FNC(sd1, "sd1", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
- "gpio33"),
- RP1_FNC(spi0, "spi0", "spi0_quad", "gpio0", "gpio1", "gpio2", "gpio3",
- "gpio7", "gpio8", "gpio9", "gpio10", "gpio11"),
- RP1_FNC(spi1, "spi1", "gpio19", "gpio20", "gpio21", "gpio16", "gpio17",
- "gpio18", "gpio27"),
- RP1_FNC(spi2, "spi2", "gpio0", "gpio1", "gpio2", "gpio3", "gpio24"),
- RP1_FNC(spi3, "spi3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio25"),
- RP1_FNC(spi4, "spi4", "gpio8", "gpio9", "gpio10", "gpio11"),
- RP1_FNC(spi5, "spi5", "gpio12", "gpio13", "gpio14", "gpio15", "gpio26"),
- RP1_FNC(spi6, "spi6_0", "spi6_1", "gpio28", "gpio29", "gpio30",
- "gpio31", "gpio32", "gpio33", "gpio40", "gpio41", "gpio42",
- "gpio43", "gpio44", "gpio45"),
- RP1_FNC(spi7, "spi7_0", "spi7_1", "gpio45", "gpio46", "gpio47",
- "gpio48", "gpio49", "gpio50", "gpio51", "gpio53"),
- RP1_FNC(spi8, "spi8_0", "spi8_1", "gpio35", "gpio36", "gpio37",
- "gpio38", "gpio39", "gpio49", "gpio50", "gpio51", "gpio52",
- "gpio53"),
- RP1_FNC(uart0, "uart0", "uart0_ctrl", "gpio4", "gpio5", "gpio6",
- "gpio7", "gpio14", "gpio15", "gpio16", "gpio17"),
- RP1_FNC(uart1, "uart1", "uart1_ctrl", "gpio0", "gpio1", "gpio2",
- "gpio3"),
- RP1_FNC(uart2, "uart2", "uart2_ctrl", "gpio4", "gpio5", "gpio6",
- "gpio7"),
- RP1_FNC(uart3, "uart3", "uart3_ctrl", "gpio8", "gpio9", "gpio10",
- "gpio11"),
- RP1_FNC(uart4, "uart4", "uart4_ctrl", "gpio12", "gpio13", "gpio14",
- "gpio15"),
- RP1_FNC(uart5, "uart5_0", "uart5_0_ctrl", "uart5_1", "uart5_1_ctrl",
- "uart5_2", "uart5_2_ctrl", "uart5_3"),
- RP1_FNC(vbus0, "vbus0_0", "vbus0_1", "gpio28", "gpio29", "gpio34",
- "gpio35"),
- RP1_FNC(vbus1, "vbus1", "gpio42", "gpio43"),
- RP1_FNC(vbus2, "vbus2", "gpio50", "gpio51"),
- RP1_FNC(vbus3, "vbus3", "gpio52", "gpio53"),
- RP1_NULL_FNC(invalid), //[func_invalid] = "?"
+static const char *const rp1_func_names[] = {
+ FUNC(alt0), FUNC(alt1), FUNC(alt2),
+ FUNC(alt3), FUNC(alt4), FUNC(gpio),
+ FUNC(alt6), FUNC(alt7), FUNC(alt8),
+ FUNC(none), FUNC(aaud), FUNC(dcd0),
+ FUNC(dpi), FUNC(dsi0_te_ext), FUNC(dsi1_te_ext),
+ FUNC(dsr0), FUNC(dtr0), FUNC(gpclk0),
+ FUNC(gpclk1), FUNC(gpclk2), FUNC(gpclk3),
+ FUNC(gpclk4), FUNC(gpclk5), FUNC(i2c0),
+ FUNC(i2c1), FUNC(i2c2), FUNC(i2c3),
+ FUNC(i2c4), FUNC(i2c5), FUNC(i2c6),
+ FUNC(i2s0), FUNC(i2s1), FUNC(i2s2),
+ FUNC(ir), FUNC(mic), FUNC(pcie_clkreq_n),
+ FUNC(pio), FUNC(proc_rio), FUNC(pwm0),
+ FUNC(pwm1), FUNC(ri0), FUNC(sd0),
+ FUNC(sd1), FUNC(spi0), FUNC(spi1),
+ FUNC(spi2), FUNC(spi3), FUNC(spi4),
+ FUNC(spi5), FUNC(spi6), FUNC(spi7),
+ FUNC(spi8), FUNC(uart0), FUNC(uart1),
+ FUNC(uart2), FUNC(uart3), FUNC(uart4),
+ FUNC(uart5), FUNC(vbus0), FUNC(vbus1),
+ FUNC(vbus2), FUNC(vbus3), [func_invalid] = "?"
};
static const struct rp1_pin_funcs rp1_gpio_pin_funcs[] = {
@@ -565,10 +347,10 @@ static const struct rp1_pin_funcs rp1_gpio_pin_funcs[] = {
PIN(1, spi0, dpi, uart1, i2c0, _, gpio, proc_rio, pio, spi2),
PIN(2, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2),
PIN(3, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2),
- PIN(4, gpclk0, dpi, uart2, i2c2, uart0, gpio, proc_rio, pio, spi3),
- PIN(5, gpclk1, dpi, uart2, i2c2, uart0, gpio, proc_rio, pio, spi3),
- PIN(6, gpclk2, dpi, uart2, i2c3, uart0, gpio, proc_rio, pio, spi3),
- PIN(7, spi0, dpi, uart2, i2c3, uart0, gpio, proc_rio, pio, spi3),
+ PIN(4, gpclk0, dpi, uart2, i2c2, ri0, gpio, proc_rio, pio, spi3),
+ PIN(5, gpclk1, dpi, uart2, i2c2, dtr0, gpio, proc_rio, pio, spi3),
+ PIN(6, gpclk2, dpi, uart2, i2c3, dcd0, gpio, proc_rio, pio, spi3),
+ PIN(7, spi0, dpi, uart2, i2c3, dsr0, gpio, proc_rio, pio, spi3),
PIN(8, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4),
PIN(9, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4),
PIN(10, spi0, dpi, uart3, i2c1, _, gpio, proc_rio, pio, spi4),
@@ -648,7 +430,7 @@ static const u8 legacy_fsel_map[][8] = {
LEGACY_MAP(27, sd0, _, dpi, _, _, _),
};
-static const char * const irq_type_names[] = {
+static const char *const irq_type_names[] = {
[IRQ_TYPE_NONE] = "none",
[IRQ_TYPE_EDGE_RISING] = "edge-rising",
[IRQ_TYPE_EDGE_FALLING] = "edge-falling",
@@ -659,18 +441,50 @@ static const char * const irq_type_names[] = {
static bool persist_gpio_outputs = true;
module_param(persist_gpio_outputs, bool, 0644);
-MODULE_PARM_DESC(persist_gpio_outputs, "Enable GPIO_OUT persistence when pin is freed");
+MODULE_PARM_DESC(persist_gpio_outputs,
+ "Enable GPIO_OUT persistence when pin is freed");
-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 bool pace_pin_updates = true;
+module_param(pace_pin_updates, bool, 0644);
+MODULE_PARM_DESC(
+ pace_pin_updates,
+ "Update pin states with guaranteed monotonicity if PCIe ASPM is enabled");
+
+static inline void rp1_pin_writel(u32 val, void __iomem *dummy,
+ void __iomem *reg)
+{
+ unsigned long flags;
-static int rp1_pinconf_set(struct pinctrl_dev *pctldev,
- unsigned int offset, unsigned long *configs,
- unsigned int num_configs);
+ local_irq_save(flags);
+ /*
+ * Issuing 6 pipelined writes to the RC's Slot Control register will stall the
+ * peripheral bus inside 2712 if the link is in L1. This acts as a lightweight
+ * "fence" operation preventing back-to-back writes arriving at RP1 on a wake.
+ */
+ if (dummy) {
+ writel_relaxed(0, dummy);
+ writel_relaxed(0, dummy);
+ writel_relaxed(0, dummy);
+ writel_relaxed(0, dummy);
+ writel_relaxed(0, dummy);
+ writel_relaxed(0, dummy);
+ }
+ writel_relaxed(val, reg);
+ local_irq_restore(flags);
+}
+
+static inline u32 rp1_pin_readl(const void __iomem *ioaddr)
+{
+ /*
+ * Prior posted writes may not yet have been emitted by the CPU - do a store-flush
+ * before reading GPIO state, as this will serialise writes versus the next issued read.
+ */
+ __dma_wmb();
+ return readl(ioaddr);
+}
+
+static int rp1_pinconf_set(struct pinctrl_dev *pctldev, 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)
@@ -692,22 +506,33 @@ static struct rp1_pin_info *rp1_get_pin_pctl(struct pinctrl_dev *pctldev,
return NULL;
}
+static void rp1_pad_update(struct rp1_pin_info *pin, u32 clr, u32 set)
+{
+ u32 padctrl = rp1_pin_readl(pin->pad);
+
+ padctrl &= ~clr;
+ padctrl |= set;
+
+ rp1_pin_writel(padctrl, pin->dummy, pin->pad);
+}
+
static void rp1_input_enable(struct rp1_pin_info *pin, int value)
{
- regmap_field_write(pin->pad[RP1_PAD_IN_ENABLE], !!value);
+ rp1_pad_update(pin, RP1_PAD_IN_ENABLE_MASK,
+ value ? RP1_PAD_IN_ENABLE_MASK : 0);
}
static void rp1_output_enable(struct rp1_pin_info *pin, int value)
{
- regmap_field_write(pin->pad[RP1_PAD_OUT_DISABLE], !value);
+ rp1_pad_update(pin, RP1_PAD_OUT_DISABLE_MASK,
+ value ? 0 : RP1_PAD_OUT_DISABLE_MASK);
}
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);
+ u32 ctrl = rp1_pin_readl(pin->gpio + RP1_GPIO_CTRL);
+ u32 oeover = FLD_GET(ctrl, RP1_GPIO_CTRL_OEOVER);
+ u32 fsel = FLD_GET(ctrl, RP1_GPIO_CTRL_FUNCSEL);
if (oeover != RP1_OEOVER_PERI || fsel >= RP1_FSEL_COUNT)
fsel = RP1_FSEL_NONE;
@@ -717,6 +542,8 @@ static u32 rp1_get_fsel(struct rp1_pin_info *pin)
static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel)
{
+ u32 ctrl = rp1_pin_readl(pin->gpio + RP1_GPIO_CTRL);
+
if (fsel >= RP1_FSEL_COUNT)
fsel = RP1_FSEL_NONE_HW;
@@ -724,62 +551,55 @@ static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel)
rp1_output_enable(pin, 1);
if (fsel == RP1_FSEL_NONE) {
- regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OEOVER], RP1_OEOVER_DISABLE);
+ FLD_SET(ctrl, 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);
+ FLD_SET(ctrl, RP1_GPIO_CTRL_OUTOVER, RP1_OUTOVER_PERI);
+ FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_PERI);
}
-
- regmap_field_write(pin->gpio[RP1_GPIO_CTRL_FUNCSEL], fsel);
+ FLD_SET(ctrl, RP1_GPIO_CTRL_FUNCSEL, fsel);
+ rp1_pin_writel(ctrl, pin->dummy, pin->gpio + RP1_GPIO_CTRL);
}
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;
+ return !(rp1_pin_readl(pin->rio + RP1_RIO_OE) & (1 << pin->offset)) ?
+ 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;
+ int offset = is_input ? RP1_CLR_OFFSET : RP1_SET_OFFSET;
- regmap_field_write(pin->rio[reg], 1);
+ rp1_pin_writel(1 << pin->offset, pin->dummy,
+ pin->rio + RP1_RIO_OE + offset);
}
static int rp1_get_value(struct rp1_pin_info *pin)
{
- unsigned int val;
-
- regmap_field_read(pin->rio[RP1_RIO_IN], &val);
-
- return !!val;
+ return !!(rp1_pin_readl(pin->rio + RP1_RIO_IN) & (1 << pin->offset));
}
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);
+ rp1_pin_writel(1 << pin->offset, pin->dummy,
+ pin->rio + RP1_RIO_OUT +
+ (value ? RP1_SET_OFFSET : RP1_CLR_OFFSET));
}
-static int rp1_gpio_get(struct gpio_chip *chip, unsigned int offset)
+static int rp1_gpio_get(struct gpio_chip *chip, unsigned 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 int rp1_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
+static int rp1_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
@@ -796,17 +616,14 @@ static int rp1_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
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;
+ 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)
+static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
@@ -814,11 +631,10 @@ static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
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,
+static int rp1_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
int value)
{
struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
@@ -828,14 +644,13 @@ static int rp1_gpio_direction_output(struct gpio_chip *chip, unsigned int offset
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,
+static int rp1_gpio_set_config(struct gpio_chip *gc, unsigned offset,
unsigned long config)
{
- struct rp1_pinctrl *pc = gpiochip_get_data(chip);
+ struct rp1_pinctrl *pc = gpiochip_get_data(gc);
unsigned long configs[] = { config };
return rp1_pinconf_set(pc->pctl_dev, offset, configs,
@@ -861,12 +676,12 @@ static const struct gpio_chip rp1_gpio_chip = {
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);
+ struct irq_chip *host_chip = irq_desc_get_chip(desc);
const struct rp1_iobank_desc *bank;
int irq = irq_desc_get_irq(desc);
unsigned long ints;
- int bit_pos;
+ int b;
if (pc->irq[0] == irq)
bank = &rp1_iobanks[0];
@@ -878,12 +693,14 @@ static void rp1_gpio_irq_handler(struct irq_desc *desc)
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);
+ for_each_set_bit(b, &ints, 32) {
+ struct rp1_pin_info *pin =
+ rp1_get_pin(chip, bank->min_gpio + b);
- regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1);
+ writel(RP1_GPIO_CTRL_IRQRESET,
+ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
generic_handle_irq(irq_find_mapping(pc->gpio_chip.irq.domain,
- bank->gpio_offset + bit_pos));
+ bank->min_gpio + b));
}
chained_irq_exit(host_chip, desc);
@@ -891,18 +708,18 @@ static void rp1_gpio_irq_handler(struct irq_desc *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);
+ writel(1 << pin->offset,
+ pin->inte + (enable ? RP1_SET_OFFSET : RP1_CLR_OFFSET));
if (!enable)
/* Clear any latched events */
- regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1);
+ writel(RP1_GPIO_CTRL_IRQRESET,
+ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
}
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);
+ unsigned gpio = irqd_to_hwirq(data);
struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
rp1_gpio_irq_config(pin, true);
@@ -911,7 +728,7 @@ static void rp1_gpio_irq_enable(struct irq_data *data)
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);
+ unsigned gpio = irqd_to_hwirq(data);
struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
rp1_gpio_irq_config(pin, false);
@@ -945,11 +762,15 @@ static int rp1_irq_set_type(struct rp1_pin_info *pin, unsigned int type)
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);
+ /* Clear the event enables */
+ writel(RP1_INT_MASK << RP1_GPIO_EVENTS_SHIFT_RAW,
+ pin->gpio + RP1_CLR_OFFSET + RP1_GPIO_CTRL);
+ /* Clear any latched events */
+ writel(RP1_GPIO_CTRL_IRQRESET,
+ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
+ /* Enable the events that are needed */
+ writel(irq_flags << RP1_GPIO_EVENTS_SHIFT_RAW,
+ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
pin->irq_type = type;
return 0;
@@ -958,9 +779,9 @@ static int rp1_irq_set_type(struct rp1_pin_info *pin, unsigned int type)
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);
+ unsigned gpio = irqd_to_hwirq(data);
+ struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
int bank = pin->bank;
unsigned long flags;
int ret;
@@ -983,14 +804,16 @@ static int rp1_gpio_irq_set_type(struct irq_data *data, unsigned int type)
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);
+ unsigned 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);
+ writel(RP1_GPIO_CTRL_IRQRESET,
+ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL);
}
-static int rp1_gpio_irq_set_affinity(struct irq_data *data, const struct cpumask *dest, bool force)
+static int rp1_gpio_irq_set_affinity(struct irq_data *data,
+ const struct cpumask *dest, bool force)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct rp1_pinctrl *pc = gpiochip_get_data(chip);
@@ -1008,7 +831,8 @@ static int rp1_gpio_irq_set_affinity(struct irq_data *data, const struct cpumask
}
if (parent_data && parent_data->chip->irq_set_affinity)
- return parent_data->chip->irq_set_affinity(parent_data, dest, force);
+ return parent_data->chip->irq_set_affinity(parent_data, dest,
+ force);
return -EINVAL;
}
@@ -1023,26 +847,20 @@ static struct irq_chip rp1_gpio_irq_chip = {
.irq_unmask = rp1_gpio_irq_enable,
.irq_set_affinity = rp1_gpio_irq_set_affinity,
.flags = IRQCHIP_IMMUTABLE,
- GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
static int rp1_pctl_get_groups_count(struct pinctrl_dev *pctldev)
{
- return ARRAY_SIZE(rp1_gpio_groups) + ARRAY_SIZE(rp1_gpio_pins);
+ return ARRAY_SIZE(rp1_gpio_groups);
}
static const char *rp1_pctl_get_group_name(struct pinctrl_dev *pctldev,
- unsigned int selector)
+ unsigned selector)
{
- unsigned int ngroups = ARRAY_SIZE(rp1_gpio_groups);
-
- if (selector < ngroups)
- return rp1_gpio_groups[selector].name;
-
- return rp1_gpio_pins[selector - ngroups].name;
+ return rp1_gpio_groups[selector];
}
-static enum funcs rp1_get_fsel_func(unsigned int pin, unsigned int fsel)
+static enum funcs rp1_get_fsel_func(unsigned pin, unsigned fsel)
{
if (pin < RP1_NUM_GPIOS) {
if (fsel < RP1_FSEL_COUNT)
@@ -1054,26 +872,17 @@ static enum funcs rp1_get_fsel_func(unsigned int pin, unsigned int fsel)
}
static int rp1_pctl_get_group_pins(struct pinctrl_dev *pctldev,
- unsigned int selector,
- const unsigned int **pins,
- unsigned int *num_pins)
+ unsigned selector, const unsigned **pins,
+ unsigned *num_pins)
{
- unsigned int ngroups = ARRAY_SIZE(rp1_gpio_groups);
-
- if (selector < ngroups) {
- *pins = rp1_gpio_groups[selector].pins;
- *num_pins = rp1_gpio_groups[selector].npins;
- } else {
- *pins = &rp1_gpio_pins[selector - ngroups].number;
- *num_pins = 1;
- }
+ *pins = &rp1_gpio_pins[selector].number;
+ *num_pins = 1;
return 0;
}
static void rp1_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
- struct seq_file *s,
- unsigned int offset)
+ struct seq_file *s, unsigned offset)
{
struct rp1_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
struct gpio_chip *chip = &pc->gpio_chip;
@@ -1084,13 +893,12 @@ static void rp1_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
int irq = irq_find_mapping(chip->irq.domain, offset);
seq_printf(s, "function %s (%s) in %s; irq %d (%s)",
- rp1_func_names[fsel].name, rp1_func_names[func].name,
- value ? "hi" : "lo",
- irq, irq_type_names[pin->irq_type]);
+ rp1_func_names[fsel], rp1_func_names[func],
+ value ? "hi" : "lo", irq, irq_type_names[pin->irq_type]);
}
static void rp1_pctl_dt_free_map(struct pinctrl_dev *pctldev,
- struct pinctrl_map *maps, unsigned int num_maps)
+ struct pinctrl_map *maps, unsigned num_maps)
{
int i;
@@ -1119,16 +927,19 @@ static int rp1_pctl_legacy_map_func(struct rp1_pinctrl *pc,
} else if (fnum < 2) {
func = func_gpio;
} else {
- dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n",
- np, pin);
+ dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n", np, pin);
return -EINVAL;
}
+ if (func == func_invalid) {
+ dev_err(pc->dev,
+ "%pOF: brcm,function %d not supported on pin %d\n", np,
+ fnum, pin);
+ }
+
map->type = PIN_MAP_TYPE_MUX_GROUP;
- map->data.mux.group = rp1_pctl_get_group_name(pc->pctl_dev,
- ARRAY_SIZE(rp1_gpio_groups)
- + pin);
- map->data.mux.function = rp1_func_names[func].name;
+ map->data.mux.group = rp1_gpio_groups[pin];
+ map->data.mux.function = rp1_func_names[func];
(*num_maps)++;
return 0;
@@ -1192,7 +1003,8 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
pins = of_find_property(np, "brcm,pins", NULL);
if (!pins) /* Assume generic bindings in this node */
- return pinconf_generic_dt_node_to_map_all(pctldev, np, map, num_maps);
+ return pinconf_generic_dt_node_to_map_all(pctldev, np, map,
+ num_maps);
funcs = of_find_property(np, "brcm,function", NULL);
if (!funcs)
@@ -1200,7 +1012,8 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
pulls = of_find_property(np, "brcm,pull", NULL);
if (!pulls)
- pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs);
+ pinconf_generic_parse_dt_config(np, pctldev, &configs,
+ &num_configs);
if (!function && !funcs && !num_configs && !pulls) {
dev_err(pc->dev,
@@ -1215,14 +1028,13 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
if (num_funcs > 1 && num_funcs != num_pins) {
dev_err(pc->dev,
- "%pOF: brcm,function must have 1 or %d entries\n",
- np, num_pins);
+ "%pOF: brcm,function must have 1 or %d entries\n", np,
+ num_pins);
return -EINVAL;
}
if (num_pulls > 1 && num_pulls != num_pins) {
- dev_err(pc->dev,
- "%pOF: brcm,pull must have 1 or %d entries\n",
+ dev_err(pc->dev, "%pOF: brcm,pull must have 1 or %d entries\n",
np, num_pins);
return -EINVAL;
}
@@ -1244,37 +1056,35 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
if (err)
goto out;
if (num_funcs) {
- err = of_property_read_u32_index(np, "brcm,function",
- (num_funcs > 1) ? i : 0,
- &func);
+ err = of_property_read_u32_index(
+ np, "brcm,function", (num_funcs > 1) ? i : 0,
+ &func);
if (err)
goto out;
- err = rp1_pctl_legacy_map_func(pc, np, pin, func,
- maps, num_maps);
+ err = rp1_pctl_legacy_map_func(pc, np, pin, func, maps,
+ num_maps);
} else if (function) {
- err = pinctrl_utils_add_map_mux(pctldev, &maps,
- &reserved_maps, num_maps,
- rp1_gpio_groups[pin].name,
- function);
+ err = pinctrl_utils_add_map_mux(
+ pctldev, &maps, &reserved_maps, num_maps,
+ rp1_gpio_groups[pin], function);
}
if (err)
goto out;
if (num_pulls) {
- err = of_property_read_u32_index(np, "brcm,pull",
- (num_pulls > 1) ? i : 0,
- &pull);
+ err = of_property_read_u32_index(
+ np, "brcm,pull", (num_pulls > 1) ? i : 0,
+ &pull);
if (err)
goto out;
- err = rp1_pctl_legacy_map_pull(pc, np, pin, pull,
- maps, num_maps);
+ err = rp1_pctl_legacy_map_pull(pc, np, pin, pull, maps,
+ num_maps);
} else if (num_configs) {
- err = pinctrl_utils_add_map_configs(pctldev, &maps,
- &reserved_maps, num_maps,
- rp1_gpio_groups[pin].name,
- configs, num_configs,
- PIN_MAP_TYPE_CONFIGS_PIN);
+ err = pinctrl_utils_add_map_configs(
+ pctldev, &maps, &reserved_maps, num_maps,
+ rp1_gpio_groups[pin], configs, num_configs,
+ PIN_MAP_TYPE_CONFIGS_PIN);
}
if (err)
@@ -1299,7 +1109,7 @@ static const struct pinctrl_ops rp1_pctl_ops = {
.dt_free_map = rp1_pctl_dt_free_map,
};
-static int rp1_pmx_free(struct pinctrl_dev *pctldev, unsigned int offset)
+static int rp1_pmx_free(struct pinctrl_dev *pctldev, unsigned offset)
{
struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset);
u32 fsel = rp1_get_fsel(pin);
@@ -1320,67 +1130,61 @@ static int rp1_pmx_get_functions_count(struct pinctrl_dev *pctldev)
}
static const char *rp1_pmx_get_function_name(struct pinctrl_dev *pctldev,
- unsigned int selector)
+ unsigned selector)
{
- return (selector < func_count) ? rp1_func_names[selector].name : NULL;
+ return (selector < func_count) ? rp1_func_names[selector] : NULL;
}
static int rp1_pmx_get_function_groups(struct pinctrl_dev *pctldev,
- unsigned int selector,
- const char * const **groups,
- unsigned * const num_groups)
+ unsigned selector,
+ const char *const **groups,
+ unsigned *const num_groups)
{
- *groups = rp1_func_names[selector].groups;
- *num_groups = rp1_func_names[selector].ngroups;
+ /* every pin can do every function */
+ *groups = rp1_gpio_groups;
+ *num_groups = ARRAY_SIZE(rp1_gpio_groups);
return 0;
}
-static int rp1_pmx_set(struct pinctrl_dev *pctldev, unsigned int func_selector,
- unsigned int group_selector)
+static int rp1_pmx_set(struct pinctrl_dev *pctldev, unsigned func_selector,
+ unsigned group_selector)
{
- struct rp1_pin_info *pin;
- const unsigned int *pins;
+ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, group_selector);
const u8 *pin_funcs;
- unsigned int num_pins;
- int offset, fsel;
+ int fsel;
- rp1_pctl_get_group_pins(pctldev, group_selector, &pins, &num_pins);
+ /* func_selector is an enum funcs, so needs translation */
- for (offset = 0; offset < num_pins; ++offset) {
- pin = rp1_get_pin_pctl(pctldev, pins[offset]);
- /* func_selector is an enum funcs, so needs translation */
- if (func_selector >= RP1_FSEL_COUNT) {
- /* Convert to an fsel number */
- pin_funcs = rp1_gpio_pin_funcs[pin->num].funcs;
- for (fsel = 0; fsel < RP1_FSEL_COUNT; fsel++) {
- if (pin_funcs[fsel] == func_selector)
- break;
- }
- } else {
- fsel = (int)func_selector;
+ if (func_selector >= RP1_FSEL_COUNT) {
+ /* Convert to an fsel number */
+ pin_funcs = rp1_gpio_pin_funcs[pin->num].funcs;
+ for (fsel = 0; fsel < RP1_FSEL_COUNT; fsel++) {
+ if (pin_funcs[fsel] == func_selector)
+ break;
}
+ } else {
+ fsel = (int)func_selector;
+ }
- if (fsel >= RP1_FSEL_COUNT && fsel != RP1_FSEL_NONE)
- return -EINVAL;
+ if (fsel >= RP1_FSEL_COUNT && fsel != RP1_FSEL_NONE)
+ return -EINVAL;
- rp1_set_fsel(pin, fsel);
- }
+ rp1_set_fsel(pin, fsel);
return 0;
}
static void rp1_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
- unsigned int offset)
+ unsigned offset)
{
(void)rp1_pmx_free(pctldev, offset);
}
static int rp1_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
- unsigned int offset,
- bool input)
+ unsigned offset, bool input)
{
struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset);
@@ -1402,9 +1206,15 @@ static const struct pinmux_ops rp1_pmx_ops = {
static void rp1_pull_config_set(struct rp1_pin_info *pin, unsigned int arg)
{
- regmap_field_write(pin->pad[RP1_PAD_PULL], arg & 0x3);
+ u32 padctrl = rp1_pin_readl(pin->pad);
+
+ FLD_SET(padctrl, RP1_PAD_PULL, arg & 0x3);
+
+ writel(padctrl, pin->pad);
}
+/* Generic pinconf methods */
+
static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset,
unsigned long *configs, unsigned int num_configs)
{
@@ -1447,11 +1257,13 @@ static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset,
break;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
- regmap_field_write(pin->pad[RP1_PAD_SCHMITT], !!arg);
+ rp1_pad_update(pin, RP1_PAD_SCHMITT_MASK,
+ arg ? RP1_PAD_SCHMITT_MASK : 0);
break;
case PIN_CONFIG_SLEW_RATE:
- regmap_field_write(pin->pad[RP1_PAD_SLEWFAST], !!arg);
+ rp1_pad_update(pin, RP1_PAD_SLEWFAST_MASK,
+ arg ? RP1_PAD_SLEWFAST_MASK : 0);
break;
case PIN_CONFIG_DRIVE_STRENGTH:
@@ -1471,7 +1283,7 @@ static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset,
default:
return -ENOTSUPP;
}
- regmap_field_write(pin->pad[RP1_PAD_DRIVE], arg);
+ rp1_pad_update(pin, RP1_PAD_DRIVE_MASK, arg);
break;
default:
@@ -1483,7 +1295,7 @@ static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset,
return 0;
}
-static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned int offset,
+static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned offset,
unsigned long *config)
{
struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset);
@@ -1494,26 +1306,23 @@ static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned int offset,
if (!pin)
return -EINVAL;
+ padctrl = rp1_pin_readl(pin->pad);
+
switch (param) {
case PIN_CONFIG_INPUT_ENABLE:
- regmap_field_read(pin->pad[RP1_PAD_IN_ENABLE], &padctrl);
- arg = !!padctrl;
+ arg = !!(padctrl & RP1_PAD_IN_ENABLE_MASK);
break;
case PIN_CONFIG_OUTPUT_ENABLE:
- regmap_field_read(pin->pad[RP1_PAD_OUT_DISABLE], &padctrl);
- arg = !padctrl;
+ arg = !(padctrl & RP1_PAD_OUT_DISABLE_MASK);
break;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
- regmap_field_read(pin->pad[RP1_PAD_SCHMITT], &padctrl);
- arg = !!padctrl;
+ arg = !!(padctrl & RP1_PAD_SCHMITT_MASK);
break;
case PIN_CONFIG_SLEW_RATE:
- regmap_field_read(pin->pad[RP1_PAD_SLEWFAST], &padctrl);
- arg = !!padctrl;
+ arg = !!(padctrl & RP1_PAD_SLEWFAST_MASK);
break;
case PIN_CONFIG_DRIVE_STRENGTH:
- regmap_field_read(pin->pad[RP1_PAD_DRIVE], &padctrl);
- switch (padctrl) {
+ switch (padctrl & RP1_PAD_DRIVE_MASK) {
case RP1_PAD_DRIVE_2MA:
arg = 2;
break;
@@ -1529,17 +1338,17 @@ static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned int offset,
}
break;
case PIN_CONFIG_BIAS_DISABLE:
- regmap_field_read(pin->pad[RP1_PAD_PULL], &padctrl);
- arg = ((padctrl == RP1_PUD_OFF));
+ arg = ((padctrl & RP1_PAD_PULL_MASK) ==
+ (RP1_PUD_OFF << RP1_PAD_PULL_LSB));
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
- regmap_field_read(pin->pad[RP1_PAD_PULL], &padctrl);
- arg = ((padctrl == RP1_PUD_DOWN));
+ arg = ((padctrl & RP1_PAD_PULL_MASK) ==
+ (RP1_PUD_DOWN << RP1_PAD_PULL_LSB));
break;
case PIN_CONFIG_BIAS_PULL_UP:
- regmap_field_read(pin->pad[RP1_PAD_PULL], &padctrl);
- arg = ((padctrl == RP1_PUD_UP));
+ arg = ((padctrl & RP1_PAD_PULL_MASK) ==
+ (RP1_PUD_UP << RP1_PAD_PULL_LSB));
break;
default:
return -ENOTSUPP;
@@ -1550,51 +1359,10 @@ static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned int offset,
return 0;
}
-static int rp1_pinconf_group_get(struct pinctrl_dev *pctldev, unsigned int selector,
- unsigned long *config)
-{
- const unsigned int *pins;
- unsigned int npins;
- int ret;
-
- ret = rp1_pctl_get_group_pins(pctldev, selector, &pins, &npins);
- if (ret < 0)
- return ret;
-
- if (!npins)
- return -ENODEV;
-
- ret = rp1_pinconf_get(pctldev, pins[0], config);
-
- return ret;
-}
-
-static int rp1_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned int selector,
- unsigned long *configs, unsigned int num_configs)
-{
- const unsigned int *pins;
- unsigned int npins;
- int ret, i;
-
- ret = rp1_pctl_get_group_pins(pctldev, selector, &pins, &npins);
- if (ret < 0)
- return ret;
-
- for (i = 0; i < npins; i++) {
- ret = rp1_pinconf_set(pctldev, pins[i], configs, num_configs);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
static const struct pinconf_ops rp1_pinconf_ops = {
.is_generic = true,
.pin_config_get = rp1_pinconf_get,
.pin_config_set = rp1_pinconf_set,
- .pin_config_group_get = rp1_pinconf_group_get,
- .pin_config_group_set = rp1_pinconf_group_set,
};
static struct pinctrl_desc rp1_pinctrl_desc = {
@@ -1617,169 +1385,97 @@ static const struct of_device_id rp1_pinctrl_match[] = {
.compatible = "raspberrypi,rp1-gpio",
.data = &rp1_pinconf_ops,
},
- {},
-};
-MODULE_DEVICE_TABLE(of, rp1_pinctrl_match);
-
-static struct rp1_pinctrl rp1_pinctrl_data = {};
-
-static const struct regmap_range rp1_gpio_reg_ranges[] = {
- /* BANK 0 */
- regmap_reg_range(0x2004, 0x20dc),
- regmap_reg_range(0x3004, 0x30dc),
- regmap_reg_range(0x0004, 0x00dc),
- regmap_reg_range(0x0124, 0x0124),
- regmap_reg_range(0x211c, 0x211c),
- regmap_reg_range(0x311c, 0x311c),
- /* BANK 1 */
- regmap_reg_range(0x6004, 0x602c),
- regmap_reg_range(0x7004, 0x702c),
- regmap_reg_range(0x4004, 0x402c),
- regmap_reg_range(0x4124, 0x4124),
- regmap_reg_range(0x611c, 0x611c),
- regmap_reg_range(0x711c, 0x711c),
- /* BANK 2 */
- regmap_reg_range(0xa004, 0xa09c),
- regmap_reg_range(0xb004, 0xb09c),
- regmap_reg_range(0x8004, 0x809c),
- regmap_reg_range(0x8124, 0x8124),
- regmap_reg_range(0xa11c, 0xa11c),
- regmap_reg_range(0xb11c, 0xb11c),
+ {}
};
-static const struct regmap_range rp1_rio_reg_ranges[] = {
- /* BANK 0 */
- regmap_reg_range(0x2000, 0x2004),
- regmap_reg_range(0x3000, 0x3004),
- regmap_reg_range(0x0004, 0x0008),
- /* BANK 1 */
- regmap_reg_range(0x6000, 0x6004),
- regmap_reg_range(0x7000, 0x7004),
- regmap_reg_range(0x4004, 0x4008),
- /* BANK 2 */
- regmap_reg_range(0xa000, 0xa004),
- regmap_reg_range(0xb000, 0xb004),
- regmap_reg_range(0x8004, 0x8008),
-};
-
-static const struct regmap_range rp1_pads_reg_ranges[] = {
- /* BANK 0 */
- regmap_reg_range(0x0004, 0x0070),
- /* BANK 1 */
- regmap_reg_range(0x4004, 0x4018),
- /* BANK 2 */
- regmap_reg_range(0x8004, 0x8050),
-};
-
-static const struct regmap_access_table rp1_gpio_reg_table = {
- .yes_ranges = rp1_gpio_reg_ranges,
- .n_yes_ranges = ARRAY_SIZE(rp1_gpio_reg_ranges),
-};
-
-static const struct regmap_access_table rp1_rio_reg_table = {
- .yes_ranges = rp1_rio_reg_ranges,
- .n_yes_ranges = ARRAY_SIZE(rp1_rio_reg_ranges),
-};
-
-static const struct regmap_access_table rp1_pads_reg_table = {
- .yes_ranges = rp1_pads_reg_ranges,
- .n_yes_ranges = ARRAY_SIZE(rp1_pads_reg_ranges),
-};
-
-static const struct regmap_config rp1_pinctrl_gpio_regmap_cfg = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = 4,
- .rd_table = &rp1_gpio_reg_table,
- .name = "rp1-gpio",
- .max_register = 0xb11c,
-};
-
-static const struct regmap_config rp1_pinctrl_rio_regmap_cfg = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = 4,
- .rd_table = &rp1_rio_reg_table,
- .name = "rp1-rio",
- .max_register = 0xb004,
-};
-
-static const struct regmap_config rp1_pinctrl_pads_regmap_cfg = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_stride = 4,
- .rd_table = &rp1_pads_reg_table,
- .name = "rp1-pads",
- .max_register = 0x8050,
-};
-
-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[])
+static inline void __iomem *devm_auto_iomap(struct platform_device *pdev,
+ unsigned int index)
{
- 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]);
- }
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
- return 0;
+ if (np)
+ return devm_of_iomap(dev, np, (int)index, NULL);
+ else
+ return devm_platform_ioremap_resource(pdev, index);
}
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 device_node *rp1_node = NULL;
+ struct rp1_pinctrl *pc;
struct gpio_irq_chip *girq;
int err, i;
- pc->dev = dev;
- pc->gpio_chip = rp1_gpio_chip;
- pc->gpio_chip.parent = dev;
+ BUILD_BUG_ON(ARRAY_SIZE(rp1_gpio_pins) != RP1_NUM_GPIOS);
+ BUILD_BUG_ON(ARRAY_SIZE(rp1_gpio_groups) != RP1_NUM_GPIOS);
- 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 = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
+ if (!pc)
+ return -ENOMEM;
- 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");
+ platform_set_drvdata(pdev, pc);
+ pc->dev = dev;
- 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");
+ pc->gpio_base = devm_auto_iomap(pdev, 0);
+ if (IS_ERR(pc->gpio_base)) {
+ dev_err(dev, "could not get GPIO IO memory\n");
+ return PTR_ERR(pc->gpio_base);
+ }
- gpio_regmap = devm_regmap_init_mmio(dev, pc->gpio_base,
- &rp1_pinctrl_gpio_regmap_cfg);
- if (IS_ERR(gpio_regmap))
- return dev_err_probe(dev, PTR_ERR(gpio_regmap), "could not init GPIO regmap\n");
+ pc->rio_base = devm_auto_iomap(pdev, 1);
+ if (IS_ERR(pc->rio_base)) {
+ dev_err(dev, "could not get RIO IO memory\n");
+ return PTR_ERR(pc->rio_base);
+ }
- rio_regmap = devm_regmap_init_mmio(dev, pc->rio_base,
- &rp1_pinctrl_rio_regmap_cfg);
- if (IS_ERR(rio_regmap))
- return dev_err_probe(dev, PTR_ERR(rio_regmap), "could not init RIO regmap\n");
+ pc->pads_base = devm_auto_iomap(pdev, 2);
+ if (IS_ERR(pc->pads_base)) {
+ dev_err(dev, "could not get PADS IO memory\n");
+ return PTR_ERR(pc->pads_base);
+ }
- pads_regmap = devm_regmap_init_mmio(dev, pc->pads_base,
- &rp1_pinctrl_pads_regmap_cfg);
- if (IS_ERR(pads_regmap))
- return dev_err_probe(dev, PTR_ERR(pads_regmap), "could not init PADS regmap\n");
+ pc->gpio_chip = rp1_gpio_chip;
+ pc->gpio_chip.parent = dev;
+
+ /*
+ * Workaround for the vagaries of PCIe on BCM2712
+ *
+ * If the link to RP1 is in L1, then the BRCMSTB RC will buffer many
+ * outbound writes - and generate write responses for them, despite the
+ * fact that the link is not yet active. This has the effect of compressing
+ * multiple writes to GPIOs together, destroying any pacing that an application
+ * may require in the 1-10us range.
+ *
+ * The RC Slot Control configuration register is special. It emits a
+ * MsgD for every write to it, will stall further writes until the message
+ * goes out on the wire. This can be (ab)used to force CPU stalls when the
+ * link is inactive, at the cost of a small amount of downstream bandwidth
+ * and some 200ns of added latency for each write.
+ *
+ * Several back-to-back configuration writes are necessary to "fill the pipe",
+ * otherwise the outbound MAC can consume a pending MMIO write and reorder
+ * it with respect to the config writes - undoing the intent.
+ *
+ * of_iomap() is used directly here as the address overlaps with the RC driver's
+ * usage.
+ */
+ rp1_node = of_find_node_by_name(NULL, "rp1");
+ if (!rp1_node)
+ dev_err(&pdev->dev, "failed to find RP1 DT node\n");
+ else if (pace_pin_updates &&
+ of_device_is_compatible(rp1_node->parent,
+ "brcm,bcm2712-pcie")) {
+ pc->dummy_base = of_iomap(rp1_node->parent, 0);
+ if (IS_ERR(pc->dummy_base)) {
+ dev_warn(
+ &pdev->dev,
+ "could not map bcm2712 root complex registers\n");
+ pc->dummy_base = NULL;
+ }
+ }
for (i = 0; i < RP1_NUM_BANKS; i++) {
const struct rp1_iobank_desc *bank = &rp1_iobanks[i];
@@ -1788,85 +1484,36 @@ static int rp1_pinctrl_probe(struct platform_device *pdev)
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");
+ pin->gpio = pc->gpio_base + bank->gpio_offset +
+ j * sizeof(u32) * 2;
+ pin->inte = pc->gpio_base + bank->inte_offset;
+ pin->ints = pc->gpio_base + bank->ints_offset;
+ pin->rio = pc->rio_base + bank->rio_offset;
+ pin->pad = pc->pads_base + bank->pads_offset +
+ j * sizeof(u32);
+ pin->dummy = pc->dummy_base ? pc->dummy_base + 0xc0 :
+ NULL;
}
raw_spin_lock_init(&pc->irq_lock[i]);
}
pc->pctl_dev = devm_pinctrl_register(dev, &rp1_pinctrl_desc, pc);
- if (IS_ERR(pc->pctl_dev))
- return dev_err_probe(dev, PTR_ERR(pc->pctl_dev),
- "Could not register pin controller\n");
+ if (IS_ERR(pc->pctl_dev)) {
+ err = PTR_ERR(pc->pctl_dev);
+ goto out_iounmap;
+ }
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
@@ -1883,11 +1530,14 @@ static int rp1_pinctrl_probe(struct platform_device *pdev)
}
}
- platform_set_drvdata(pdev, pc);
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_level_irq;
err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
- if (err)
- return dev_err_probe(dev, err, "could not add GPIO chip\n");
+ if (err) {
+ dev_err(dev, "could not add GPIO chip\n");
+ goto out_iounmap;
+ }
pc->gpio_range = rp1_pinctrl_gpio_range;
pc->gpio_range.base = pc->gpio_chip.base;
@@ -1895,10 +1545,24 @@ static int rp1_pinctrl_probe(struct platform_device *pdev)
pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
return 0;
+
+out_iounmap:
+ if (pc->dummy_base)
+ iounmap(pc->dummy_base);
+ return err;
+}
+
+static void rp1_pinctrl_remove(struct platform_device *pdev)
+{
+ struct rp1_pinctrl *pc = platform_get_drvdata(pdev);
+
+ if (pc->dummy_base)
+ iounmap(pc->dummy_base);
}
static struct platform_driver rp1_pinctrl_driver = {
.probe = rp1_pinctrl_probe,
+ .remove = rp1_pinctrl_remove,
.driver = {
.name = MODULE_NAME,
.of_match_table = rp1_pinctrl_match,