diff --git a/arch/arm64/boot/dts/broadcom/rp1-common.dtsi b/arch/arm64/boot/dts/broadcom/rp1-common.dtsi new file mode 100644 index 00000000000000..5002a375eb0b2d --- /dev/null +++ b/arch/arm64/boot/dts/broadcom/rp1-common.dtsi @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +#include +#include +#include + +pci_ep_bus: pci-ep-bus@1 { + compatible = "simple-bus"; + ranges = <0x00 0x40000000 0x01 0x00 0x00000000 0x00 0x00400000>; + dma-ranges = <0x10 0x00000000 0x43000000 0x10 0x00000000 0x10 0x00000000>; + #address-cells = <2>; + #size-cells = <2>; + + rp1_clocks: clocks@40018000 { + compatible = "raspberrypi,rp1-clocks"; + reg = <0x00 0x40018000 0x0 0x10038>; + #clock-cells = <1>; + clocks = <&clk_rp1_xosc>; + assigned-clocks = <&rp1_clocks RP1_PLL_SYS_CORE>, + <&rp1_clocks RP1_PLL_SYS>, + <&rp1_clocks RP1_PLL_SYS_SEC>, + <&rp1_clocks RP1_CLK_SYS>; + assigned-clock-rates = <1000000000>, // RP1_PLL_SYS_CORE + <200000000>, // RP1_PLL_SYS + <125000000>, // RP1_PLL_SYS_SEC + <200000000>; // RP1_CLK_SYS + }; + + rp1_gpio: pinctrl@400d0000 { + compatible = "raspberrypi,rp1-gpio"; + reg = <0x00 0x400d0000 0x0 0xc000>, + <0x00 0x400e0000 0x0 0xc000>, + <0x00 0x400f0000 0x0 0xc000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>, + <1 IRQ_TYPE_LEVEL_HIGH>, + <2 IRQ_TYPE_LEVEL_HIGH>; + }; +}; diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index f67484bff8a53f..bbfc0dfafe48ba 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -653,6 +653,11 @@ hdmi_compute_config(const struct drm_connector *connector, ret = hdmi_compute_format_bpc(connector, conn_state, mode, max_bpc, HDMI_COLORSPACE_RGB); + + if (ret) + ret = hdmi_compute_format_bpc(connector, conn_state, mode, + max_bpc, HDMI_COLORSPACE_YUV422); + if (ret) { if (connector->ycbcr_420_allowed) { ret = hdmi_compute_format_bpc(connector, conn_state, diff --git a/drivers/pinctrl/pinctrl-rp1.c b/drivers/pinctrl/pinctrl-rp1.c index dadafc935dbb28..16320049b5c55e 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,15 +8,31 @@ * pinctrl-bcm2835.c, please see original file for copyright information */ +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include +#include +#include #include +#include #include +#include #include #include -#include - -#include "pinmux.h" +#include +#include +#include "core.h" #include "pinconf.h" #include "pinctrl-utils.h" @@ -24,13 +40,60 @@ #define RP1_NUM_GPIOS 54 #define RP1_NUM_BANKS 3 +#define RP1_RW_OFFSET 0x0000 +#define RP1_XOR_OFFSET 0x1000 +#define RP1_SET_OFFSET 0x2000 +#define RP1_CLR_OFFSET 0x3000 + +#define RP1_GPIO_STATUS 0x0000 +#define RP1_GPIO_CTRL 0x0004 + +#define RP1_GPIO_PCIE_INTE 0x011c +#define RP1_GPIO_PCIE_INTS 0x0124 + +#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) + +#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) + +#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 + #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_MASK 0xf + #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 #define RP1_FSEL_COUNT 9 @@ -39,108 +102,48 @@ #define RP1_FSEL_NONE 0x09 #define RP1_FSEL_NONE_HW 0x1f -#define RP1_PAD_DRIVE_2MA 0x0 -#define RP1_PAD_DRIVE_4MA 0x1 -#define RP1_PAD_DRIVE_8MA 0x2 -#define RP1_PAD_DRIVE_12MA 0x3 - -enum { - RP1_PUD_OFF = 0, - RP1_PUD_DOWN = 1, - RP1_PUD_UP = 2, -}; - -enum { - RP1_DIR_OUTPUT = 0, - RP1_DIR_INPUT = 1, -}; - -enum { - RP1_OUTOVER_PERI = 0, - RP1_OUTOVER_INVPERI = 1, - RP1_OUTOVER_LOW = 2, - RP1_OUTOVER_HIGH = 3, -}; - -enum { - RP1_OEOVER_PERI = 0, - RP1_OEOVER_INVPERI = 1, - RP1_OEOVER_DISABLE = 2, - RP1_OEOVER_ENABLE = 3, -}; - -enum { - RP1_INOVER_PERI = 0, - RP1_INOVER_INVPERI = 1, - RP1_INOVER_LOW = 2, - RP1_INOVER_HIGH = 3, -}; - -enum { - RP1_GPIO_CTRL_IRQRESET_SET = 0, - RP1_GPIO_CTRL_INT_CLR = 1, - RP1_GPIO_CTRL_INT_SET = 2, - RP1_GPIO_CTRL_OEOVER = 3, - RP1_GPIO_CTRL_FUNCSEL = 4, - RP1_GPIO_CTRL_OUTOVER = 5, - RP1_GPIO_CTRL = 6, -}; - -enum { - RP1_INTE_SET = 0, - RP1_INTE_CLR = 1, -}; - -enum { - RP1_RIO_OUT_SET = 0, - RP1_RIO_OUT_CLR = 1, - RP1_RIO_OE = 2, - RP1_RIO_OE_SET = 3, - RP1_RIO_OE_CLR = 4, - RP1_RIO_IN = 5, -}; - -enum { - RP1_PAD_SLEWFAST = 0, - RP1_PAD_SCHMITT = 1, - RP1_PAD_PULL = 2, - RP1_PAD_DRIVE = 3, - RP1_PAD_IN_ENABLE = 4, - RP1_PAD_OUT_DISABLE = 5, -}; - -static const struct reg_field rp1_gpio_fields[] = { - [RP1_GPIO_CTRL_IRQRESET_SET] = REG_FIELD(0x2004, 28, 28), - [RP1_GPIO_CTRL_INT_CLR] = REG_FIELD(0x3004, 20, 23), - [RP1_GPIO_CTRL_INT_SET] = REG_FIELD(0x2004, 20, 23), - [RP1_GPIO_CTRL_OEOVER] = REG_FIELD(0x0004, 14, 15), - [RP1_GPIO_CTRL_FUNCSEL] = REG_FIELD(0x0004, 0, 4), - [RP1_GPIO_CTRL_OUTOVER] = REG_FIELD(0x0004, 12, 13), - [RP1_GPIO_CTRL] = REG_FIELD(0x0004, 0, 31), -}; - -static const struct reg_field rp1_inte_fields[] = { - [RP1_INTE_SET] = REG_FIELD(0x2000, 0, 0), - [RP1_INTE_CLR] = REG_FIELD(0x3000, 0, 0), -}; - -static const struct reg_field rp1_rio_fields[] = { - [RP1_RIO_OUT_SET] = REG_FIELD(0x2000, 0, 0), - [RP1_RIO_OUT_CLR] = REG_FIELD(0x3000, 0, 0), - [RP1_RIO_OE] = REG_FIELD(0x0004, 0, 0), - [RP1_RIO_OE_SET] = REG_FIELD(0x2004, 0, 0), - [RP1_RIO_OE_CLR] = REG_FIELD(0x3004, 0, 0), - [RP1_RIO_IN] = REG_FIELD(0x0008, 0, 0), -}; - -static const struct reg_field rp1_pad_fields[] = { - [RP1_PAD_SLEWFAST] = REG_FIELD(0, 0, 0), - [RP1_PAD_SCHMITT] = REG_FIELD(0, 1, 1), - [RP1_PAD_PULL] = REG_FIELD(0, 2, 3), - [RP1_PAD_DRIVE] = REG_FIELD(0, 4, 5), - [RP1_PAD_IN_ENABLE] = REG_FIELD(0, 6, 6), - [RP1_PAD_OUT_DISABLE] = REG_FIELD(0, 7, 7), -}; +#define RP1_DIR_OUTPUT 0 +#define RP1_DIR_INPUT 1 + +#define RP1_OUTOVER_PERI 0 +#define RP1_OUTOVER_INVPERI 1 +#define RP1_OUTOVER_LOW 2 +#define RP1_OUTOVER_HIGH 3 + +#define RP1_OEOVER_PERI 0 +#define RP1_OEOVER_INVPERI 1 +#define RP1_OEOVER_DISABLE 2 +#define RP1_OEOVER_ENABLE 3 + +#define RP1_INOVER_PERI 0 +#define RP1_INOVER_INVPERI 1 +#define RP1_INOVER_LOW 2 +#define RP1_INOVER_HIGH 3 + +#define RP1_RIO_OUT 0x00 +#define RP1_RIO_OE 0x04 +#define RP1_RIO_IN 0x08 + +#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 + +#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 @@ -172,6 +175,31 @@ static const struct reg_field rp1_pad_fields[] = { 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 +212,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 +241,7 @@ enum funcs { func_proc_rio, func_pwm0, func_pwm1, + func_ri0, func_sd0, func_sd1, func_spi0, @@ -240,34 +272,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,6 +288,13 @@ 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[] = { @@ -337,227 +354,128 @@ static struct pinctrl_pin_desc rp1_gpio_pins[] = { 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 +483,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), @@ -661,12 +579,41 @@ 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"); -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; + + 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, @@ -692,22 +639,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 +675,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 +684,52 @@ 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 +746,15 @@ 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; } -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 +762,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,18 +775,17 @@ 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, - ARRAY_SIZE(configs)); + ARRAY_SIZE(configs)); } static const struct gpio_chip rp1_gpio_chip = { @@ -861,12 +807,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 +824,13 @@ 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 +838,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 +858,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 +892,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 +909,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,11 +934,11 @@ 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) @@ -1023,26 +974,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 +999,19 @@ 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) + unsigned offset) { struct rp1_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); struct gpio_chip *chip = &pc->gpio_chip; @@ -1084,13 +1022,13 @@ 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, + 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; @@ -1124,11 +1062,14 @@ static int rp1_pctl_legacy_map_func(struct rp1_pinctrl *pc, 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; @@ -1254,7 +1195,7 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, } else if (function) { err = pinctrl_utils_add_map_mux(pctldev, &maps, &reserved_maps, num_maps, - rp1_gpio_groups[pin].name, + rp1_gpio_groups[pin], function); } @@ -1272,7 +1213,7 @@ static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, } else if (num_configs) { err = pinctrl_utils_add_map_configs(pctldev, &maps, &reserved_maps, num_maps, - rp1_gpio_groups[pin].name, + rp1_gpio_groups[pin], configs, num_configs, PIN_MAP_TYPE_CONFIGS_PIN); } @@ -1299,7 +1240,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,66 +1261,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, + 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; - - rp1_pctl_get_group_pins(pctldev, group_selector, &pins, &num_pins); - - 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; - } + int fsel; - if (fsel >= RP1_FSEL_COUNT && fsel != RP1_FSEL_NONE) - return -EINVAL; + /* func_selector is an enum funcs, so needs translation */ - rp1_set_fsel(pin, fsel); + 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; + + 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, + unsigned offset, bool input) { struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); @@ -1402,9 +1338,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 +1389,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 +1415,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 +1427,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 +1438,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 +1470,14 @@ 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 +1488,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,87 +1514,94 @@ 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_config rp1_pinctrl_regmap_cfg = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .fast_io = true, - .name = "rp1-pinctrl", -}; - -static int rp1_gen_regfield(struct device *dev, - const struct reg_field *array, - size_t array_size, - int reg_off, - int pin_off, - bool additive_offset, - struct regmap *regmap, - struct regmap_field *out[]) +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 = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); + if (!pc) + return -ENOMEM; - 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"); + platform_set_drvdata(pdev, pc); + pc->dev = dev; - pc->rio_base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(pc->rio_base)) - return dev_err_probe(dev, PTR_ERR(pc->rio_base), "could not get RIO IO memory\n"); + pc->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); + } - 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->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); + } - gpio_regmap = devm_regmap_init_mmio(dev, pc->gpio_base, - &rp1_pinctrl_regmap_cfg); - if (IS_ERR(gpio_regmap)) - return dev_err_probe(dev, PTR_ERR(gpio_regmap), "could not init GPIO regmap\n"); + 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); + } - rio_regmap = devm_regmap_init_mmio(dev, pc->rio_base, - &rp1_pinctrl_regmap_cfg); - if (IS_ERR(rio_regmap)) - return dev_err_probe(dev, PTR_ERR(rio_regmap), "could not init RIO regmap\n"); + pc->gpio_chip = rp1_gpio_chip; + pc->gpio_chip.parent = dev; - pads_regmap = devm_regmap_init_mmio(dev, pc->pads_base, - &rp1_pinctrl_regmap_cfg); - if (IS_ERR(pads_regmap)) - return dev_err_probe(dev, PTR_ERR(pads_regmap), "could not init PADS regmap\n"); + /* + * 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]; @@ -1706,85 +1610,35 @@ 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 @@ -1801,11 +1655,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; @@ -1813,19 +1670,28 @@ 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, .suppress_bind_attrs = true, }, }; -module_platform_driver(rp1_pinctrl_driver); - -MODULE_AUTHOR("Phil Elwell "); -MODULE_AUTHOR("Andrea della Porta "); -MODULE_DESCRIPTION("RP1 pinctrl/gpio driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(rp1_pinctrl_driver); diff --git a/drivers/power/supply/rpi_poe_power.c b/drivers/power/supply/rpi_poe_power.c index 4f9f5b58916761..80f59fc8266cfb 100644 --- a/drivers/power/supply/rpi_poe_power.c +++ b/drivers/power/supply/rpi_poe_power.c @@ -186,13 +186,13 @@ static int rpi_poe_power_supply_probe(struct platform_device *pdev) if (device_property_read_u32(&pdev->dev, "reg", &ctx->offset)) return -EINVAL; } else { - fw_node = NULL; // hack xxx fwnode_find_reference(pdev->dev.fwnode, "firmware", 0); + fw_node = of_find_compatible_node(NULL, NULL, "raspberrypi,bcm2835-firmware"); if (!fw_node) { dev_err(&pdev->dev, "Missing firmware node\n"); return -ENOENT; } - ctx->fw = NULL; // hack xxx rpi_firmware_get(fw_node); + ctx->fw = rpi_firmware_get(fw_node); if (!ctx->fw) return -EPROBE_DEFER; if (rpi_firmware_property(ctx->fw,