diff options
Diffstat (limited to 'drivers/pinctrl')
| -rw-r--r-- | drivers/pinctrl/bcm/pinctrl-bcm2835.c | 27 | ||||
| -rw-r--r-- | drivers/pinctrl/pinctrl-rp1.c | 1380 |
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, |
