diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-16 09:35:24 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-16 09:35:24 -0800 |
| commit | 46a1daac56b3bf1bdbd8b37e6db811f015bc1f4b (patch) | |
| tree | 5143225e474619cd153c28dc9e68ff8e41b91c47 | |
| parent | 6086f349a30232f3119ec647356cd191087b1333 (diff) | |
| parent | 9c5a40f2922a5a6d6b42e7b3d4c8e253918c07a1 (diff) | |
Merge tag 'pinctrl-v7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control updates from Linus Walleij:
"Core changes:
- Drop the unused devm_pinctrl_unregister() function
- Move pretended generic pin control functionality out of the core
and into the Amlogic AM4 driver. We have something better coming
(hopefully)
New hardware support:
- Spacemit K3 (RISC-V) pin control support
- Atmel AT91 PIO4 (ARM32) SAMA7D65 pin control support
- Exynos9610 (ARM64) pin control support
- Qualcomm Mahua TLMM (ARM64) pin control support
- Microchip Polarfire MSSIO (RISC-V) pin control support
- Ocelot LAN9645XF (multiplatform) pin control support
Improvements:
- Using a few more guards for locking
- Various nonurgent fixes and tweaks"
* tag 'pinctrl-v7.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (73 commits)
pinctrl: generic: move function to amlogic-am4 driver
pinctrl: intel: Align Copyright note with corporate guidelines
pinctrl: mediatek: remove unused drv_offset field
pinctrl: canaan: k230: Fix NULL pointer dereference when parsing devicetree
pinctrl: single: fix refcount leak in pcs_add_gpio_func()
pinctrl: meson: amlogic-a4: Fix device node reference leak in bank helpers
pinctrl: qcom: sm8250-lpass-lpi: Fix i2s2_data_groups definition
pinctrl: core: Remove duplicate error messages
pinctrl: core: Simplify devm_pinctrl_*()
pinctrl: core: Remove unused devm_pinctrl_unregister()
dt-bindings: pinctrl: spacemit: fix drive-strength check warning
pinctrl: fix kismet issues with GENERIC_PINCTRL
pinctrl: tangier: Join tng_pinctrl_probe() into its wrapper
pinctrl: tangier: Remove duplicate error messages
pinctrl: lynxpoint: Remove duplicate error messages
pinctrl: cherryview: Remove duplicate error messages
pinctrl: baytrail: Remove duplicate error messages
pinctrl: intel: Remove duplicate error messages
pinctrl: equilibrium: Fix device node reference leak in pinbank_init()
dt-bindings: pinctrl: pinctrl-microchip-sgpio: add LAN969x
...
93 files changed, 2671 insertions, 497 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml index 990b78765427..45b7a0b6c626 100644 --- a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml @@ -106,7 +106,7 @@ patternProperties: # the pin numbers then, # - Finally, the name will end with either -pin or pins. - "^([rs]-)?(([a-z0-9]{3,}|[a-oq-z][a-z0-9]*?)?-)+?(p[a-ilm][0-9]*?-)??pins?$": + "^([rs]-)?(([a-z0-9]{3,}|[a-oq-z0-9][a-z0-9]*?)?-)+?(p[a-ilm][0-9]*?-)??pins?$": type: object properties: diff --git a/Documentation/devicetree/bindings/pinctrl/intel,pinctrl-keembay.yaml b/Documentation/devicetree/bindings/pinctrl/intel,pinctrl-keembay.yaml index 005d95a9e4d6..ec9848192351 100644 --- a/Documentation/devicetree/bindings/pinctrl/intel,pinctrl-keembay.yaml +++ b/Documentation/devicetree/bindings/pinctrl/intel,pinctrl-keembay.yaml @@ -33,7 +33,7 @@ properties: interrupts: description: Specifies the interrupt lines to be used by the controller. - Each interrupt line is shared by upto 4 GPIO lines. + Each interrupt line is shared by up to 4 GPIO lines. maxItems: 8 interrupt-controller: true diff --git a/Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-mssio.yaml b/Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-mssio.yaml new file mode 100644 index 000000000000..fe05196160f4 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-mssio.yaml @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/microchip,mpfs-pinctrl-mssio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip Polarfire SoC MSSIO pinctrl + +maintainers: + - Conor Dooley <conor.dooley@microchip.com> + +properties: + compatible: + oneOf: + - const: microchip,mpfs-pinctrl-mssio + - items: + - const: microchip,pic64gx-pinctrl-mssio + - const: microchip,mpfs-pinctrl-mssio + + reg: + maxItems: 1 + + pinctrl-use-default: true + +patternProperties: + '-cfg$': + type: object + additionalProperties: false + + patternProperties: + '-pins$': + type: object + additionalProperties: false + + allOf: + - $ref: pincfg-node.yaml# + - $ref: pinmux-node.yaml# + + properties: + pins: + description: + The list of IOs that properties in the pincfg node apply to. + + function: + description: + A string containing the name of the function to mux for these + pins. The "reserved" function tristates a pin. + enum: [ sd, emmc, qspi, spi, usb, uart, i2c, can, mdio, misc + reserved, gpio, fabric-test, tied-low, tied-high, tristate ] + + bias-bus-hold: true + bias-disable: true + bias-pull-down: true + bias-pull-up: true + input-schmitt-enable: true + low-power-enable: true + + drive-strength: + enum: [ 2, 4, 6, 8, 10, 12, 16, 20 ] + + power-source: + description: + Which bank voltage to use. This cannot differ for pins in a + given bank, the whole bank uses the same voltage. + enum: [ 1200000, 1500000, 1800000, 2500000, 3300000 ] + + microchip,clamp-diode: + $ref: /schemas/types.yaml#/definitions/flag + description: + Reflects the "Clamp Diode" setting in the MSS Configurator for + this pin. This setting controls whether or not input voltage + clamping should be enabled. + + microchip,ibufmd: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + description: + Reflects the "IBUFMD" bits in the MSS Configurator output files + for this pin. + + required: + - pins + - function + - power-source + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + pinctrl@204 { + compatible = "microchip,mpfs-pinctrl-mssio"; + reg = <0x204 0x7c>; + + ikrd-spi1-cfg { + spi1-pins { + pins = <30>, <31>, <32>, <33>; + function = "spi"; + bias-pull-up; + drive-strength = <8>; + power-source = <3300000>; + microchip,ibufmd = <0x1>; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/pinctrl/microchip,sparx5-sgpio.yaml b/Documentation/devicetree/bindings/pinctrl/microchip,sparx5-sgpio.yaml index fa47732d7cef..9fbbafcdc063 100644 --- a/Documentation/devicetree/bindings/pinctrl/microchip,sparx5-sgpio.yaml +++ b/Documentation/devicetree/bindings/pinctrl/microchip,sparx5-sgpio.yaml @@ -21,10 +21,15 @@ properties: pattern: '^gpio@[0-9a-f]+$' compatible: - enum: - - microchip,sparx5-sgpio - - mscc,ocelot-sgpio - - mscc,luton-sgpio + oneOf: + - enum: + - microchip,sparx5-sgpio + - mscc,ocelot-sgpio + - mscc,luton-sgpio + - items: + - enum: + - microchip,lan9691-sgpio + - const: microchip,sparx5-sgpio '#address-cells': const: 1 @@ -80,7 +85,12 @@ patternProperties: type: object properties: compatible: - const: microchip,sparx5-sgpio-bank + oneOf: + - items: + - enum: + - microchip,lan9691-sgpio-bank + - const: microchip,sparx5-sgpio-bank + - const: microchip,sparx5-sgpio-bank reg: description: | diff --git a/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml index 31bc30a81752..930955caacd1 100644 --- a/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml @@ -14,6 +14,7 @@ properties: compatible: oneOf: - enum: + - microchip,lan96455f-pinctrl - microchip,lan966x-pinctrl - microchip,lan9691-pinctrl - microchip,sparx5-pinctrl @@ -30,6 +31,11 @@ properties: - microchip,lan9693-pinctrl - microchip,lan9692-pinctrl - const: microchip,lan9691-pinctrl + - items: + - enum: + - microchip,lan96457f-pinctrl + - microchip,lan96459f-pinctrl + - const: microchip,lan96455f-pinctrl reg: items: diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,glymur-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,glymur-tlmm.yaml index d2b0cfeffb50..2836a1a10579 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,glymur-tlmm.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,glymur-tlmm.yaml @@ -10,14 +10,16 @@ maintainers: - Bjorn Andersson <bjorn.andersson@oss.qualcomm.com> description: - Top Level Mode Multiplexer pin controller in Qualcomm Glymur SoC. + Top Level Mode Multiplexer pin controller in Qualcomm Glymur and Mahua SoC. allOf: - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml# properties: compatible: - const: qcom,glymur-tlmm + enum: + - qcom,glymur-tlmm + - qcom,mahua-tlmm reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,r9a09g077-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/renesas,r9a09g077-pinctrl.yaml index 36d665971484..f049013a4e0c 100644 --- a/Documentation/devicetree/bindings/pinctrl/renesas,r9a09g077-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/renesas,r9a09g077-pinctrl.yaml @@ -49,6 +49,17 @@ properties: gpio-ranges: maxItems: 1 + interrupt-controller: true + + '#interrupt-cells': + const: 2 + description: + The first cell contains the global GPIO port index, constructed using the + RZT2H_GPIO() helper macro from <dt-bindings/pinctrl/renesas,r9a09g077-pinctrl.h> + and the second cell is used to specify the flag. + E.g. "interrupts = <RZT2H_GPIO(8, 6) IRQ_TYPE_EDGE_FALLING>;" if P08_6 is + being used as an interrupt. + clocks: maxItems: 1 @@ -139,6 +150,8 @@ examples: gpio-controller; #gpio-cells = <2>; gpio-ranges = <&pinctrl 0 0 288>; + interrupt-controller; + #interrupt-cells = <2>; power-domains = <&cpg>; serial0-pins { diff --git a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml index f3c433015b12..2b88f25e80a6 100644 --- a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml +++ b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl-wakeup-interrupt.yaml @@ -48,6 +48,7 @@ properties: - enum: - google,gs101-wakeup-eint - samsung,exynos2200-wakeup-eint + - samsung,exynos9610-wakeup-eint - samsung,exynos9810-wakeup-eint - samsung,exynos990-wakeup-eint - samsung,exynosautov9-wakeup-eint diff --git a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml index ddc5e2efff21..7b006009ca0e 100644 --- a/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/samsung,pinctrl.yaml @@ -55,6 +55,7 @@ properties: - samsung,exynos850-pinctrl - samsung,exynos8890-pinctrl - samsung,exynos8895-pinctrl + - samsung,exynos9610-pinctrl - samsung,exynos9810-pinctrl - samsung,exynos990-pinctrl - samsung,exynosautov9-pinctrl diff --git a/Documentation/devicetree/bindings/pinctrl/spacemit,k1-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/spacemit,k1-pinctrl.yaml index d80e88aa07b4..3e734aeb01cc 100644 --- a/Documentation/devicetree/bindings/pinctrl/spacemit,k1-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/spacemit,k1-pinctrl.yaml @@ -11,7 +11,9 @@ maintainers: properties: compatible: - const: spacemit,k1-pinctrl + enum: + - spacemit,k1-pinctrl + - spacemit,k3-pinctrl reg: items: @@ -30,6 +32,10 @@ properties: resets: maxItems: 1 + spacemit,apbc: + $ref: /schemas/types.yaml#/definitions/phandle + description: Phandle to syscon that access the protected register + patternProperties: '-cfg$': type: object @@ -72,10 +78,20 @@ patternProperties: enum: [ 0, 1 ] drive-strength: - description: | - typical current when output high level. - 1.8V output: 11, 21, 32, 42 (mA) - 3.3V output: 7, 10, 13, 16, 19, 23, 26, 29 (mA) + description: + typical current (in mA) when the output at high level. + anyOf: + - enum: [ 11, 21, 32, 42 ] + description: For K1 SoC, 1.8V voltage output + + - enum: [ 7, 10, 13, 16, 19, 23, 26, 29 ] + description: For K1 SoC, 3.3V voltage output + + - enum: [ 2, 4, 6, 7, 9, 11, 13, 14, 21, 23, 25, 26, 28, 30, 31, 33 ] + description: For K3 SoC, 1.8V voltage output + + - enum: [ 3, 5, 7, 9, 11, 13, 15, 17, 25, 27, 29, 31, 33, 35, 37, 38 ] + description: For K3 SoC, 3.3V voltage output input-schmitt: description: | @@ -126,6 +142,7 @@ examples: clocks = <&syscon_apbc 42>, <&syscon_apbc 94>; clock-names = "func", "bus"; + spacemit,apbc = <&syscon_apbc>; uart0_2_cfg: uart0-2-cfg { uart0-2-pins { diff --git a/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml index 39987f722411..44e4a50c3155 100644 --- a/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml +++ b/Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-mss-top-sysreg.yaml @@ -42,6 +42,10 @@ properties: type: object $ref: /schemas/pinctrl/microchip,mpfs-pinctrl-iomux0.yaml + pinctrl@204: + type: object + $ref: /schemas/pinctrl/microchip,mpfs-pinctrl-mssio.yaml + required: - compatible - reg diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index 0198ac65e874..7d2b897d66fa 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -408,7 +408,6 @@ PINCTRL devm_pinctrl_get_select() devm_pinctrl_register() devm_pinctrl_register_and_init() - devm_pinctrl_unregister() POWER devm_reboot_mode_register() diff --git a/MAINTAINERS b/MAINTAINERS index 8cdb5449000d..8a307490a478 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22666,6 +22666,7 @@ F: Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml F: Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml F: Documentation/devicetree/bindings/net/can/microchip,mpfs-can.yaml F: Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-iomux0.yaml +F: Documentation/devicetree/bindings/pinctrl/microchip,mpfs-pinctrl-mssio.yaml F: Documentation/devicetree/bindings/pinctrl/microchip,pic64gx-pinctrl-gpio2.yaml F: Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml F: Documentation/devicetree/bindings/riscv/microchip.yaml @@ -22680,8 +22681,9 @@ F: drivers/gpio/gpio-mpfs.c F: drivers/i2c/busses/i2c-microchip-corei2c.c F: drivers/mailbox/mailbox-mpfs.c F: drivers/pci/controller/plda/pcie-microchip-host.c -F: drivers/pinctrl/pinctrl-mpfs-iomux0.c -F: drivers/pinctrl/pinctrl-pic64gx-gpio2.c +F: drivers/pinctrl/microchip/pinctrl-mpfs-iomux0.c +F: drivers/pinctrl/microchip/pinctrl-mpfs-mssio.c +F: drivers/pinctrl/microchip/pinctrl-pic64gx-gpio2.c F: drivers/pwm/pwm-microchip-core.c F: drivers/reset/reset-mpfs.c F: drivers/rtc/rtc-mpfs.c diff --git a/drivers/base/base.h b/drivers/base/base.h index 8c2175820da9..79d031d2d845 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -302,3 +302,12 @@ static inline int devtmpfs_delete_node(struct device *dev) { return 0; } void software_node_notify(struct device *dev); void software_node_notify_remove(struct device *dev); + +#ifdef CONFIG_PINCTRL +int pinctrl_bind_pins(struct device *dev); +#else +static inline int pinctrl_bind_pins(struct device *dev) +{ + return 0; +} +#endif /* CONFIG_PINCTRL */ diff --git a/drivers/base/pinctrl.c b/drivers/base/pinctrl.c index c22864458511..6e250272c843 100644 --- a/drivers/base/pinctrl.c +++ b/drivers/base/pinctrl.c @@ -14,6 +14,8 @@ #include <linux/pinctrl/consumer.h> #include <linux/slab.h> +#include "base.h" + /** * pinctrl_bind_pins() - called by the device core before probe * @dev: the device that is just about to probe diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 7b9f792acb0e..afecd9407f53 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -25,6 +25,12 @@ config GENERIC_PINCONF bool select PINCONF +config GENERIC_PINCTRL + bool + select GENERIC_PINCONF + select GENERIC_PINCTRL_GROUPS + select GENERIC_PINMUX_FUNCTIONS + config DEBUG_PINCTRL bool "Debug PINCTRL calls" depends on DEBUG_KERNEL @@ -486,16 +492,6 @@ config PINCTRL_PIC32MZDA def_bool y if PIC32MZDA select PINCTRL_PIC32 -config PINCTRL_PIC64GX - bool "pic64gx gpio2 pinctrl driver" - depends on ARCH_MICROCHIP || COMPILE_TEST - depends on OF - select GENERIC_PINCONF - select REGMAP_MMIO - default y - help - This selects the pinctrl driver for gpio2 on pic64gx. - config PINCTRL_PISTACHIO bool "IMG Pistachio SoC pinctrl driver" depends on OF && (MIPS || COMPILE_TEST) @@ -507,15 +503,6 @@ config PINCTRL_PISTACHIO help This support pinctrl and GPIO driver for IMG Pistachio SoC. -config PINCTRL_POLARFIRE_SOC - bool "Polarfire SoC pinctrl driver" - depends on ARCH_MICROCHIP || COMPILE_TEST - depends on OF - select GENERIC_PINCONF - default y - help - This selects the pinctrl driver for Microchip Polarfire SoC. - config PINCTRL_RK805 tristate "Pinctrl and GPIO driver for RK805 PMIC" depends on MFD_RK8XX @@ -710,6 +697,7 @@ source "drivers/pinctrl/freescale/Kconfig" source "drivers/pinctrl/intel/Kconfig" source "drivers/pinctrl/mediatek/Kconfig" source "drivers/pinctrl/meson/Kconfig" +source "drivers/pinctrl/microchip/Kconfig" source "drivers/pinctrl/mvebu/Kconfig" source "drivers/pinctrl/nomadik/Kconfig" source "drivers/pinctrl/nuvoton/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index be5200c23e60..f7d5d5f76d0c 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -7,6 +7,7 @@ obj-y += core.o pinctrl-utils.o obj-$(CONFIG_PINMUX) += pinmux.o obj-$(CONFIG_PINCONF) += pinconf.o obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o +obj-$(CONFIG_GENERIC_PINCTRL) += pinctrl-generic.o obj-$(CONFIG_OF) += devicetree.o obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o @@ -48,9 +49,7 @@ obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o obj-$(CONFIG_PINCTRL_PEF2256) += pinctrl-pef2256.o obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o -obj-$(CONFIG_PINCTRL_PIC64GX) += pinctrl-pic64gx-gpio2.o obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o -obj-$(CONFIG_PINCTRL_POLARFIRE_SOC) += pinctrl-mpfs-iomux0.o obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o obj-$(CONFIG_PINCTRL_RP1) += pinctrl-rp1.o @@ -76,6 +75,7 @@ obj-y += freescale/ obj-$(CONFIG_X86) += intel/ obj-y += mediatek/ obj-$(CONFIG_PINCTRL_MESON) += meson/ +obj-y += microchip/ obj-y += mvebu/ obj-y += nomadik/ obj-y += nuvoton/ diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c index cb295856dda1..f9d8fb1ab1ec 100644 --- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c @@ -6,14 +6,12 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/kernel.h> -#include <linux/mutex.h> -#include <linux/of.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinconf-generic.h> -#include <linux/string.h> #include <linux/types.h> #include "../core.h" diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c index 792089628362..50979787db5c 100644 --- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c @@ -7,14 +7,13 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/mfd/syscon.h> -#include <linux/mutex.h> +#include <linux/mod_devicetable.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinconf-generic.h> -#include <linux/string.h> #include <linux/types.h> #include "../core.h" @@ -2654,9 +2653,7 @@ static struct regmap *aspeed_g5_acquire_regmap(struct aspeed_pinmux_data *ctx, np = of_parse_phandle(ctx->dev->of_node, "aspeed,external-nodes", 1); if (np) { - if (!of_device_is_compatible(np->parent, "aspeed,ast2400-lpc-v2") && - !of_device_is_compatible(np->parent, "aspeed,ast2500-lpc-v2") && - !of_device_is_compatible(np->parent, "aspeed,ast2600-lpc-v2")) + if (!of_device_is_compatible(np->parent, "aspeed,ast2500-lpc-v2")) return ERR_PTR(-ENODEV); map = syscon_node_to_regmap(np->parent); diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c index b0c7e4f6df9c..8cf61aab81b1 100644 --- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c @@ -4,13 +4,10 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/kernel.h> -#include <linux/mfd/syscon.h> -#include <linux/mutex.h> -#include <linux/of.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> -#include <linux/string.h> #include <linux/types.h> #include "../core.h" diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 83254a95ef17..342bda2a1bd6 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1383,9 +1383,9 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state) } EXPORT_SYMBOL_GPL(pinctrl_select_state); -static void devm_pinctrl_release(struct device *dev, void *res) +static void devm_pinctrl_release(void *p) { - pinctrl_put(*(struct pinctrl **)res); + pinctrl_put(p); } /** @@ -1397,31 +1397,21 @@ static void devm_pinctrl_release(struct device *dev, void *res) */ struct pinctrl *devm_pinctrl_get(struct device *dev) { - struct pinctrl **ptr, *p; - - ptr = devres_alloc(devm_pinctrl_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct pinctrl *p; + int ret; p = pinctrl_get(dev); - if (!IS_ERR(p)) { - *ptr = p; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + if (IS_ERR(p)) + return p; + + ret = devm_add_action_or_reset(dev, devm_pinctrl_release, p); + if (ret) + return ERR_PTR(ret); return p; } EXPORT_SYMBOL_GPL(devm_pinctrl_get); -static int devm_pinctrl_match(struct device *dev, void *res, void *data) -{ - struct pinctrl **p = res; - - return *p == data; -} - /** * devm_pinctrl_put() - Resource managed pinctrl_put() * @p: the pinctrl handle to release @@ -1432,8 +1422,7 @@ static int devm_pinctrl_match(struct device *dev, void *res, void *data) */ void devm_pinctrl_put(struct pinctrl *p) { - WARN_ON(devres_release(p->dev, devm_pinctrl_release, - devm_pinctrl_match, p)); + devm_release_action(p->dev, devm_pinctrl_release, p); } EXPORT_SYMBOL_GPL(devm_pinctrl_put); @@ -2198,10 +2187,8 @@ int pinctrl_enable(struct pinctrl_dev *pctldev) int error; error = pinctrl_claim_hogs(pctldev); - if (error) { - dev_err(pctldev->dev, "could not claim hogs: %i\n", error); + if (error) return error; - } mutex_lock(&pinctrldev_list_mutex); list_add_tail(&pctldev->node, &pinctrldev_list); @@ -2316,23 +2303,11 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev) } EXPORT_SYMBOL_GPL(pinctrl_unregister); -static void devm_pinctrl_dev_release(struct device *dev, void *res) +static void devm_pinctrl_dev_release(void *pctldev) { - struct pinctrl_dev *pctldev = *(struct pinctrl_dev **)res; - pinctrl_unregister(pctldev); } -static int devm_pinctrl_dev_match(struct device *dev, void *res, void *data) -{ - struct pctldev **r = res; - - if (WARN_ON(!r || !*r)) - return 0; - - return *r == data; -} - /** * devm_pinctrl_register() - Resource managed version of pinctrl_register(). * @dev: parent device for this pin controller @@ -2348,20 +2323,16 @@ struct pinctrl_dev *devm_pinctrl_register(struct device *dev, const struct pinctrl_desc *pctldesc, void *driver_data) { - struct pinctrl_dev **ptr, *pctldev; - - ptr = devres_alloc(devm_pinctrl_dev_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct pinctrl_dev *pctldev; + int ret; pctldev = pinctrl_register(pctldesc, dev, driver_data); - if (IS_ERR(pctldev)) { - devres_free(ptr); + if (IS_ERR(pctldev)) return pctldev; - } - *ptr = pctldev; - devres_add(dev, ptr); + ret = devm_add_action_or_reset(dev, devm_pinctrl_dev_release, pctldev); + if (ret) + return ERR_PTR(ret); return pctldev; } @@ -2383,38 +2354,16 @@ int devm_pinctrl_register_and_init(struct device *dev, void *driver_data, struct pinctrl_dev **pctldev) { - struct pinctrl_dev **ptr; int error; - ptr = devres_alloc(devm_pinctrl_dev_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return -ENOMEM; - error = pinctrl_register_and_init(pctldesc, dev, driver_data, pctldev); - if (error) { - devres_free(ptr); + if (error) return error; - } - - *ptr = *pctldev; - devres_add(dev, ptr); - return 0; + return devm_add_action_or_reset(dev, devm_pinctrl_dev_release, *pctldev); } EXPORT_SYMBOL_GPL(devm_pinctrl_register_and_init); -/** - * devm_pinctrl_unregister() - Resource managed version of pinctrl_unregister(). - * @dev: device for which resource was allocated - * @pctldev: the pinctrl device to unregister. - */ -void devm_pinctrl_unregister(struct device *dev, struct pinctrl_dev *pctldev) -{ - WARN_ON(devres_release(dev, devm_pinctrl_dev_release, - devm_pinctrl_dev_match, pctldev)); -} -EXPORT_SYMBOL_GPL(devm_pinctrl_unregister); - static int __init pinctrl_init(void) { pr_debug("initialized pinctrl subsystem\n"); diff --git a/drivers/pinctrl/freescale/pinctrl-imx-scmi.c b/drivers/pinctrl/freescale/pinctrl-imx-scmi.c index 4e8ab919b334..dab2fabdf456 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx-scmi.c +++ b/drivers/pinctrl/freescale/pinctrl-imx-scmi.c @@ -38,11 +38,12 @@ struct scmi_pinctrl_imx { }; /* SCMI pin control types, aligned with SCMI firmware */ -#define IMX_SCMI_NUM_CFG 4 +#define IMX_SCMI_NUM_CFG 5 #define IMX_SCMI_PIN_MUX 192 #define IMX_SCMI_PIN_CONFIG 193 #define IMX_SCMI_PIN_DAISY_ID 194 #define IMX_SCMI_PIN_DAISY_CFG 195 +#define IMX_SCMI_PIN_EXT 196 #define IMX_SCMI_NO_PAD_CTL BIT(31) #define IMX_SCMI_PAD_SION BIT(30) @@ -50,8 +51,9 @@ struct scmi_pinctrl_imx { #define IMX_SCMI_PIN_SIZE 24 -#define IMX95_DAISY_OFF 0x408 #define IMX94_DAISY_OFF 0x608 +#define IMX95_DAISY_OFF 0x408 +#define IMX952_DAISY_OFF 0x460 static int pinctrl_scmi_imx_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np, @@ -73,6 +75,8 @@ static int pinctrl_scmi_imx_dt_node_to_map(struct pinctrl_dev *pctldev, daisy_off = IMX95_DAISY_OFF; } else if (of_machine_is_compatible("fsl,imx94")) { daisy_off = IMX94_DAISY_OFF; + } else if (of_machine_is_compatible("fsl,imx952")) { + daisy_off = IMX952_DAISY_OFF; } else { dev_err(pctldev->dev, "platform not support scmi pinctrl\n"); return -EINVAL; @@ -118,7 +122,14 @@ static int pinctrl_scmi_imx_dt_node_to_map(struct pinctrl_dev *pctldev, pin_id = mux_reg / 4; - cfg[j++] = pinconf_to_config_packed(IMX_SCMI_PIN_MUX, mux_val); + cfg[j++] = pinconf_to_config_packed(IMX_SCMI_PIN_MUX, (mux_val & 0xFF)); + + if (mux_val & 0xFF00) { + int ext_val = (mux_val & 0xFF00) >> 8; + + cfg[j++] = pinconf_to_config_packed(IMX_SCMI_PIN_EXT, ext_val); + } else + ncfg--; if (!conf_reg || (conf_val & IMX_SCMI_NO_PAD_CTL)) ncfg--; @@ -291,8 +302,9 @@ scmi_pinctrl_imx_get_pins(struct scmi_pinctrl_imx *pmx, struct pinctrl_desc *des } static const char * const scmi_pinctrl_imx_allowlist[] = { - "fsl,imx95", "fsl,imx94", + "fsl,imx95", + "fsl,imx952", NULL }; diff --git a/drivers/pinctrl/intel/Kconfig b/drivers/pinctrl/intel/Kconfig index 248c2e558ff3..04c3a5b581f3 100644 --- a/drivers/pinctrl/intel/Kconfig +++ b/drivers/pinctrl/intel/Kconfig @@ -45,6 +45,7 @@ config PINCTRL_INTEL_PLATFORM of Intel PCH pins and using them as GPIOs. Currently the following Intel SoCs / platforms require this to be functional: - Lunar Lake + - Nova Lake - Panther Lake config PINCTRL_ALDERLAKE @@ -52,7 +53,10 @@ config PINCTRL_ALDERLAKE select PINCTRL_INTEL help This pinctrl driver provides an interface that allows configuring - of Intel Alder Lake PCH pins and using them as GPIOs. + PCH pins of the following platforms and using them as GPIOs: + - Alder Lake HX, N, and S + - Raptor Lake HX, E, and S + - Twin Lake config PINCTRL_BROXTON tristate "Intel Broxton pinctrl and GPIO driver" @@ -136,15 +140,17 @@ config PINCTRL_METEORLAKE select PINCTRL_INTEL help This pinctrl driver provides an interface that allows configuring - of Intel Meteor Lake pins and using them as GPIOs. + SoC pins of the following platforms and using them as GPIOs: + - Arrow Lake (all variants) + - Meteor Lake (all variants) config PINCTRL_METEORPOINT tristate "Intel Meteor Point pinctrl and GPIO driver" select PINCTRL_INTEL help - Meteor Point is the PCH of Intel Meteor Lake. This pinctrl driver - provides an interface that allows configuring of PCH pins and - using them as GPIOs. + This pinctrl driver provides an interface that allows configuring + PCH pins of the following platforms and using them as GPIOs: + - Arrow Lake HX and S config PINCTRL_SUNRISEPOINT tristate "Intel Sunrisepoint pinctrl and GPIO driver" @@ -159,7 +165,11 @@ config PINCTRL_TIGERLAKE select PINCTRL_INTEL help This pinctrl driver provides an interface that allows configuring - of Intel Tiger Lake PCH pins and using them as GPIOs. + PCH pins of the following platforms and using them as GPIOs: + - Alder Lake H, P, PS, and U + - Raptor Lake H, P, PS, PX, and U + - Rocket Lake S + - Tiger Lake (all variants) source "drivers/pinctrl/intel/Kconfig.tng" endmenu diff --git a/drivers/pinctrl/intel/pinctrl-alderlake.c b/drivers/pinctrl/intel/pinctrl-alderlake.c index 7bf1d5c285a0..dcb541976f2f 100644 --- a/drivers/pinctrl/intel/pinctrl-alderlake.c +++ b/drivers/pinctrl/intel/pinctrl-alderlake.c @@ -2,7 +2,7 @@ /* * Intel Alder Lake PCH pinctrl/GPIO driver * - * Copyright (C) 2020, 2022 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index b3a5222a175f..b733ec31ad9d 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -2,7 +2,7 @@ /* * Pinctrl GPIO driver for Intel Baytrail * - * Copyright (c) 2012-2013, Intel Corporation + * Copyright (C) 2012-2013 Intel Corporation * Author: Mathias Nyman <mathias.nyman@linux.intel.com> */ @@ -101,10 +101,12 @@ struct intel_pad_context { u32 val; }; -#define COMMUNITY(p, n, map) \ +#define BYT_COMMUNITY(p, n, g, map) \ { \ .pin_base = (p), \ .npins = (n), \ + .gpps = (g), \ + .ngpps = ARRAY_SIZE(g), \ .pad_map = (map),\ } @@ -360,8 +362,15 @@ static const struct intel_function byt_score_functions[] = { FUNCTION("gpio", byt_score_gpio_groups), }; +static const struct intel_padgroup byt_score_gpps[] = { + INTEL_GPP(0, 0, 31, 0), + INTEL_GPP(1, 32, 63, 32), + INTEL_GPP(2, 64, 95, 64), + INTEL_GPP(3, 96, 101, 96), +}; + static const struct intel_community byt_score_communities[] = { - COMMUNITY(0, BYT_NGPIO_SCORE, byt_score_pins_map), + BYT_COMMUNITY(0, 102, byt_score_gpps, byt_score_pins_map), }; static const struct intel_pinctrl_soc_data byt_score_soc_data = { @@ -483,8 +492,13 @@ static const struct intel_function byt_sus_functions[] = { FUNCTION("pmu_clk", byt_sus_pmu_clk_groups), }; +static const struct intel_padgroup byt_sus_gpps[] = { + INTEL_GPP(0, 0, 31, 0), + INTEL_GPP(1, 32, 43, 32), +}; + static const struct intel_community byt_sus_communities[] = { - COMMUNITY(0, BYT_NGPIO_SUS, byt_sus_pins_map), + BYT_COMMUNITY(0, 44, byt_sus_gpps, byt_sus_pins_map), }; static const struct intel_pinctrl_soc_data byt_sus_soc_data = { @@ -536,8 +550,12 @@ static const unsigned int byt_ncore_pins_map[BYT_NGPIO_NCORE] = { 3, 6, 10, 13, 2, 5, 9, 7, }; +static const struct intel_padgroup byt_ncore_gpps[] = { + INTEL_GPP(0, 0, 27, 0), +}; + static const struct intel_community byt_ncore_communities[] = { - COMMUNITY(0, BYT_NGPIO_NCORE, byt_ncore_pins_map), + BYT_COMMUNITY(0, 28, byt_ncore_gpps, byt_ncore_pins_map), }; static const struct intel_pinctrl_soc_data byt_ncore_soc_data = { @@ -1490,19 +1508,6 @@ static int byt_gpio_irq_init_hw(struct gpio_chip *chip) return 0; } -static int byt_gpio_add_pin_ranges(struct gpio_chip *chip) -{ - struct intel_pinctrl *vg = gpiochip_get_data(chip); - struct device *dev = vg->dev; - int ret; - - ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, vg->soc->npins); - if (ret) - return dev_err_probe(dev, ret, "failed to add GPIO pin range\n"); - - return 0; -} - static int byt_gpio_probe(struct intel_pinctrl *vg) { struct platform_device *pdev = to_platform_device(vg->dev); @@ -1515,7 +1520,7 @@ static int byt_gpio_probe(struct intel_pinctrl *vg) gc->label = dev_name(vg->dev); gc->base = -1; gc->can_sleep = false; - gc->add_pin_ranges = byt_gpio_add_pin_ranges; + gc->add_pin_ranges = intel_gpio_add_pin_ranges; gc->parent = vg->dev; gc->ngpio = vg->soc->npins; @@ -1611,7 +1616,7 @@ static int byt_pinctrl_probe(struct platform_device *pdev) vg->pctldev = devm_pinctrl_register(dev, &vg->pctldesc, vg); if (IS_ERR(vg->pctldev)) - return dev_err_probe(dev, PTR_ERR(vg->pctldev), "failed to register pinctrl\n"); + return PTR_ERR(vg->pctldev); ret = byt_gpio_probe(vg); if (ret) diff --git a/drivers/pinctrl/intel/pinctrl-broxton.c b/drivers/pinctrl/intel/pinctrl-broxton.c index 140b29956340..3d3c1706928a 100644 --- a/drivers/pinctrl/intel/pinctrl-broxton.c +++ b/drivers/pinctrl/intel/pinctrl-broxton.c @@ -2,7 +2,7 @@ /* * Intel Broxton SoC pinctrl/GPIO driver * - * Copyright (C) 2015, 2016 Intel Corporation + * Copyright (C) 2015-2016 Intel Corporation * Author: Mika Westerberg <mika.westerberg@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-cannonlake.c b/drivers/pinctrl/intel/pinctrl-cannonlake.c index a3ffd19fd5be..baa7c9a62ff9 100644 --- a/drivers/pinctrl/intel/pinctrl-cannonlake.c +++ b/drivers/pinctrl/intel/pinctrl-cannonlake.c @@ -2,7 +2,7 @@ /* * Intel Cannon Lake PCH pinctrl/GPIO driver * - * Copyright (C) 2017, Intel Corporation + * Copyright (C) 2017 Intel Corporation * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com> * Mika Westerberg <mika.westerberg@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-cedarfork.c b/drivers/pinctrl/intel/pinctrl-cedarfork.c index 2916f7d90090..578e1ee57acf 100644 --- a/drivers/pinctrl/intel/pinctrl-cedarfork.c +++ b/drivers/pinctrl/intel/pinctrl-cedarfork.c @@ -2,7 +2,7 @@ /* * Intel Cedar Fork PCH pinctrl/GPIO driver * - * Copyright (C) 2017, Intel Corporation + * Copyright (C) 2017 Intel Corporation * Author: Mika Westerberg <mika.westerberg@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 8bd0c8512f78..a33eca5eafc4 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -2,7 +2,7 @@ /* * Cherryview/Braswell pinctrl driver * - * Copyright (C) 2014, 2020 Intel Corporation + * Copyright (C) 2014-2020 Intel Corporation * Author: Mika Westerberg <mika.westerberg@linux.intel.com> * * This driver is based on the original Cherryview GPIO driver by @@ -1644,7 +1644,7 @@ static int chv_pinctrl_probe(struct platform_device *pdev) pctrl->pctldev = devm_pinctrl_register(dev, &pctrl->pctldesc, pctrl); if (IS_ERR(pctrl->pctldev)) - return dev_err_probe(dev, PTR_ERR(pctrl->pctldev), "failed to register pinctrl\n"); + return PTR_ERR(pctrl->pctldev); ret = chv_gpio_probe(pctrl, irq); if (ret) diff --git a/drivers/pinctrl/intel/pinctrl-denverton.c b/drivers/pinctrl/intel/pinctrl-denverton.c index f492f73ba246..4a1d346fb30c 100644 --- a/drivers/pinctrl/intel/pinctrl-denverton.c +++ b/drivers/pinctrl/intel/pinctrl-denverton.c @@ -2,7 +2,7 @@ /* * Intel Denverton SoC pinctrl/GPIO driver * - * Copyright (C) 2017, Intel Corporation + * Copyright (C) 2017 Intel Corporation * Author: Mika Westerberg <mika.westerberg@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-elkhartlake.c b/drivers/pinctrl/intel/pinctrl-elkhartlake.c index 0e8742f31cd4..8a24ef12141d 100644 --- a/drivers/pinctrl/intel/pinctrl-elkhartlake.c +++ b/drivers/pinctrl/intel/pinctrl-elkhartlake.c @@ -2,7 +2,7 @@ /* * Intel Elkhart Lake PCH pinctrl/GPIO driver * - * Copyright (C) 2019, Intel Corporation + * Copyright (C) 2019 Intel Corporation * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-emmitsburg.c b/drivers/pinctrl/intel/pinctrl-emmitsburg.c index ba06a9ec239a..3b63b6dd2560 100644 --- a/drivers/pinctrl/intel/pinctrl-emmitsburg.c +++ b/drivers/pinctrl/intel/pinctrl-emmitsburg.c @@ -2,7 +2,7 @@ /* * Intel Emmitsburg PCH pinctrl/GPIO driver * - * Copyright (C) 2020, Intel Corporation + * Copyright (C) 2020 Intel Corporation * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-icelake.c b/drivers/pinctrl/intel/pinctrl-icelake.c index 1516fe7b4e4a..daabc5288cbb 100644 --- a/drivers/pinctrl/intel/pinctrl-icelake.c +++ b/drivers/pinctrl/intel/pinctrl-icelake.c @@ -2,7 +2,7 @@ /* * Intel Ice Lake PCH pinctrl/GPIO driver * - * Copyright (C) 2018, 2022 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com> * Mika Westerberg <mika.westerberg@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-intel-platform.c b/drivers/pinctrl/intel/pinctrl-intel-platform.c index dd5dbede0f59..61dd579e3f97 100644 --- a/drivers/pinctrl/intel/pinctrl-intel-platform.c +++ b/drivers/pinctrl/intel/pinctrl-intel-platform.c @@ -2,7 +2,7 @@ /* * Intel PCH pinctrl/GPIO driver * - * Copyright (C) 2021-2023, Intel Corporation + * Copyright (C) 2021-2023 Intel Corporation * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index cf9db8ac0f42..9d32bb8bc13a 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -2,7 +2,7 @@ /* * Intel pinctrl/GPIO core driver. * - * Copyright (C) 2015, Intel Corporation + * Copyright (C) 2015 Intel Corporation * Authors: Mathias Nyman <mathias.nyman@linux.intel.com> * Mika Westerberg <mika.westerberg@linux.intel.com> */ @@ -1673,7 +1673,7 @@ int intel_pinctrl_probe(struct platform_device *pdev, pctrl->pctldev = devm_pinctrl_register(dev, &pctrl->pctldesc, pctrl); if (IS_ERR(pctrl->pctldev)) - return dev_err_probe(dev, PTR_ERR(pctrl->pctldev), "failed to register pinctrl\n"); + return PTR_ERR(pctrl->pctldev); ret = intel_gpio_probe(pctrl, irq); if (ret) diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h index c1520797f895..2f37109d5860 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.h +++ b/drivers/pinctrl/intel/pinctrl-intel.h @@ -2,7 +2,7 @@ /* * Core pinctrl/GPIO driver for Intel GPIO controllers * - * Copyright (C) 2015, Intel Corporation + * Copyright (C) 2015 Intel Corporation * Authors: Mathias Nyman <mathias.nyman@linux.intel.com> * Mika Westerberg <mika.westerberg@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-jasperlake.c b/drivers/pinctrl/intel/pinctrl-jasperlake.c index c6e1836c69a7..a8f65c3dbb1c 100644 --- a/drivers/pinctrl/intel/pinctrl-jasperlake.c +++ b/drivers/pinctrl/intel/pinctrl-jasperlake.c @@ -2,7 +2,7 @@ /* * Intel Jasper Lake PCH pinctrl/GPIO driver * - * Copyright (C) 2020, Intel Corporation + * Copyright (C) 2020 Intel Corporation * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-lakefield.c b/drivers/pinctrl/intel/pinctrl-lakefield.c index bfb8b565d15c..39872c352ac2 100644 --- a/drivers/pinctrl/intel/pinctrl-lakefield.c +++ b/drivers/pinctrl/intel/pinctrl-lakefield.c @@ -2,7 +2,7 @@ /* * Intel Lakefield PCH pinctrl/GPIO driver * - * Copyright (C) 2020, Intel Corporation + * Copyright (C) 2020 Intel Corporation * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-lewisburg.c b/drivers/pinctrl/intel/pinctrl-lewisburg.c index 9fe651370f32..ebbc94047b6f 100644 --- a/drivers/pinctrl/intel/pinctrl-lewisburg.c +++ b/drivers/pinctrl/intel/pinctrl-lewisburg.c @@ -2,7 +2,7 @@ /* * Intel Lewisburg pinctrl/GPIO driver * - * Copyright (C) 2017, Intel Corporation + * Copyright (C) 2017 Intel Corporation * Author: Mika Westerberg <mika.westerberg@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-lynxpoint.c b/drivers/pinctrl/intel/pinctrl-lynxpoint.c index 1565eefdd4bf..299ee4f22bdc 100644 --- a/drivers/pinctrl/intel/pinctrl-lynxpoint.c +++ b/drivers/pinctrl/intel/pinctrl-lynxpoint.c @@ -2,7 +2,7 @@ /* * Intel Lynxpoint PCH pinctrl/GPIO driver * - * Copyright (c) 2012, 2019, Intel Corporation + * Copyright (C) 2012-2019 Intel Corporation * Authors: Mathias Nyman <mathias.nyman@linux.intel.com> * Andy Shevchenko <andriy.shevchenko@linux.intel.com> */ @@ -29,10 +29,12 @@ #include "pinctrl-intel.h" -#define COMMUNITY(p, n) \ +#define LPTLP_COMMUNITY(p, n, g) \ { \ .pin_base = (p), \ .npins = (n), \ + .gpps = (g), \ + .ngpps = ARRAY_SIZE(g), \ } static const struct pinctrl_pin_desc lptlp_pins[] = { @@ -133,8 +135,14 @@ static const struct pinctrl_pin_desc lptlp_pins[] = { PINCTRL_PIN(94, "GP94_UART0_CTSB"), }; +static const struct intel_padgroup lptlp_gpps[] = { + INTEL_GPP(0, 0, 31, 0), + INTEL_GPP(1, 32, 63, 32), + INTEL_GPP(2, 64, 94, 64), +}; + static const struct intel_community lptlp_communities[] = { - COMMUNITY(0, 95), + LPTLP_COMMUNITY(0, 95, lptlp_gpps), }; static const struct intel_pinctrl_soc_data lptlp_soc_data = { @@ -692,19 +700,6 @@ static int lp_gpio_irq_init_hw(struct gpio_chip *chip) return 0; } -static int lp_gpio_add_pin_ranges(struct gpio_chip *chip) -{ - struct intel_pinctrl *lg = gpiochip_get_data(chip); - struct device *dev = lg->dev; - int ret; - - ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, lg->soc->npins); - if (ret) - return dev_err_probe(dev, ret, "failed to add GPIO pin range\n"); - - return 0; -} - static int lp_gpio_probe(struct platform_device *pdev) { const struct intel_pinctrl_soc_data *soc; @@ -740,7 +735,7 @@ static int lp_gpio_probe(struct platform_device *pdev) lg->pctldev = devm_pinctrl_register(dev, &lg->pctldesc, lg); if (IS_ERR(lg->pctldev)) - return dev_err_probe(dev, PTR_ERR(lg->pctldev), "failed to register pinctrl\n"); + return PTR_ERR(lg->pctldev); platform_set_drvdata(pdev, lg); @@ -777,7 +772,7 @@ static int lp_gpio_probe(struct platform_device *pdev) gc->base = -1; gc->ngpio = LP_NUM_GPIO; gc->can_sleep = false; - gc->add_pin_ranges = lp_gpio_add_pin_ranges; + gc->add_pin_ranges = intel_gpio_add_pin_ranges; gc->parent = dev; /* set up interrupts */ diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c index 2f4d73dda41d..83b4d1862545 100644 --- a/drivers/pinctrl/intel/pinctrl-merrifield.c +++ b/drivers/pinctrl/intel/pinctrl-merrifield.c @@ -2,7 +2,7 @@ /* * Intel Merrifield SoC pinctrl driver * - * Copyright (C) 2016, Intel Corporation + * Copyright (C) 2016 Intel Corporation * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-meteorlake.c b/drivers/pinctrl/intel/pinctrl-meteorlake.c index b7395947569a..3f5070a339bf 100644 --- a/drivers/pinctrl/intel/pinctrl-meteorlake.c +++ b/drivers/pinctrl/intel/pinctrl-meteorlake.c @@ -2,7 +2,7 @@ /* * Intel Meteor Lake PCH pinctrl/GPIO driver * - * Copyright (C) 2022, Intel Corporation + * Copyright (C) 2022 Intel Corporation * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-meteorpoint.c b/drivers/pinctrl/intel/pinctrl-meteorpoint.c index b7858c2b2c5c..bff7be1f137d 100644 --- a/drivers/pinctrl/intel/pinctrl-meteorpoint.c +++ b/drivers/pinctrl/intel/pinctrl-meteorpoint.c @@ -2,7 +2,7 @@ /* * Intel Meteor Point PCH pinctrl/GPIO driver * - * Copyright (C) 2022-2023, Intel Corporation + * Copyright (C) 2022-2023 Intel Corporation * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-moorefield.c b/drivers/pinctrl/intel/pinctrl-moorefield.c index 6a79207e6b2a..30f9a4481827 100644 --- a/drivers/pinctrl/intel/pinctrl-moorefield.c +++ b/drivers/pinctrl/intel/pinctrl-moorefield.c @@ -2,7 +2,7 @@ /* * Intel Moorefield SoC pinctrl driver * - * Copyright (C) 2022, Intel Corporation + * Copyright (C) 2022 Intel Corporation * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c index b51befde9e8b..308651091d9c 100644 --- a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c +++ b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c @@ -2,7 +2,7 @@ /* * Intel Sunrisepoint PCH pinctrl/GPIO driver * - * Copyright (C) 2015, Intel Corporation + * Copyright (C) 2015 Intel Corporation * Authors: Mathias Nyman <mathias.nyman@linux.intel.com> * Mika Westerberg <mika.westerberg@linux.intel.com> */ diff --git a/drivers/pinctrl/intel/pinctrl-tangier.c b/drivers/pinctrl/intel/pinctrl-tangier.c index 5f0b7334a489..5fc13d369dd8 100644 --- a/drivers/pinctrl/intel/pinctrl-tangier.c +++ b/drivers/pinctrl/intel/pinctrl-tangier.c @@ -2,7 +2,7 @@ /* * Intel Tangier pinctrl driver * - * Copyright (C) 2016, 2023 Intel Corporation + * Copyright (C) 2016-2023 Intel Corporation * * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com> * Raag Jadav <raag.jadav@intel.com> @@ -518,15 +518,19 @@ static const struct pinctrl_desc tng_pinctrl_desc = { .owner = THIS_MODULE, }; -static int tng_pinctrl_probe(struct platform_device *pdev, - const struct tng_pinctrl *data) +int devm_tng_pinctrl_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + const struct tng_pinctrl *data; struct tng_family *families; struct tng_pinctrl *tp; void __iomem *regs; unsigned int i; + data = device_get_match_data(dev); + if (!data) + return -ENODATA; + tp = devm_kmemdup(dev, data, sizeof(*data), GFP_KERNEL); if (!tp) return -ENOMEM; @@ -562,21 +566,10 @@ static int tng_pinctrl_probe(struct platform_device *pdev, tp->pctldev = devm_pinctrl_register(dev, &tp->pctldesc, tp); if (IS_ERR(tp->pctldev)) - return dev_err_probe(dev, PTR_ERR(tp->pctldev), "failed to register pinctrl\n"); + return PTR_ERR(tp->pctldev); return 0; } - -int devm_tng_pinctrl_probe(struct platform_device *pdev) -{ - const struct tng_pinctrl *data; - - data = device_get_match_data(&pdev->dev); - if (!data) - return -ENODATA; - - return tng_pinctrl_probe(pdev, data); -} EXPORT_SYMBOL_NS_GPL(devm_tng_pinctrl_probe, "PINCTRL_TANGIER"); MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); diff --git a/drivers/pinctrl/intel/pinctrl-tangier.h b/drivers/pinctrl/intel/pinctrl-tangier.h index 955cc967c0bc..6af8eeeae943 100644 --- a/drivers/pinctrl/intel/pinctrl-tangier.h +++ b/drivers/pinctrl/intel/pinctrl-tangier.h @@ -2,7 +2,7 @@ /* * Intel Tangier pinctrl functions * - * Copyright (C) 2016, 2023 Intel Corporation + * Copyright (C) 2016-2023 Intel Corporation * * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com> * Raag Jadav <raag.jadav@intel.com> diff --git a/drivers/pinctrl/intel/pinctrl-tigerlake.c b/drivers/pinctrl/intel/pinctrl-tigerlake.c index c0887596d113..ae231f7fba49 100644 --- a/drivers/pinctrl/intel/pinctrl-tigerlake.c +++ b/drivers/pinctrl/intel/pinctrl-tigerlake.c @@ -2,7 +2,7 @@ /* * Intel Tiger Lake PCH pinctrl/GPIO driver * - * Copyright (C) 2019 - 2020, Intel Corporation + * Copyright (C) 2019-2020 Intel Corporation * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com> * Mika Westerberg <mika.westerberg@linux.intel.com> */ diff --git a/drivers/pinctrl/mediatek/mtk-eint.c b/drivers/pinctrl/mediatek/mtk-eint.c index c8c5097c11c4..2a3c04eedc5f 100644 --- a/drivers/pinctrl/mediatek/mtk-eint.c +++ b/drivers/pinctrl/mediatek/mtk-eint.c @@ -544,24 +544,32 @@ int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin) } } - eint->pin_list = devm_kmalloc(eint->dev, eint->nbase * sizeof(u16 *), GFP_KERNEL); + eint->pin_list = devm_kcalloc(eint->dev, eint->nbase, + sizeof(*eint->pin_list), GFP_KERNEL); if (!eint->pin_list) goto err_pin_list; - eint->wake_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL); + eint->wake_mask = devm_kcalloc(eint->dev, eint->nbase, + sizeof(*eint->wake_mask), GFP_KERNEL); if (!eint->wake_mask) goto err_wake_mask; - eint->cur_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL); + eint->cur_mask = devm_kcalloc(eint->dev, eint->nbase, + sizeof(*eint->cur_mask), GFP_KERNEL); if (!eint->cur_mask) goto err_cur_mask; for (i = 0; i < eint->nbase; i++) { - eint->pin_list[i] = devm_kzalloc(eint->dev, eint->base_pin_num[i] * sizeof(u16), + eint->pin_list[i] = devm_kzalloc(eint->dev, + eint->base_pin_num[i] * sizeof(**eint->pin_list), GFP_KERNEL); port = DIV_ROUND_UP(eint->base_pin_num[i], 32); - eint->wake_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL); - eint->cur_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL); + eint->wake_mask[i] = devm_kzalloc(eint->dev, + port * sizeof(**eint->wake_mask), + GFP_KERNEL); + eint->cur_mask[i] = devm_kzalloc(eint->dev, + port * sizeof(**eint->cur_mask), + GFP_KERNEL); if (!eint->pin_list[i] || !eint->wake_mask[i] || !eint->cur_mask[i]) goto err_eint; } @@ -597,12 +605,9 @@ int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin) err_eint: for (i = 0; i < eint->nbase; i++) { - if (eint->cur_mask[i]) - devm_kfree(eint->dev, eint->cur_mask[i]); - if (eint->wake_mask[i]) - devm_kfree(eint->dev, eint->wake_mask[i]); - if (eint->pin_list[i]) - devm_kfree(eint->dev, eint->pin_list[i]); + devm_kfree(eint->dev, eint->cur_mask[i]); + devm_kfree(eint->dev, eint->wake_mask[i]); + devm_kfree(eint->dev, eint->pin_list[i]); } devm_kfree(eint->dev, eint->cur_mask); err_cur_mask: diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7981.c b/drivers/pinctrl/mediatek/pinctrl-mt7981.c index 6216c2e057f6..22c8f2480346 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c @@ -1019,7 +1019,7 @@ static struct mtk_pin_soc mt7981_data = { .nfuncs = ARRAY_SIZE(mt7981_functions), .eint_hw = &mt7981_eint_hw, .gpio_m = 0, - .ies_present = false, + .ies_present = true, .base_names = mt7981_pinctrl_register_base_names, .nbase_names = ARRAY_SIZE(mt7981_pinctrl_register_base_names), .bias_disable_set = mtk_pinconf_bias_disable_set, diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7986.c b/drivers/pinctrl/mediatek/pinctrl-mt7986.c index 2a762ade9c35..5dda4b7467fd 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt7986.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt7986.c @@ -919,7 +919,7 @@ static struct mtk_pin_soc mt7986a_data = { .nfuncs = ARRAY_SIZE(mt7986_functions), .eint_hw = &mt7986a_eint_hw, .gpio_m = 0, - .ies_present = false, + .ies_present = true, .base_names = mt7986_pinctrl_register_base_names, .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), .bias_disable_set = mtk_pinconf_bias_disable_set, @@ -945,7 +945,7 @@ static struct mtk_pin_soc mt7986b_data = { .nfuncs = ARRAY_SIZE(mt7986_functions), .eint_hw = &mt7986b_eint_hw, .gpio_m = 0, - .ies_present = false, + .ies_present = true, .base_names = mt7986_pinctrl_register_base_names, .nbase_names = ARRAY_SIZE(mt7986_pinctrl_register_base_names), .bias_disable_set = mtk_pinconf_bias_disable_set, diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7988.c b/drivers/pinctrl/mediatek/pinctrl-mt7988.c index 9569e8c0cec1..fd3a7ff0a04d 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt7988.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt7988.c @@ -1505,7 +1505,7 @@ static const struct mtk_pin_soc mt7988_data = { .nfuncs = ARRAY_SIZE(mt7988_functions), .eint_hw = &mt7988_eint_hw, .gpio_m = 0, - .ies_present = false, + .ies_present = true, .base_names = mt7988_pinctrl_register_base_names, .nbase_names = ARRAY_SIZE(mt7988_pinctrl_register_base_names), .bias_disable_set = mtk_pinconf_bias_disable_set, diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8365.c b/drivers/pinctrl/mediatek/pinctrl-mt8365.c index e3e0d66cfbbf..c20b9e2e02dd 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt8365.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt8365.c @@ -456,7 +456,6 @@ static const struct mtk_pinctrl_devdata mt8365_pinctrl_data = { .smt_offset = 0x0470, .pullen_offset = 0x0860, .pullsel_offset = 0x0900, - .drv_offset = 0x0710, .type1_start = 145, .type1_end = 145, .port_shf = 4, diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h index 11afa12a96cb..3b96f3dd338d 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h @@ -263,7 +263,6 @@ struct mtk_pinctrl_devdata { unsigned int smt_offset; unsigned int pullen_offset; unsigned int pullsel_offset; - unsigned int drv_offset; unsigned int dout_offset; unsigned int din_offset; unsigned int pinmux_offset; diff --git a/drivers/pinctrl/meson/Kconfig b/drivers/pinctrl/meson/Kconfig index 0315e224bce6..ce6aeec2fc79 100644 --- a/drivers/pinctrl/meson/Kconfig +++ b/drivers/pinctrl/meson/Kconfig @@ -15,25 +15,25 @@ if PINCTRL_MESON config PINCTRL_MESON8 bool "Meson 8 SoC pinctrl driver" - depends on ARM + depends on ARM || COMPILE_TEST select PINCTRL_MESON8_PMX default ARCH_MESON config PINCTRL_MESON8B bool "Meson 8b SoC pinctrl driver" - depends on ARM + depends on ARM || COMPILE_TEST select PINCTRL_MESON8_PMX default ARCH_MESON config PINCTRL_MESON_GXBB tristate "Meson gxbb SoC pinctrl driver" - depends on ARM64 + depends on ARM64 || COMPILE_TEST select PINCTRL_MESON8_PMX default ARCH_MESON config PINCTRL_MESON_GXL tristate "Meson gxl SoC pinctrl driver" - depends on ARM64 + depends on ARM64 || COMPILE_TEST select PINCTRL_MESON8_PMX default ARCH_MESON @@ -42,7 +42,7 @@ config PINCTRL_MESON8_PMX config PINCTRL_MESON_AXG tristate "Meson axg Soc pinctrl driver" - depends on ARM64 + depends on ARM64 || COMPILE_TEST select PINCTRL_MESON_AXG_PMX default ARCH_MESON @@ -51,25 +51,25 @@ config PINCTRL_MESON_AXG_PMX config PINCTRL_MESON_G12A tristate "Meson g12a Soc pinctrl driver" - depends on ARM64 + depends on ARM64 || COMPILE_TEST select PINCTRL_MESON_AXG_PMX default ARCH_MESON config PINCTRL_MESON_A1 tristate "Meson a1 Soc pinctrl driver" - depends on ARM64 + depends on ARM64 || COMPILE_TEST select PINCTRL_MESON_AXG_PMX default ARCH_MESON config PINCTRL_MESON_S4 tristate "Meson s4 Soc pinctrl driver" - depends on ARM64 + depends on ARM64 || COMPILE_TEST select PINCTRL_MESON_AXG_PMX default ARCH_MESON config PINCTRL_AMLOGIC_A4 bool "AMLOGIC pincontrol" - depends on ARM64 + depends on ARM64 || COMPILE_TEST default ARCH_MESON help This is the driver for the pin controller found on Amlogic SoCs. @@ -80,13 +80,13 @@ config PINCTRL_AMLOGIC_A4 config PINCTRL_AMLOGIC_C3 tristate "Amlogic C3 SoC pinctrl driver" - depends on ARM64 + depends on ARM64 || COMPILE_TEST select PINCTRL_MESON_AXG_PMX default ARCH_MESON config PINCTRL_AMLOGIC_T7 tristate "Amlogic T7 SoC pinctrl driver" - depends on ARM64 + depends on ARM64 || COMPILE_TEST select PINCTRL_MESON_AXG_PMX default ARCH_MESON diff --git a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c index d9e3a8d5932a..dfa32b11555c 100644 --- a/drivers/pinctrl/meson/pinctrl-amlogic-a4.c +++ b/drivers/pinctrl/meson/pinctrl-amlogic-a4.c @@ -24,6 +24,7 @@ #include <dt-bindings/pinctrl/amlogic,pinctrl.h> #include "../core.h" +#include "../pinctrl-utils.h" #include "../pinconf.h" #define gpio_chip_to_bank(chip) \ @@ -672,11 +673,79 @@ static void aml_pin_dbg_show(struct pinctrl_dev *pcdev, struct seq_file *s, seq_printf(s, " %s", dev_name(pcdev->dev)); } +static int aml_dt_node_to_map_pinmux(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **map, + unsigned int *num_maps) +{ + struct device *dev = pctldev->dev; + struct device_node *pnode; + unsigned long *configs = NULL; + unsigned int num_configs = 0; + struct property *prop; + unsigned int reserved_maps; + int reserve; + int ret; + + prop = of_find_property(np, "pinmux", NULL); + if (!prop) { + dev_info(dev, "Missing pinmux property\n"); + return -ENOENT; + } + + pnode = of_get_parent(np); + if (!pnode) { + dev_info(dev, "Missing function node\n"); + return -EINVAL; + } + + reserved_maps = 0; + *map = NULL; + *num_maps = 0; + + ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, + &num_configs); + if (ret < 0) { + dev_err(dev, "%pOF: could not parse node property\n", np); + return ret; + } + + reserve = 1; + if (num_configs) + reserve++; + + ret = pinctrl_utils_reserve_map(pctldev, map, &reserved_maps, + num_maps, reserve); + if (ret < 0) + goto exit; + + ret = pinctrl_utils_add_map_mux(pctldev, map, + &reserved_maps, num_maps, np->name, + pnode->name); + if (ret < 0) + goto exit; + + if (num_configs) { + ret = pinctrl_utils_add_map_configs(pctldev, map, &reserved_maps, + num_maps, np->name, configs, + num_configs, PIN_MAP_TYPE_CONFIGS_GROUP); + if (ret < 0) + goto exit; + } + +exit: + kfree(configs); + if (ret) + pinctrl_utils_free_map(pctldev, *map, *num_maps); + + return ret; +} + static const struct pinctrl_ops aml_pctrl_ops = { .get_groups_count = aml_get_groups_count, .get_group_name = aml_get_group_name, .get_group_pins = aml_get_group_pins, - .dt_node_to_map = pinconf_generic_dt_node_to_map_pinmux, + .dt_node_to_map = aml_dt_node_to_map_pinmux, .dt_free_map = pinconf_generic_dt_free_map, .pin_dbg_show = aml_pin_dbg_show, }; @@ -725,8 +794,9 @@ static u32 aml_bank_pins(struct device_node *np) if (of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &of_args)) return 0; - else - return of_args.args[2]; + + of_node_put(of_args.np); + return of_args.args[2]; } static int aml_bank_number(struct device_node *np) @@ -736,8 +806,9 @@ static int aml_bank_number(struct device_node *np) if (of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &of_args)) return -EINVAL; - else - return of_args.args[1] >> 8; + + of_node_put(of_args.np); + return of_args.args[1] >> 8; } static unsigned int aml_count_pins(struct device_node *np) @@ -893,7 +964,7 @@ static const struct gpio_chip aml_gpio_template = { .direction_input = aml_gpio_direction_input, .direction_output = aml_gpio_direction_output, .get_direction = aml_gpio_get_direction, - .can_sleep = false, + .can_sleep = true, }; static void init_bank_register_bit(struct aml_pinctrl *info, diff --git a/drivers/pinctrl/microchip/Kconfig b/drivers/pinctrl/microchip/Kconfig new file mode 100644 index 000000000000..aba55f686f45 --- /dev/null +++ b/drivers/pinctrl/microchip/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config PINCTRL_PIC64GX + bool "pic64gx gpio2 pinctrl driver" + depends on ARCH_MICROCHIP || COMPILE_TEST + depends on OF + select GENERIC_PINCONF + select REGMAP_MMIO + help + This selects the pinctrl driver for gpio2 on pic64gx. + +config PINCTRL_POLARFIRE_SOC + bool "Polarfire SoC pinctrl drivers" + depends on ARCH_MICROCHIP || COMPILE_TEST + depends on OF + select GENERIC_PINCTRL + help + This selects the pinctrl drivers for Microchip Polarfire SoC. diff --git a/drivers/pinctrl/microchip/Makefile b/drivers/pinctrl/microchip/Makefile new file mode 100644 index 000000000000..ab0575cd2ed1 --- /dev/null +++ b/drivers/pinctrl/microchip/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_PINCTRL_PIC64GX) += pinctrl-pic64gx-gpio2.o +obj-$(CONFIG_PINCTRL_POLARFIRE_SOC) += pinctrl-mpfs-iomux0.o +obj-$(CONFIG_PINCTRL_POLARFIRE_SOC) += pinctrl-mpfs-mssio.o diff --git a/drivers/pinctrl/pinctrl-mpfs-iomux0.c b/drivers/pinctrl/microchip/pinctrl-mpfs-iomux0.c index cf5b2e4e8f5b..1b060a038920 100644 --- a/drivers/pinctrl/pinctrl-mpfs-iomux0.c +++ b/drivers/pinctrl/microchip/pinctrl-mpfs-iomux0.c @@ -15,10 +15,10 @@ #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> -#include "core.h" -#include "pinctrl-utils.h" -#include "pinconf.h" -#include "pinmux.h" +#include "../core.h" +#include "../pinctrl-utils.h" +#include "../pinconf.h" +#include "../pinmux.h" #define MPFS_IOMUX0_REG 0x200 diff --git a/drivers/pinctrl/microchip/pinctrl-mpfs-mssio.c b/drivers/pinctrl/microchip/pinctrl-mpfs-mssio.c new file mode 100644 index 000000000000..3d5ffd6cb14b --- /dev/null +++ b/drivers/pinctrl/microchip/pinctrl-mpfs-mssio.c @@ -0,0 +1,737 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/bitfield.h> +#include <linux/module.h> +#include <linux/mfd/syscon.h> +#include <linux/mod_devicetable.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/seq_file.h> + +#include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinmux.h> + +#include "../core.h" +#include "../pinctrl-utils.h" +#include "../pinconf.h" +#include "../pinmux.h" + +#define MPFS_PINCTRL_PAD_MUX_MASK GENMASK(3, 0) + +#define MPFS_PINCTRL_IOCFG_MASK GENMASK(14, 0) +#define MPFS_PINCTRL_IBUFMD_MASK GENMASK(2, 0) +#define MPFS_PINCTRL_DRV_MASK GENMASK(6, 3) +#define MPFS_PINCTRL_CLAMP BIT(7) +#define MPFS_PINCTRL_ENHYST BIT(8) +#define MPFS_PINCTRL_LOCKDN BIT(9) +#define MPFS_PINCTRL_WPD BIT(10) +#define MPFS_PINCTRL_WPU BIT(11) +#define MPFS_PINCTRL_PULL_MASK GENMASK(11, 10) +#define MPFS_PINCTRL_LP_PERSIST_EN BIT(12) +#define MPFS_PINCTRL_LP_BYPASS_EN BIT(13) + +#define MPFS_PINCTRL_MSSIO_BANK2_CFG_CR 0x1c4 +#define MPFS_PINCTRL_MSSIO_BANK4_CFG_CR 0x1c8 +#define MPFS_PINCTRL_BANK_VOLTAGE_MASK GENMASK(19, 16) + +#define MPFS_PINCTRL_IOCFG01_REG 0x234 + +#define MPFS_PINCTRL_INTER_BANK_GAP 0x4 + +#define MPFS_PINCTRL_BANK2_START 14 + +#define MPFS_PINCTRL_LOCKDOWN (PIN_CONFIG_END + 1) +#define MPFS_PINCTRL_CLAMP_DIODE (PIN_CONFIG_END + 2) +#define MPFS_PINCTRL_IBUFMD (PIN_CONFIG_END + 3) + +struct mpfs_pinctrl_mux_config { + u8 pin; + u8 function; +}; + +struct mpfs_pinctrl { + struct pinctrl_dev *pctrl; + struct device *dev; + struct regmap *regmap; + struct regmap *sysreg_regmap; + struct mutex mutex; + struct pinctrl_desc desc; +}; + +struct mpfs_pinctrl_drive_strength { + u8 ma; + u8 val; +}; + +struct mpfs_pinctrl_bank_voltage { + u32 uv; + u8 val; +}; + +static struct mpfs_pinctrl_drive_strength mpfs_pinctrl_drive_strengths[8] = { + { .ma = 2, .val = 2 }, + { .ma = 4, .val = 3 }, + { .ma = 6, .val = 4 }, + { .ma = 8, .val = 5 }, + { .ma = 10, .val = 6 }, + { .ma = 12, .val = 7 }, + { .ma = 16, .val = 10 }, + { .ma = 20, .val = 12 }, +}; +static struct mpfs_pinctrl_bank_voltage mpfs_pinctrl_bank_voltages[8] = { + { .uv = 1200000, .val = 0 }, + { .uv = 1500000, .val = 2 }, + { .uv = 1800000, .val = 4 }, + { .uv = 2500000, .val = 6 }, + { .uv = 3300000, .val = 8 }, + { .uv = 0, .val = 0x3f }, // pin unused +}; + +static int mpfs_pinctrl_get_drive_strength_ma(u32 drive_strength) +{ + size_t num = ARRAY_SIZE(mpfs_pinctrl_drive_strengths); + + for (int i = 0; i < num; i++) + if (drive_strength == mpfs_pinctrl_drive_strengths[i].val) + return mpfs_pinctrl_drive_strengths[i].ma; + + return -EINVAL; +} + +static int mpfs_pinctrl_get_drive_strength_val(u32 drive_strength_ma) +{ + size_t num = ARRAY_SIZE(mpfs_pinctrl_drive_strengths); + + if (!drive_strength_ma) + return -EINVAL; + + for (int i = 0; i < num; i++) + if (drive_strength_ma <= mpfs_pinctrl_drive_strengths[i].ma) + return mpfs_pinctrl_drive_strengths[i].val; + + return mpfs_pinctrl_drive_strengths[num - 1].val; +} + +static int mpfs_pinctrl_get_bank_voltage_uv(u32 bank_voltage) +{ + size_t num = ARRAY_SIZE(mpfs_pinctrl_bank_voltages); + + for (int i = 0; i < num; i++) + if (bank_voltage == mpfs_pinctrl_bank_voltages[i].val) + return mpfs_pinctrl_bank_voltages[i].uv; + + return -EINVAL; +} + +static int mpfs_pinctrl_get_bank_voltage_val(u32 bank_voltage_uv) +{ + size_t num = ARRAY_SIZE(mpfs_pinctrl_bank_voltages); + + for (int i = 0; i < num; i++) + if (bank_voltage_uv <= mpfs_pinctrl_bank_voltages[i].uv) + return mpfs_pinctrl_bank_voltages[i].val; + + return -EINVAL; +} + +static u32 mpfs_pinctrl_pin_to_bank_voltage(struct mpfs_pinctrl *pctrl, unsigned int pin) +{ + u32 bank_voltage, val; + + if (pin < MPFS_PINCTRL_BANK2_START) + regmap_read(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK4_CFG_CR, &val); + else + regmap_read(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK2_CFG_CR, &val); + + bank_voltage = FIELD_GET(MPFS_PINCTRL_BANK_VOLTAGE_MASK, val); + + return mpfs_pinctrl_get_bank_voltage_uv(bank_voltage); +} + +static void mpfs_pinctrl_set_bank_voltage(struct mpfs_pinctrl *pctrl, unsigned int pin, + u32 bank_voltage) +{ + u32 val = FIELD_PREP(MPFS_PINCTRL_BANK_VOLTAGE_MASK, bank_voltage); + + if (pin < MPFS_PINCTRL_BANK2_START) + regmap_assign_bits(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK4_CFG_CR, + MPFS_PINCTRL_BANK_VOLTAGE_MASK, val); + else + regmap_assign_bits(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK2_CFG_CR, + MPFS_PINCTRL_BANK_VOLTAGE_MASK, val); +} + +static char *mpfs_pinctrl_function_names[] = { + "sd", + "emmc", + "qspi", + "spi", + "usb", + "uart", + "i2c", + "can", + "mdio", + "misc", + "reserved", + "gpio", + "fabric test", + "tied-low", + "tied-high", + "tristate" +}; + +static int mpfs_pinctrl_function_map(const char *function) +{ + size_t num = ARRAY_SIZE(mpfs_pinctrl_function_names); + + for (int i = 0; i < num; i++) + if (!strcmp(function, mpfs_pinctrl_function_names[i])) + return i; + + return -EINVAL; +} + +static const struct pinconf_generic_params mpfs_pinctrl_custom_bindings[] = { + { "microchip,clamp-diode", MPFS_PINCTRL_CLAMP_DIODE, 1 }, + { "microchip,ibufmd", MPFS_PINCTRL_IBUFMD, 0x0 }, +}; + +static int mpfs_pinctrl_pin_to_iomux_offset(unsigned int pin) +{ + int offset; + + switch (pin) { + case 0 ... 7: + offset = pin * 4; + break; + case 8 ... 13: + offset = (pin - 8) * 4; + break; + case 14 ... 21: + offset = (pin - 14) * 4; + break; + case 22 ... 29: + offset = (pin - 22) * 4; + break; + case 30 ... 37: + offset = (pin - 30) * 4; + break; + default: + offset = -EINVAL; + } + + return offset; +} + +static int mpfs_pinctrl_pin_to_iomux_reg(unsigned int pin) +{ + int reg; + + switch (pin) { + case 0 ... 7: + reg = 0x204; + break; + case 8 ... 13: + reg = 0x208; + break; + case 14 ... 21: + reg = 0x20c; + break; + case 22 ... 29: + reg = 0x210; + break; + case 30 ... 37: + reg = 0x214; + break; + default: + reg = -EINVAL; + } + + return reg; +} + +static int mpfs_pinctrl_pin_to_iocfg_reg(unsigned int pin) +{ + u32 reg = MPFS_PINCTRL_IOCFG01_REG; + + if (pin >= MPFS_PINCTRL_BANK2_START) + reg += MPFS_PINCTRL_INTER_BANK_GAP; + + // 2 pins per 32-bit register + reg += (pin / 2) * 0x4; + + return reg; +} + +static int mpfs_pinctrl_pin_to_iocfg_offset(unsigned int pin) +{ + return 16 * (pin % 2); +} + +static void mpfs_pinctrl_dbg_show(struct pinctrl_dev *pctrl_dev, struct seq_file *seq, + unsigned int pin) +{ + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); + u32 func; + int reg, offset; + + reg = mpfs_pinctrl_pin_to_iomux_reg(pin); + offset = mpfs_pinctrl_pin_to_iomux_offset(pin); + + seq_printf(seq, "reg: %x, offset: %u ", reg, offset); + seq_printf(seq, "pin: %u ", pin); + + if (reg < 0 || offset < 0) + return; + + regmap_read(pctrl->regmap, reg, &func); + func = (func >> offset) & MPFS_PINCTRL_PAD_MUX_MASK; + seq_printf(seq, "func: %s (%x)\n", mpfs_pinctrl_function_names[func], func); +} + +static const struct pinctrl_ops mpfs_pinctrl_ops = { + .get_groups_count = pinctrl_generic_get_group_count, + .get_group_name = pinctrl_generic_get_group_name, + .get_group_pins = pinctrl_generic_get_group_pins, + .pin_dbg_show = mpfs_pinctrl_dbg_show, + .dt_node_to_map = pinctrl_generic_pins_function_dt_node_to_map, + .dt_free_map = pinctrl_utils_free_map, +}; + +static int mpfs_pinctrl_set_pin_func(struct mpfs_pinctrl *pctrl, u8 pin, u8 function) +{ + struct device *dev = pctrl->dev; + int reg, offset; + u32 func, mask; + + reg = mpfs_pinctrl_pin_to_iomux_reg(pin); + offset = mpfs_pinctrl_pin_to_iomux_offset(pin); + + func = function << offset; + mask = MPFS_PINCTRL_PAD_MUX_MASK << offset; + + dev_dbg(dev, "Setting pin %u. reg: %x offset %u func %x\n", pin, reg, offset, func); + + if (reg < 0 || offset < 0) + return -EINVAL; + + regmap_update_bits(pctrl->regmap, reg, mask, func); + + return 0; +} + +static int mpfs_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev, unsigned int fsel, + unsigned int gsel) +{ + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); + const struct group_desc *group; + const char **functions; + + group = pinctrl_generic_get_group(pctrl_dev, gsel); + if (!group) + return -EINVAL; + + functions = group->data; + + for (int i = 0; i < group->grp.npins; i++) { + int function; + + function = mpfs_pinctrl_function_map(functions[i]); + if (function < 0) { + dev_err(pctrl->dev, "invalid function %s\n", functions[i]); + return function; + } + + mpfs_pinctrl_set_pin_func(pctrl, group->grp.pins[i], function); + } + + return 0; +} + +static const struct pinmux_ops mpfs_pinctrl_pinmux_ops = { + .get_functions_count = pinmux_generic_get_function_count, + .get_function_name = pinmux_generic_get_function_name, + .get_function_groups = pinmux_generic_get_function_groups, + .set_mux = mpfs_pinctrl_set_mux, +}; + +static int mpfs_pinctrl_pinconf_get(struct pinctrl_dev *pctrl_dev, unsigned int pin, + unsigned long *config) +{ + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); + int param = pinconf_to_config_param(*config); + int reg = mpfs_pinctrl_pin_to_iocfg_reg(pin); + int val; + u32 arg; + u8 str; + + regmap_read(pctrl->regmap, reg, &val); + + val = val >> mpfs_pinctrl_pin_to_iocfg_offset(pin); + val = val & MPFS_PINCTRL_IOCFG_MASK; + + switch (param) { + case PIN_CONFIG_BIAS_BUS_HOLD: + if (!(val & MPFS_PINCTRL_WPD)) + return -EINVAL; + + if (!(val & MPFS_PINCTRL_WPU)) + return -EINVAL; + + arg = 1; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + if (!(val & MPFS_PINCTRL_WPD)) + return -EINVAL; + + if (val & MPFS_PINCTRL_WPU) + return -EINVAL; + + arg = 1; + break; + case PIN_CONFIG_BIAS_PULL_UP: + if (!(val & MPFS_PINCTRL_WPU)) + return -EINVAL; + + if (val & MPFS_PINCTRL_WPD) + return -EINVAL; + + arg = 1; + break; + case PIN_CONFIG_BIAS_DISABLE: + if (val & MPFS_PINCTRL_PULL_MASK) + return -EINVAL; + + arg = 1; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + str = FIELD_GET(MPFS_PINCTRL_DRV_MASK, val); + if (!str) + return -EINVAL; + + arg = mpfs_pinctrl_get_drive_strength_ma(str); + break; + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: + if (!FIELD_GET(MPFS_PINCTRL_ENHYST, val)) + return -EINVAL; + + arg = 1; + break; + case PIN_CONFIG_PERSIST_STATE: + if (!FIELD_GET(MPFS_PINCTRL_LP_PERSIST_EN, val)) + return -EINVAL; + + arg = 1; + break; + case PIN_CONFIG_MODE_LOW_POWER: + if (!FIELD_GET(MPFS_PINCTRL_LP_BYPASS_EN, val)) + return -EINVAL; + + arg = 1; + break; + case PIN_CONFIG_POWER_SOURCE: + arg = mpfs_pinctrl_pin_to_bank_voltage(pctrl, pin); + break; + case MPFS_PINCTRL_CLAMP_DIODE: + if (!FIELD_GET(MPFS_PINCTRL_CLAMP, val)) + return -EINVAL; + + arg = 1; + break; + case MPFS_PINCTRL_LOCKDOWN: + /* + * Lockdown is a read-only configuration, it'll get set if the + * tamper unit triggers global lockdown and lockdown has been + * set in the MSS Configurator for the bank a pin belongs to. + */ + if (!FIELD_GET(MPFS_PINCTRL_LOCKDN, val)) + return -EINVAL; + + arg = 1; + break; + case MPFS_PINCTRL_IBUFMD: + arg = FIELD_GET(MPFS_PINCTRL_IBUFMD_MASK, val); + break; + default: + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static int mpfs_pinctrl_pinconf_generate_config(struct mpfs_pinctrl *pctrl, unsigned int pin, + unsigned long *configs, unsigned int num_configs, + u32 *value, u32 *bank_voltage) +{ + u32 val = 0; + + for (int i = 0; i < num_configs; i++) { + int param, tmp; + u32 arg; + + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + switch (param) { + case PIN_CONFIG_BIAS_BUS_HOLD: + val |= MPFS_PINCTRL_PULL_MASK; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + val &= ~MPFS_PINCTRL_PULL_MASK; + val |= MPFS_PINCTRL_WPD; + break; + case PIN_CONFIG_BIAS_PULL_UP: + val &= ~MPFS_PINCTRL_PULL_MASK; + val |= MPFS_PINCTRL_WPU; + break; + case PIN_CONFIG_BIAS_DISABLE: + val &= ~MPFS_PINCTRL_PULL_MASK; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + tmp = mpfs_pinctrl_get_drive_strength_val(arg); + if (tmp < 0) + return tmp; + + val |= FIELD_PREP(MPFS_PINCTRL_DRV_MASK, tmp); + break; + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: + if (!arg) + break; + val |= MPFS_PINCTRL_ENHYST; + break; + case PIN_CONFIG_PERSIST_STATE: + val |= MPFS_PINCTRL_LP_PERSIST_EN; + break; + case PIN_CONFIG_MODE_LOW_POWER: + if (arg) + val |= MPFS_PINCTRL_LP_BYPASS_EN; + break; + case PIN_CONFIG_POWER_SOURCE: + tmp = mpfs_pinctrl_get_bank_voltage_val(arg); + if (tmp < 0) + return tmp; + + *bank_voltage = tmp; + break; + case MPFS_PINCTRL_CLAMP_DIODE: + val |= MPFS_PINCTRL_CLAMP; + break; + case MPFS_PINCTRL_IBUFMD: + val |= FIELD_PREP(MPFS_PINCTRL_IBUFMD_MASK, arg); + break; + default: + dev_err(pctrl->dev, "config %u not supported\n", param); + return -ENOTSUPP; + } + } + + *value = val; + return 0; +} + +static int mpfs_pinctrl_pin_set_config(struct mpfs_pinctrl *pctrl, unsigned int pin, u32 config) +{ + int reg = mpfs_pinctrl_pin_to_iocfg_reg(pin); + int offset = mpfs_pinctrl_pin_to_iocfg_offset(pin); + u32 val, mask; + + mask = MPFS_PINCTRL_IOCFG_MASK << offset; + val = config << offset; + + regmap_update_bits(pctrl->regmap, reg, mask, val); + + return 0; +} + +static int mpfs_pinctrl_pinconf_set(struct pinctrl_dev *pctrl_dev, unsigned int pin, + unsigned long *configs, unsigned int num_configs) +{ + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); + u32 val, bank_voltage = 0; + int ret; + + ret = mpfs_pinctrl_pinconf_generate_config(pctrl, pin, configs, num_configs, &val, + &bank_voltage); + if (ret) + return ret; + + ret = mpfs_pinctrl_pin_set_config(pctrl, pin, val); + if (ret) + return ret; + + if (bank_voltage) + mpfs_pinctrl_set_bank_voltage(pctrl, pin, bank_voltage); + + return 0; +} + +static int mpfs_pinctrl_pinconf_group_set(struct pinctrl_dev *pctrl_dev, unsigned int gsel, + unsigned long *configs, unsigned int num_configs) +{ + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); + const struct group_desc *group; + unsigned int pin; + u32 val, bank_voltage = 0; + int ret; + + group = pinctrl_generic_get_group(pctrl_dev, gsel); + if (!group) + return -EINVAL; + + /* + * Assume that the first pin in a group is representative, as the mss + * configurator doesn't allow splitting a function between two banks. + */ + pin = group->grp.pins[0]; + + ret = mpfs_pinctrl_pinconf_generate_config(pctrl, pin, configs, num_configs, &val, + &bank_voltage); + if (ret) + return ret; + + for (int i = 0; i < group->grp.npins; i++) + mpfs_pinctrl_pin_set_config(pctrl, group->grp.pins[i], val); + + if (bank_voltage) + mpfs_pinctrl_set_bank_voltage(pctrl, group->grp.pins[0], bank_voltage); + + return 0; +} + +static void mpfs_pinctrl_pinconf_dbg_show(struct pinctrl_dev *pctrl_dev, struct seq_file *seq, + unsigned int pin) +{ + struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); + u32 val; + int reg, offset; + + reg = mpfs_pinctrl_pin_to_iocfg_reg(pin); + offset = mpfs_pinctrl_pin_to_iocfg_offset(pin); + + seq_printf(seq, "pin: %u ", pin); + seq_printf(seq, "reg: %x offset: %u ", reg, offset); + + if (reg < 0 || offset < 0) + return; + + regmap_read(pctrl->regmap, reg, &val); + val = (val & (MPFS_PINCTRL_IOCFG_MASK << offset)) >> offset; + seq_printf(seq, "val: %x\n", val); +} + +static const struct pinconf_ops mpfs_pinctrl_pinconf_ops = { + .pin_config_get = mpfs_pinctrl_pinconf_get, + .pin_config_set = mpfs_pinctrl_pinconf_set, + .pin_config_group_set = mpfs_pinctrl_pinconf_group_set, + .pin_config_dbg_show = mpfs_pinctrl_pinconf_dbg_show, + .is_generic = true, +}; + +static const struct pinctrl_pin_desc mpfs_pinctrl_pins[] = { + PINCTRL_PIN(0, "bank 4 0"), + PINCTRL_PIN(1, "bank 4 1"), + PINCTRL_PIN(2, "bank 4 2"), + PINCTRL_PIN(3, "bank 4 3"), + PINCTRL_PIN(4, "bank 4 4"), + PINCTRL_PIN(5, "bank 4 5"), + PINCTRL_PIN(6, "bank 4 6"), + PINCTRL_PIN(7, "bank 4 7"), + PINCTRL_PIN(8, "bank 4 8"), + PINCTRL_PIN(9, "bank 4 9"), + PINCTRL_PIN(10, "bank 4 10"), + PINCTRL_PIN(11, "bank 4 11"), + PINCTRL_PIN(12, "bank 4 12"), + PINCTRL_PIN(13, "bank 4 13"), + + PINCTRL_PIN(14, "bank 2 0"), + PINCTRL_PIN(15, "bank 2 1"), + PINCTRL_PIN(16, "bank 2 2"), + PINCTRL_PIN(17, "bank 2 3"), + PINCTRL_PIN(18, "bank 2 4"), + PINCTRL_PIN(19, "bank 2 5"), + PINCTRL_PIN(20, "bank 2 6"), + PINCTRL_PIN(21, "bank 2 7"), + PINCTRL_PIN(22, "bank 2 8"), + PINCTRL_PIN(23, "bank 2 9"), + PINCTRL_PIN(24, "bank 2 10"), + PINCTRL_PIN(25, "bank 2 11"), + PINCTRL_PIN(26, "bank 2 12"), + PINCTRL_PIN(27, "bank 2 13"), + PINCTRL_PIN(28, "bank 2 14"), + PINCTRL_PIN(29, "bank 2 15"), + PINCTRL_PIN(30, "bank 2 16"), + PINCTRL_PIN(31, "bank 2 17"), + PINCTRL_PIN(32, "bank 2 18"), + PINCTRL_PIN(33, "bank 2 19"), + PINCTRL_PIN(34, "bank 2 20"), + PINCTRL_PIN(35, "bank 2 21"), + PINCTRL_PIN(36, "bank 2 22"), + PINCTRL_PIN(37, "bank 2 23"), +}; + +static int mpfs_pinctrl_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mpfs_pinctrl *pctrl; + int ret; + + pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) + return -ENOMEM; + + pctrl->regmap = device_node_to_regmap(pdev->dev.parent->of_node); + if (IS_ERR(pctrl->regmap)) + dev_err_probe(dev, PTR_ERR(pctrl->regmap), "Failed to find syscon regmap\n"); + + pctrl->sysreg_regmap = syscon_regmap_lookup_by_compatible("microchip,mpfs-sysreg-scb"); + if (IS_ERR(pctrl->sysreg_regmap)) + return PTR_ERR(pctrl->sysreg_regmap); + + pctrl->desc.name = dev_name(dev); + pctrl->desc.pins = mpfs_pinctrl_pins; + pctrl->desc.npins = ARRAY_SIZE(mpfs_pinctrl_pins); + pctrl->desc.pctlops = &mpfs_pinctrl_ops; + pctrl->desc.pmxops = &mpfs_pinctrl_pinmux_ops; + pctrl->desc.confops = &mpfs_pinctrl_pinconf_ops; + pctrl->desc.owner = THIS_MODULE; + pctrl->desc.num_custom_params = ARRAY_SIZE(mpfs_pinctrl_custom_bindings); + pctrl->desc.custom_params = mpfs_pinctrl_custom_bindings; + + pctrl->dev = dev; + + ret = devm_mutex_init(dev, &pctrl->mutex); + if (ret) + return ret; + + platform_set_drvdata(pdev, pctrl); + + pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl); + if (IS_ERR(pctrl->pctrl)) + return PTR_ERR(pctrl->pctrl); + + return 0; +} + +static const struct of_device_id mpfs_pinctrl_of_match[] = { + { .compatible = "microchip,mpfs-pinctrl-mssio" }, + { } +}; +MODULE_DEVICE_TABLE(of, mpfs_pinctrl_of_match); + +static struct platform_driver mpfs_pinctrl_driver = { + .driver = { + .name = "mpfs-pinctrl", + .of_match_table = mpfs_pinctrl_of_match, + }, + .probe = mpfs_pinctrl_probe, +}; +module_platform_driver(mpfs_pinctrl_driver); + +MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>"); +MODULE_DESCRIPTION("Polarfire SoC mssio pinctrl driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/pinctrl-pic64gx-gpio2.c b/drivers/pinctrl/microchip/pinctrl-pic64gx-gpio2.c index f322bb5e6181..a0b3e839cf3b 100644 --- a/drivers/pinctrl/pinctrl-pic64gx-gpio2.c +++ b/drivers/pinctrl/microchip/pinctrl-pic64gx-gpio2.c @@ -14,7 +14,7 @@ #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> -#include "pinctrl-utils.h" +#include "../pinctrl-utils.h" #define PIC64GX_PINMUX_REG 0x0 diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 366775841c63..94b1d057197c 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -385,75 +385,6 @@ out: } EXPORT_SYMBOL_GPL(pinconf_generic_parse_dt_config); -int pinconf_generic_dt_node_to_map_pinmux(struct pinctrl_dev *pctldev, - struct device_node *np, - struct pinctrl_map **map, - unsigned int *num_maps) -{ - struct device *dev = pctldev->dev; - struct device_node *pnode; - unsigned long *configs = NULL; - unsigned int num_configs = 0; - struct property *prop; - unsigned int reserved_maps; - int reserve; - int ret; - - prop = of_find_property(np, "pinmux", NULL); - if (!prop) { - dev_info(dev, "Missing pinmux property\n"); - return -ENOENT; - } - - pnode = of_get_parent(np); - if (!pnode) { - dev_info(dev, "Missing function node\n"); - return -EINVAL; - } - - reserved_maps = 0; - *map = NULL; - *num_maps = 0; - - ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, - &num_configs); - if (ret < 0) { - dev_err(dev, "%pOF: could not parse node property\n", np); - return ret; - } - - reserve = 1; - if (num_configs) - reserve++; - - ret = pinctrl_utils_reserve_map(pctldev, map, &reserved_maps, - num_maps, reserve); - if (ret < 0) - goto exit; - - ret = pinctrl_utils_add_map_mux(pctldev, map, - &reserved_maps, num_maps, np->name, - pnode->name); - if (ret < 0) - goto exit; - - if (num_configs) { - ret = pinctrl_utils_add_map_configs(pctldev, map, &reserved_maps, - num_maps, np->name, configs, - num_configs, PIN_MAP_TYPE_CONFIGS_GROUP); - if (ret < 0) - goto exit; - } - -exit: - kfree(configs); - if (ret) - pinctrl_utils_free_map(pctldev, *map, *num_maps); - - return ret; -} -EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map_pinmux); - int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev, struct device_node *np, struct pinctrl_map **map, unsigned int *reserved_maps, unsigned int *num_maps, diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h index e1ae71610526..2880adef476e 100644 --- a/drivers/pinctrl/pinconf.h +++ b/drivers/pinctrl/pinconf.h @@ -160,3 +160,19 @@ pinconf_generic_parse_dt_pinmux(struct device_node *np, struct device *dev, return -ENOTSUPP; } #endif + +#if defined(CONFIG_GENERIC_PINCTRL) && defined (CONFIG_OF) +int pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **maps, + unsigned int *num_maps); +#else +static inline int +pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **maps, + unsigned int *num_maps) +{ + return -ENOTSUPP; +} +#endif diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 2dac5c71eb00..2af94ef56434 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -21,11 +21,9 @@ #include <linux/gpio/driver.h> #include <linux/slab.h> #include <linux/platform_device.h> -#include <linux/mutex.h> #include <linux/acpi.h> #include <linux/seq_file.h> #include <linux/interrupt.h> -#include <linux/list.h> #include <linux/bitops.h> #include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinconf-generic.h> diff --git a/drivers/pinctrl/pinctrl-apple-gpio.c b/drivers/pinctrl/pinctrl-apple-gpio.c index e1a7bc8cf765..2bd5013b19ac 100644 --- a/drivers/pinctrl/pinctrl-apple-gpio.c +++ b/drivers/pinctrl/pinctrl-apple-gpio.c @@ -102,9 +102,9 @@ static u32 apple_gpio_get_reg(struct apple_gpio_pinctrl *pctl, static int apple_gpio_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *node, struct pinctrl_map **map, - unsigned *num_maps) + unsigned int *num_maps) { - unsigned reserved_maps; + unsigned int reserved_maps; struct apple_gpio_pinctrl *pctl; u32 pinfunc, pin, func; int num_pins, i, ret; @@ -170,8 +170,15 @@ static const struct pinctrl_ops apple_gpio_pinctrl_ops = { /* Pin multiplexer functions */ -static int apple_gpio_pinmux_set(struct pinctrl_dev *pctldev, unsigned func, - unsigned group) +static bool apple_gpio_pinmux_func_is_gpio(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + /* Function selector 0 is always the GPIO mode */ + return (selector == 0); +} + +static int apple_gpio_pinmux_set(struct pinctrl_dev *pctldev, unsigned int func, + unsigned int group) { struct apple_gpio_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); @@ -186,6 +193,7 @@ static const struct pinmux_ops apple_gpio_pinmux_ops = { .get_functions_count = pinmux_generic_get_function_count, .get_function_name = pinmux_generic_get_function_name, .get_function_groups = pinmux_generic_get_function_groups, + .function_is_gpio = apple_gpio_pinmux_func_is_gpio, .set_mux = apple_gpio_pinmux_set, .strict = true, }; @@ -202,7 +210,7 @@ static int apple_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) return GPIO_LINE_DIRECTION_IN; } -static int apple_gpio_get(struct gpio_chip *chip, unsigned offset) +static int apple_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct apple_gpio_pinctrl *pctl = gpiochip_get_data(chip); unsigned int reg = apple_gpio_get_reg(pctl, offset); diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index ec5351fc282e..41cbb46ac589 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -1053,6 +1053,12 @@ static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = { .last_bank_count = ATMEL_PIO_NPINS_PER_BANK, }; +static const struct atmel_pioctrl_data microchip_sama7d65_pioctrl_data = { + .nbanks = 5, + .last_bank_count = 14, /* sama7d65 has only PE0 to PE13 */ + .slew_rate_support = 1, +}; + static const struct atmel_pioctrl_data microchip_sama7g5_pioctrl_data = { .nbanks = 5, .last_bank_count = 8, /* sama7g5 has only PE0 to PE7 */ @@ -1064,6 +1070,9 @@ static const struct of_device_id atmel_pctrl_of_match[] = { .compatible = "atmel,sama5d2-pinctrl", .data = &atmel_sama5d2_pioctrl_data, }, { + .compatible = "microchip,sama7d65-pinctrl", + .data = µchip_sama7d65_pioctrl_data, + }, { .compatible = "microchip,sama7g5-pinctrl", .data = µchip_sama7g5_pioctrl_data, }, { diff --git a/drivers/pinctrl/pinctrl-aw9523.c b/drivers/pinctrl/pinctrl-aw9523.c index 479553a79216..02a24ac87ea4 100644 --- a/drivers/pinctrl/pinctrl-aw9523.c +++ b/drivers/pinctrl/pinctrl-aw9523.c @@ -291,14 +291,14 @@ static int aw9523_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, unsigned int mask, val; int i, rc; - mutex_lock(&awi->i2c_lock); + guard(mutex)(&awi->i2c_lock); for (i = 0; i < num_configs; i++) { param = pinconf_to_config_param(configs[i]); arg = pinconf_to_config_argument(configs[i]); rc = aw9523_pcfg_param_to_reg(param, pin, ®); if (rc) - goto end; + return rc; switch (param) { case PIN_CONFIG_LEVEL: @@ -307,7 +307,7 @@ static int aw9523_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, AW9523_REG_CONF_STATE(pin), BIT(regbit), 0); if (rc) - goto end; + return rc; /* Then, fall through to config output level */ fallthrough; @@ -323,10 +323,9 @@ static int aw9523_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, break; case PIN_CONFIG_DRIVE_OPEN_DRAIN: /* Open-Drain is supported only on port 0 */ - if (pin >= AW9523_PINS_PER_PORT) { - rc = -ENOTSUPP; - goto end; - } + if (pin >= AW9523_PINS_PER_PORT) + return -ENOTSUPP; + mask = AW9523_GCR_GPOMD_MASK; val = 0; break; @@ -341,17 +340,15 @@ static int aw9523_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, val = AW9523_GCR_GPOMD_MASK; break; default: - rc = -ENOTSUPP; - goto end; + return -ENOTSUPP; } rc = regmap_update_bits(awi->regmap, reg, mask, val); if (rc) - goto end; + return rc; } -end: - mutex_unlock(&awi->i2c_lock); - return rc; + + return 0; } static const struct pinconf_ops aw9523_pinconf_ops = { @@ -599,14 +596,14 @@ static int aw9523_gpio_get_multiple(struct gpio_chip *chip, u8 m, state = 0; int ret; - mutex_lock(&awi->i2c_lock); + guard(mutex)(&awi->i2c_lock); /* Port 0 (gpio 0-7) */ m = *mask; if (m) { ret = _aw9523_gpio_get_multiple(awi, 0, &state, m); if (ret) - goto out; + return ret; } *bits = state; @@ -616,13 +613,12 @@ static int aw9523_gpio_get_multiple(struct gpio_chip *chip, ret = _aw9523_gpio_get_multiple(awi, AW9523_PINS_PER_PORT, &state, m); if (ret) - goto out; + return ret; *bits |= (state << 8); } -out: - mutex_unlock(&awi->i2c_lock); - return ret; + + return 0; } static int aw9523_gpio_set_multiple(struct gpio_chip *chip, @@ -632,30 +628,28 @@ static int aw9523_gpio_set_multiple(struct gpio_chip *chip, struct aw9523 *awi = gpiochip_get_data(chip); u8 mask_lo, mask_hi, bits_lo, bits_hi; unsigned int reg; - int ret = 0; + int ret; mask_lo = *mask; mask_hi = *mask >> 8; bits_lo = *bits; bits_hi = *bits >> 8; - mutex_lock(&awi->i2c_lock); + guard(mutex)(&awi->i2c_lock); if (mask_hi) { reg = AW9523_REG_OUT_STATE(AW9523_PINS_PER_PORT); ret = regmap_write_bits(awi->regmap, reg, mask_hi, bits_hi); if (ret) - goto out; + return ret; } if (mask_lo) { reg = AW9523_REG_OUT_STATE(0); ret = regmap_write_bits(awi->regmap, reg, mask_lo, bits_lo); if (ret) - goto out; + return ret; } -out: - mutex_unlock(&awi->i2c_lock); - return ret; + return 0; } static int aw9523_gpio_set(struct gpio_chip *chip, unsigned int offset, @@ -695,16 +689,15 @@ static int aw9523_direction_output(struct gpio_chip *chip, u8 regbit = offset % AW9523_PINS_PER_PORT; int ret; - mutex_lock(&awi->i2c_lock); + guard(mutex)(&awi->i2c_lock); ret = regmap_update_bits(awi->regmap, AW9523_REG_OUT_STATE(offset), BIT(regbit), value ? BIT(regbit) : 0); if (ret) - goto end; + return ret; ret = regmap_update_bits(awi->regmap, AW9523_REG_CONF_STATE(offset), BIT(regbit), 0); -end: - mutex_unlock(&awi->i2c_lock); + return ret; } diff --git a/drivers/pinctrl/pinctrl-equilibrium.c b/drivers/pinctrl/pinctrl-equilibrium.c index 2d04829b29c9..48b55c5bf8d4 100644 --- a/drivers/pinctrl/pinctrl-equilibrium.c +++ b/drivers/pinctrl/pinctrl-equilibrium.c @@ -846,6 +846,7 @@ static int pinbank_init(struct device_node *np, bank->pin_base = spec.args[1]; bank->nr_pins = spec.args[2]; + of_node_put(spec.np); bank->aval_pinmap = readl(bank->membase + REG_AVAIL); bank->id = id; diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c new file mode 100644 index 000000000000..efb39c6a6703 --- /dev/null +++ b/drivers/pinctrl/pinctrl-generic.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define pr_fmt(fmt) "generic pinconfig core: " fmt + +#include <linux/array_size.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/slab.h> + +#include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinctrl.h> + +#include "core.h" +#include "pinconf.h" +#include "pinctrl-utils.h" +#include "pinmux.h" + +static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *parent, + struct device_node *np, + struct pinctrl_map **maps, + unsigned int *num_maps, + unsigned int *num_reserved_maps, + const char **group_names, + unsigned int ngroups) +{ + struct device *dev = pctldev->dev; + const char **functions; + const char *group_name; + unsigned long *configs; + unsigned int num_configs, pin, *pins; + int npins, ret, reserve = 1; + + npins = of_property_count_u32_elems(np, "pins"); + + if (npins < 1) { + dev_err(dev, "invalid pinctrl group %pOFn.%pOFn %d\n", + parent, np, npins); + return npins; + } + + group_name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn", parent, np); + if (!group_name) + return -ENOMEM; + + group_names[ngroups] = group_name; + + pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL); + if (!pins) + return -ENOMEM; + + functions = devm_kcalloc(dev, npins, sizeof(*functions), GFP_KERNEL); + if (!functions) + return -ENOMEM; + + for (int i = 0; i < npins; i++) { + ret = of_property_read_u32_index(np, "pins", i, &pin); + if (ret) + return ret; + + pins[i] = pin; + + ret = of_property_read_string(np, "function", &functions[i]); + if (ret) + return ret; + } + + ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve); + if (ret) + return ret; + + ret = pinctrl_utils_add_map_mux(pctldev, maps, num_reserved_maps, num_maps, group_name, + parent->name); + if (ret < 0) + return ret; + + ret = pinctrl_generic_add_group(pctldev, group_name, pins, npins, functions); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to add group %s: %d\n", + group_name, ret); + + ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs); + if (ret) + return dev_err_probe(dev, ret, "failed to parse pin config of group %s\n", + group_name); + + if (num_configs == 0) + return 0; + + ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve); + if (ret) + return ret; + + ret = pinctrl_utils_add_map_configs(pctldev, maps, num_reserved_maps, num_maps, group_name, + configs, + num_configs, PIN_MAP_TYPE_CONFIGS_GROUP); + kfree(configs); + if (ret) + return ret; + + return 0; +}; + +/* + * For platforms that do not define groups or functions in the driver, but + * instead use the devicetree to describe them. This function will, unlike + * pinconf_generic_dt_node_to_map() etc which rely on driver defined groups + * and functions, create them in addition to parsing pinconf properties and + * adding mappings. + */ +int pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **maps, + unsigned int *num_maps) +{ + struct device *dev = pctldev->dev; + struct device_node *child_np; + const char **group_names; + unsigned int num_reserved_maps = 0; + int ngroups = 0; + int ret; + + *maps = NULL; + *num_maps = 0; + + /* + * Check if this is actually the pins node, or a parent containing + * multiple pins nodes. + */ + if (!of_property_present(np, "pins")) + goto parent; + + group_names = devm_kcalloc(dev, 1, sizeof(*group_names), GFP_KERNEL); + if (!group_names) + return -ENOMEM; + + ret = pinctrl_generic_pins_function_dt_subnode_to_map(pctldev, np, np, + maps, num_maps, + &num_reserved_maps, + group_names, + ngroups); + if (ret) { + pinctrl_utils_free_map(pctldev, *maps, *num_maps); + return dev_err_probe(dev, ret, "error figuring out mappings for %s\n", np->name); + } + + ret = pinmux_generic_add_function(pctldev, np->name, group_names, 1, NULL); + if (ret < 0) { + pinctrl_utils_free_map(pctldev, *maps, *num_maps); + return dev_err_probe(dev, ret, "error adding function %s\n", np->name); + } + + return 0; + +parent: + for_each_available_child_of_node(np, child_np) + ngroups += 1; + + group_names = devm_kcalloc(dev, ngroups, sizeof(*group_names), GFP_KERNEL); + if (!group_names) + return -ENOMEM; + + ngroups = 0; + for_each_available_child_of_node_scoped(np, child_np) { + ret = pinctrl_generic_pins_function_dt_subnode_to_map(pctldev, np, child_np, + maps, num_maps, + &num_reserved_maps, + group_names, + ngroups); + if (ret) { + pinctrl_utils_free_map(pctldev, *maps, *num_maps); + return dev_err_probe(dev, ret, "error figuring out mappings for %s\n", + np->name); + } + + ngroups++; + } + + ret = pinmux_generic_add_function(pctldev, np->name, group_names, ngroups, NULL); + if (ret < 0) { + pinctrl_utils_free_map(pctldev, *maps, *num_maps); + return dev_err_probe(dev, ret, "error adding function %s\n", np->name); + } + + return 0; +} +EXPORT_SYMBOL_GPL(pinctrl_generic_pins_function_dt_node_to_map); diff --git a/drivers/pinctrl/pinctrl-k230.c b/drivers/pinctrl/pinctrl-k230.c index d716f23d837f..20f7c0f70eb7 100644 --- a/drivers/pinctrl/pinctrl-k230.c +++ b/drivers/pinctrl/pinctrl-k230.c @@ -65,6 +65,7 @@ struct k230_pmx_func { }; struct k230_pinctrl { + struct device *dev; struct pinctrl_desc pctl; struct pinctrl_dev *pctl_dev; struct regmap *regmap_base; @@ -470,7 +471,7 @@ static int k230_pinctrl_parse_groups(struct device_node *np, struct k230_pinctrl *info, unsigned int index) { - struct device *dev = info->pctl_dev->dev; + struct device *dev = info->dev; const __be32 *list; int size, i, ret; @@ -511,7 +512,7 @@ static int k230_pinctrl_parse_functions(struct device_node *np, struct k230_pinctrl *info, unsigned int index) { - struct device *dev = info->pctl_dev->dev; + struct device *dev = info->dev; struct k230_pmx_func *func; struct k230_pin_group *grp; static unsigned int idx, i; @@ -596,6 +597,8 @@ static int k230_pinctrl_probe(struct platform_device *pdev) if (!info) return -ENOMEM; + info->dev = dev; + pctl = &info->pctl; pctl->name = "k230-pinctrl"; diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c index b6363f3cdce9..7a6cb5f502b0 100644 --- a/drivers/pinctrl/pinctrl-microchip-sgpio.c +++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c @@ -264,19 +264,17 @@ static int sgpio_single_shot(struct sgpio_priv *priv) * setting. * After the manual burst, reenable the auto repeat mode again. */ - mutex_lock(&priv->poll_lock); + guard(mutex)(&priv->poll_lock); ret = regmap_update_bits(priv->regs, addr, single_shot | auto_repeat, single_shot); if (ret) - goto out; + return ret; ret = regmap_read_poll_timeout(priv->regs, addr, ctrl, !(ctrl & single_shot), 100, 60000); /* reenable auto repeat mode even if there was an error */ ret2 = regmap_update_bits(priv->regs, addr, auto_repeat, auto_repeat); -out: - mutex_unlock(&priv->poll_lock); return ret ?: ret2; } diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c index 70da3f37567a..6ea9544ddd06 100644 --- a/drivers/pinctrl/pinctrl-ocelot.c +++ b/drivers/pinctrl/pinctrl-ocelot.c @@ -97,6 +97,8 @@ enum { FUNC_FC_SHRD20, FUNC_FUSA, FUNC_GPIO, + FUNC_I2C, + FUNC_I2C_Sa, FUNC_IB_TRG_a, FUNC_IB_TRG_b, FUNC_IB_TRG_c, @@ -112,9 +114,11 @@ enum { FUNC_IRQ1, FUNC_IRQ1_IN, FUNC_IRQ1_OUT, + FUNC_IRQ2, FUNC_IRQ3, FUNC_IRQ4, FUNC_EXT_IRQ, + FUNC_MACLED, FUNC_MIIM, FUNC_MIIM_a, FUNC_MIIM_b, @@ -126,6 +130,7 @@ enum { FUNC_OB_TRG_a, FUNC_OB_TRG_b, FUNC_PHY_LED, + FUNC_PHY_DBG, FUNC_PCI_WAKE, FUNC_MD, FUNC_PCIE_PERST, @@ -156,10 +161,12 @@ enum { FUNC_SG0, FUNC_SG1, FUNC_SG2, + FUNC_SPI, FUNC_SGPIO_a, FUNC_SGPIO_b, FUNC_SI, FUNC_SI2, + FUNC_SI_Sa, FUNC_SYNCE, FUNC_TACHO, FUNC_TACHO_a, @@ -188,6 +195,7 @@ enum { FUNC_EMMC_SD, FUNC_REF_CLK, FUNC_RCVRD_CLK, + FUNC_RGMII, FUNC_MAX }; @@ -237,6 +245,8 @@ static const char *const ocelot_function_names[] = { [FUNC_FC_SHRD20] = "fc_shrd20", [FUNC_FUSA] = "fusa", [FUNC_GPIO] = "gpio", + [FUNC_I2C] = "i2c", + [FUNC_I2C_Sa] = "i2c_slave_a", [FUNC_IB_TRG_a] = "ib_trig_a", [FUNC_IB_TRG_b] = "ib_trig_b", [FUNC_IB_TRG_c] = "ib_trig_c", @@ -252,9 +262,11 @@ static const char *const ocelot_function_names[] = { [FUNC_IRQ1] = "irq1", [FUNC_IRQ1_IN] = "irq1_in", [FUNC_IRQ1_OUT] = "irq1_out", + [FUNC_IRQ2] = "irq2", [FUNC_IRQ3] = "irq3", [FUNC_IRQ4] = "irq4", [FUNC_EXT_IRQ] = "ext_irq", + [FUNC_MACLED] = "mac_led", [FUNC_MIIM] = "miim", [FUNC_MIIM_a] = "miim_a", [FUNC_MIIM_b] = "miim_b", @@ -263,6 +275,7 @@ static const char *const ocelot_function_names[] = { [FUNC_MIIM_Sb] = "miim_slave_b", [FUNC_MIIM_IRQ] = "miim_irq", [FUNC_PHY_LED] = "phy_led", + [FUNC_PHY_DBG] = "phy_dbg", [FUNC_PCI_WAKE] = "pci_wake", [FUNC_PCIE_PERST] = "pcie_perst", [FUNC_MD] = "md", @@ -300,6 +313,8 @@ static const char *const ocelot_function_names[] = { [FUNC_SGPIO_b] = "sgpio_b", [FUNC_SI] = "si", [FUNC_SI2] = "si2", + [FUNC_SI_Sa] = "si_slave_a", + [FUNC_SPI] = "spi", [FUNC_SYNCE] = "synce", [FUNC_TACHO] = "tacho", [FUNC_TACHO_a] = "tacho_a", @@ -328,6 +343,7 @@ static const char *const ocelot_function_names[] = { [FUNC_EMMC_SD] = "emmc_sd", [FUNC_REF_CLK] = "ref_clk", [FUNC_RCVRD_CLK] = "rcvrd_clk", + [FUNC_RGMII] = "rgmii", }; struct ocelot_pmx_func { @@ -358,12 +374,14 @@ struct ocelot_pinctrl { const struct ocelot_pincfg_data *pincfg_data; struct ocelot_pmx_func func[FUNC_MAX]; u8 stride; + u8 altm_stride; struct workqueue_struct *wq; }; struct ocelot_match_data { struct pinctrl_desc desc; struct ocelot_pincfg_data pincfg_data; + unsigned int n_alt_modes; }; struct ocelot_irq_work { @@ -1321,6 +1339,132 @@ static const struct pinctrl_pin_desc lan969x_pins[] = { LAN969X_PIN(66), }; +#define LAN9645X_P(p, f0, f1, f2, f3, f4, f5, f6, f7) \ +static struct ocelot_pin_caps lan9645x_pin_##p = { \ + .pin = p, \ + .functions = { \ + FUNC_##f0, FUNC_##f1, FUNC_##f2, \ + FUNC_##f3 \ + }, \ + .a_functions = { \ + FUNC_##f4, FUNC_##f5, FUNC_##f6, \ + FUNC_##f7 \ + }, \ +} + +/* Pin FUNC0 FUNC1 FUNC2 FUNC3 FUNC4 FUNC5 FUNC6 FUNC7 */ +LAN9645X_P(0, GPIO, SPI, SI_Sa, I2C_Sa, MIIM_Sa, UART, MIIM, PHY_DBG); +LAN9645X_P(1, GPIO, SPI, SI_Sa, I2C_Sa, MIIM_Sa, UART, MIIM, PHY_DBG); +LAN9645X_P(2, GPIO, SPI, SI_Sa, I2C, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(3, GPIO, SPI, SI_Sa, I2C, MIIM_Sa, NONE, NONE, PHY_DBG); +LAN9645X_P(4, GPIO, RGMII, TWI_SCL_M, I2C, NONE, NONE, SI_Sa, PHY_DBG); +LAN9645X_P(5, GPIO, RGMII, TWI_SCL_M, I2C, NONE, NONE, SI_Sa, PHY_DBG); +LAN9645X_P(6, GPIO, RGMII, TWI_SCL_M, NONE, NONE, NONE, SI_Sa, PHY_DBG); +LAN9645X_P(7, GPIO, RGMII, TWI_SCL_M, SFP, SGPIO_a, MIIM, SI_Sa, PHY_DBG); +LAN9645X_P(8, GPIO, RGMII, TWI_SCL_M, SFP, SGPIO_a, MIIM, NONE, PHY_DBG); +LAN9645X_P(9, GPIO, RGMII, TWI_SCL_M, RECO_CLK, SGPIO_a, IRQ1, UART, PHY_DBG); +LAN9645X_P(10, GPIO, RGMII, TWI_SCL_M, RECO_CLK, SGPIO_a, IRQ2, UART, PHY_DBG); +LAN9645X_P(11, GPIO, RGMII, TWI_SCL_M, MIIM, NONE, IRQ3, NONE, PHY_DBG); +LAN9645X_P(12, GPIO, RGMII, TWI_SCL_M, MIIM, PTP0, NONE, NONE, PHY_DBG); +LAN9645X_P(13, GPIO, RGMII, TWI_SCL_M, CLKMON, PTP1, MACLED, NONE, PHY_DBG); +LAN9645X_P(14, GPIO, RGMII, TWI_SCL_M, CLKMON, PTP2, MACLED, NONE, PHY_DBG); +LAN9645X_P(15, GPIO, RGMII, TWI_SCL_M, CLKMON, PTP3, NONE, NONE, PHY_DBG); +LAN9645X_P(16, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(17, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(18, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(19, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(20, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(21, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(22, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(23, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(24, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(25, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(26, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(27, GPIO, RGMII, NONE, NONE, NONE, NONE, NONE, PHY_DBG); +LAN9645X_P(28, GPIO, RECO_CLK, MIIM, NONE, NONE, NONE, NONE, R); +LAN9645X_P(29, GPIO, RECO_CLK, MIIM, NONE, NONE, NONE, NONE, R); +LAN9645X_P(30, GPIO, PTP0, I2C, UART, NONE, NONE, NONE, R); +LAN9645X_P(31, GPIO, PTP1, TWI_SCL_M, UART, NONE, NONE, NONE, R); +LAN9645X_P(32, GPIO, PTP2, TWI_SCL_M, NONE, NONE, NONE, NONE, R); +LAN9645X_P(33, GPIO, PTP3, IRQ0, NONE, NONE, NONE, NONE, R); +LAN9645X_P(34, GPIO, RECO_CLK, PHY_LED, PHY_LED, NONE, NONE, NONE, R); +LAN9645X_P(35, GPIO, RECO_CLK, PHY_LED, PHY_LED, NONE, MACLED, NONE, R); +LAN9645X_P(36, GPIO, PTP0, PHY_LED, PHY_LED, NONE, MACLED, NONE, R); +LAN9645X_P(37, GPIO, PTP1, PHY_LED, PHY_LED, NONE, MACLED, NONE, R); +LAN9645X_P(38, GPIO, NONE, PHY_LED, PHY_LED, NONE, MACLED, NONE, R); +LAN9645X_P(39, GPIO, UART, PHY_LED, NONE, NONE, MACLED, NONE, R); +LAN9645X_P(40, GPIO, SPI, PHY_LED, SGPIO_a, NONE, MACLED, NONE, R); +LAN9645X_P(41, GPIO, SPI, PHY_LED, SGPIO_a, IRQ1, MACLED, NONE, R); +LAN9645X_P(42, GPIO, SPI, PHY_LED, SGPIO_a, IRQ2, MACLED, SFP, R); +LAN9645X_P(43, GPIO, SPI, PHY_LED, SGPIO_a, IRQ3, MACLED, SFP, R); +LAN9645X_P(44, GPIO, MIIM, I2C, NONE, NONE, NONE, NONE, R); +LAN9645X_P(45, GPIO, MIIM, I2C, NONE, NONE, NONE, NONE, R); +LAN9645X_P(46, GPIO, NONE, PHY_LED, NONE, NONE, NONE, NONE, R); +LAN9645X_P(47, GPIO, NONE, PHY_LED, NONE, NONE, NONE, NONE, R); +LAN9645X_P(48, GPIO, MIIM_Sa, PHY_LED, NONE, NONE, NONE, NONE, R); +LAN9645X_P(49, GPIO, MIIM_Sa, PHY_LED, I2C_Sa, NONE, NONE, NONE, R); +LAN9645X_P(50, GPIO, MIIM_Sa, PHY_LED, I2C_Sa, NONE, NONE, NONE, R); + +#define LAN9645X_PIN(n) { \ + .number = n, \ + .name = "GPIO_"#n, \ + .drv_data = &lan9645x_pin_##n \ +} + +static const struct pinctrl_pin_desc lan9645x_pins[] = { + LAN9645X_PIN(0), + LAN9645X_PIN(1), + LAN9645X_PIN(2), + LAN9645X_PIN(3), + LAN9645X_PIN(4), + LAN9645X_PIN(5), + LAN9645X_PIN(6), + LAN9645X_PIN(7), + LAN9645X_PIN(8), + LAN9645X_PIN(9), + LAN9645X_PIN(10), + LAN9645X_PIN(11), + LAN9645X_PIN(12), + LAN9645X_PIN(13), + LAN9645X_PIN(14), + LAN9645X_PIN(15), + LAN9645X_PIN(16), + LAN9645X_PIN(17), + LAN9645X_PIN(18), + LAN9645X_PIN(19), + LAN9645X_PIN(20), + LAN9645X_PIN(21), + LAN9645X_PIN(22), + LAN9645X_PIN(23), + LAN9645X_PIN(24), + LAN9645X_PIN(25), + LAN9645X_PIN(26), + LAN9645X_PIN(27), + LAN9645X_PIN(28), + LAN9645X_PIN(29), + LAN9645X_PIN(30), + LAN9645X_PIN(31), + LAN9645X_PIN(32), + LAN9645X_PIN(33), + LAN9645X_PIN(34), + LAN9645X_PIN(35), + LAN9645X_PIN(36), + LAN9645X_PIN(37), + LAN9645X_PIN(38), + LAN9645X_PIN(39), + LAN9645X_PIN(40), + LAN9645X_PIN(41), + LAN9645X_PIN(42), + LAN9645X_PIN(43), + LAN9645X_PIN(44), + LAN9645X_PIN(45), + LAN9645X_PIN(46), + LAN9645X_PIN(47), + LAN9645X_PIN(48), + LAN9645X_PIN(49), + LAN9645X_PIN(50), +}; + static int ocelot_get_functions_count(struct pinctrl_dev *pctldev) { return ARRAY_SIZE(ocelot_function_names); @@ -1362,7 +1506,7 @@ static int ocelot_pin_function_idx(struct ocelot_pinctrl *info, return -1; } -#define REG_ALT(msb, info, p) (OCELOT_GPIO_ALT0 * (info)->stride + 4 * ((msb) + ((info)->stride * ((p) / 32)))) +#define REG_ALT(msb, info, p) (OCELOT_GPIO_ALT0 * (info)->stride + 4 * ((msb) + ((info)->altm_stride * ((p) / 32)))) static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int selector, unsigned int group) @@ -1469,6 +1613,13 @@ static int lan966x_gpio_request_enable(struct pinctrl_dev *pctldev, return 0; } +static int lan9645x_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + return 0; +} + static const struct pinmux_ops ocelot_pmx_ops = { .get_functions_count = ocelot_get_functions_count, .get_function_name = ocelot_get_function_name, @@ -1487,6 +1638,15 @@ static const struct pinmux_ops lan966x_pmx_ops = { .gpio_request_enable = lan966x_gpio_request_enable, }; +static const struct pinmux_ops lan9645x_pmx_ops = { + .get_functions_count = ocelot_get_functions_count, + .get_function_name = ocelot_get_function_name, + .get_function_groups = ocelot_get_function_groups, + .set_mux = lan966x_pinmux_set_mux, + .gpio_set_direction = ocelot_gpio_set_direction, + .gpio_request_enable = lan9645x_gpio_request_enable, +}; + static int ocelot_pctl_get_groups_count(struct pinctrl_dev *pctldev) { struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); @@ -1884,6 +2044,24 @@ static const struct ocelot_match_data lan969x_desc = { }, }; +static struct ocelot_match_data lan9645xf_desc = { + .desc = { + .name = "lan9645xf-pinctrl", + .pins = lan9645x_pins, + .npins = ARRAY_SIZE(lan9645x_pins), + .pctlops = &ocelot_pctl_ops, + .pmxops = &lan9645x_pmx_ops, + .confops = &ocelot_confops, + .owner = THIS_MODULE, + }, + .pincfg_data = { + .pd_bit = BIT(3), + .pu_bit = BIT(2), + .drive_bits = GENMASK(1, 0), + }, + .n_alt_modes = 7, +}; + static int ocelot_create_group_func_map(struct device *dev, struct ocelot_pinctrl *info) { @@ -2218,6 +2396,7 @@ static const struct of_device_id ocelot_pinctrl_of_match[] = { { .compatible = "microchip,sparx5-pinctrl", .data = &sparx5_desc }, { .compatible = "microchip,lan966x-pinctrl", .data = &lan966x_desc }, { .compatible = "microchip,lan9691-pinctrl", .data = &lan969x_desc }, + { .compatible = "microchip,lan96455f-pinctrl", .data = &lan9645xf_desc }, {}, }; MODULE_DEVICE_TABLE(of, ocelot_pinctrl_of_match); @@ -2294,6 +2473,9 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev) reset_control_reset(reset); info->stride = 1 + (info->desc->npins - 1) / 32; + info->altm_stride = info->stride; + if (data->n_alt_modes) + info->altm_stride = fls(data->n_alt_modes); regmap_config.max_register = OCELOT_GPIO_SD_MAP * info->stride + 15 * 4; diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 2fc67aeafdb3..816823403e97 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -3639,17 +3639,16 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, * The lock makes sure that either gpio-probe has completed * or the gpio driver hasn't probed yet. */ - mutex_lock(&bank->deferred_lock); - if (!gpio || !gpio->direction_output) { - rc = rockchip_pinconf_defer_pin(bank, pin - bank->pin_base, param, - arg); - mutex_unlock(&bank->deferred_lock); - if (rc) - return rc; - - break; + scoped_guard(mutex, &bank->deferred_lock) { + if (!gpio || !gpio->direction_output) { + rc = rockchip_pinconf_defer_pin(bank, + pin - bank->pin_base, + param, arg); + if (rc) + return rc; + break; + } } - mutex_unlock(&bank->deferred_lock); } switch (param) { diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c index af3ac031e362..d5fb8649cd9a 100644 --- a/drivers/pinctrl/pinctrl-scmi.c +++ b/drivers/pinctrl/pinctrl-scmi.c @@ -504,8 +504,9 @@ static int pinctrl_scmi_get_pins(struct scmi_pinctrl *pmx, } static const char * const scmi_pinctrl_blocklist[] = { - "fsl,imx95", "fsl,imx94", + "fsl,imx95", + "fsl,imx952", NULL }; diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 998f23d6c317..d85e6c1f6321 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1359,6 +1359,7 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs) } range = devm_kzalloc(pcs->dev, sizeof(*range), GFP_KERNEL); if (!range) { + of_node_put(gpiospec.np); ret = -ENOMEM; break; } @@ -1368,6 +1369,7 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs) mutex_lock(&pcs->mutex); list_add_tail(&range->node, &pcs->gpiofuncs); mutex_unlock(&pcs->mutex); + of_node_put(gpiospec.np); } return ret; } diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index d3cea3437d7f..8ce88e591f47 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -987,6 +987,7 @@ static int st_pinconf_get(struct pinctrl_dev *pctldev, static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned pin_id) + __must_hold(&pctldev->mutex) { struct st_pio_control *pc; unsigned long config; diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c index 129fa51d13b1..3f581404a9b9 100644 --- a/drivers/pinctrl/pinctrl-tb10x.c +++ b/drivers/pinctrl/pinctrl-tb10x.c @@ -607,7 +607,7 @@ static int tb10x_gpio_request_enable(struct pinctrl_dev *pctl, int muxmode = -1; int i; - mutex_lock(&state->mutex); + guard(mutex)(&state->mutex); /* * Figure out to which port the requested GPIO belongs and how to @@ -642,7 +642,6 @@ static int tb10x_gpio_request_enable(struct pinctrl_dev *pctl, * Error: The requested pin is already * used for something else. */ - mutex_unlock(&state->mutex); return -EBUSY; } break; @@ -667,8 +666,6 @@ static int tb10x_gpio_request_enable(struct pinctrl_dev *pctl, if (muxport >= 0) tb10x_pinctrl_set_config(state, muxport, muxmode); - mutex_unlock(&state->mutex); - return 0; } @@ -695,34 +692,28 @@ static int tb10x_pctl_set_mux(struct pinctrl_dev *pctl, if (grp->port < 0) return 0; - mutex_lock(&state->mutex); + guard(mutex)(&state->mutex); /* * Check if the requested function is compatible with previously * requested functions. */ if (state->ports[grp->port].count - && (state->ports[grp->port].mode != grp->mode)) { - mutex_unlock(&state->mutex); + && (state->ports[grp->port].mode != grp->mode)) return -EBUSY; - } /* * Check if the requested function is compatible with previously * requested GPIOs. */ for (i = 0; i < grp->pincnt; i++) - if (test_bit(grp->pins[i], state->gpios)) { - mutex_unlock(&state->mutex); + if (test_bit(grp->pins[i], state->gpios)) return -EBUSY; - } tb10x_pinctrl_set_config(state, grp->port, grp->mode); state->ports[grp->port].count++; - mutex_unlock(&state->mutex); - return 0; } diff --git a/drivers/pinctrl/qcom/pinctrl-glymur.c b/drivers/pinctrl/qcom/pinctrl-glymur.c index 335005084b6b..44f9745325b7 100644 --- a/drivers/pinctrl/qcom/pinctrl-glymur.c +++ b/drivers/pinctrl/qcom/pinctrl-glymur.c @@ -1729,6 +1729,26 @@ static const struct msm_gpio_wakeirq_map glymur_pdc_map[] = { { 232, 206 }, { 234, 172 }, { 235, 173 }, { 242, 158 }, { 244, 156 }, }; +static const struct msm_gpio_wakeirq_map mahua_pdc_map[] = { + { 0, 116 }, { 2, 114 }, { 3, 115 }, { 4, 175 }, { 5, 176 }, + { 7, 111 }, { 11, 129 }, { 13, 130 }, { 15, 112 }, { 19, 113 }, + { 23, 187 }, { 27, 188 }, { 28, 121 }, { 29, 122 }, { 30, 136 }, + { 31, 203 }, { 32, 189 }, { 34, 174 }, { 35, 190 }, { 36, 191 }, + { 39, 124 }, { 43, 192 }, { 47, 193 }, { 51, 123 }, { 53, 133 }, + { 55, 125 }, { 59, 131 }, { 64, 134 }, { 65, 150 }, { 66, 186 }, + { 67, 132 }, { 68, 195 }, { 71, 135 }, { 75, 196 }, { 79, 197 }, + { 83, 198 }, { 84, 181 }, { 85, 199 }, { 87, 200 }, { 91, 201 }, + { 92, 182 }, { 93, 183 }, { 94, 184 }, { 95, 185 }, { 98, 202 }, + { 105, 157 }, { 113, 128 }, { 121, 117 }, { 123, 118 }, { 125, 119 }, + { 129, 120 }, { 131, 126 }, { 132, 160 }, { 133, 194 }, { 134, 127 }, + { 141, 137 }, { 144, 138 }, { 145, 139 }, { 147, 140 }, { 148, 141 }, + { 150, 146 }, { 151, 147 }, { 153, 148 }, { 154, 144 }, { 155, 159 }, + { 156, 149 }, { 157, 151 }, { 163, 142 }, { 172, 143 }, { 181, 145 }, + { 193, 161 }, { 196, 152 }, { 203, 177 }, { 208, 178 }, { 215, 162 }, + { 217, 153 }, { 220, 154 }, { 221, 155 }, { 228, 179 }, { 230, 180 }, + { 232, 206 }, { 234, 172 }, { 235, 173 }, { 242, 158 }, { 244, 156 }, +}; + static const struct msm_pinctrl_soc_data glymur_tlmm = { .pins = glymur_pins, .npins = ARRAY_SIZE(glymur_pins), @@ -1742,14 +1762,34 @@ static const struct msm_pinctrl_soc_data glymur_tlmm = { .egpio_func = 11, }; +static const struct msm_pinctrl_soc_data mahua_tlmm = { + .pins = glymur_pins, + .npins = ARRAY_SIZE(glymur_pins), + .functions = glymur_functions, + .nfunctions = ARRAY_SIZE(glymur_functions), + .groups = glymur_groups, + .ngroups = ARRAY_SIZE(glymur_groups), + .ngpios = 251, + .wakeirq_map = mahua_pdc_map, + .nwakeirq_map = ARRAY_SIZE(mahua_pdc_map), + .egpio_func = 11, +}; + static const struct of_device_id glymur_tlmm_of_match[] = { - { .compatible = "qcom,glymur-tlmm", }, - { } + { .compatible = "qcom,glymur-tlmm", .data = &glymur_tlmm }, + { .compatible = "qcom,mahua-tlmm", .data = &mahua_tlmm }, + { }, }; static int glymur_tlmm_probe(struct platform_device *pdev) { - return msm_pinctrl_probe(pdev, &glymur_tlmm); + const struct msm_pinctrl_soc_data *data; + + data = of_device_get_match_data(&pdev->dev); + if (!data) + return -ENODEV; + + return msm_pinctrl_probe(pdev, data); } static struct platform_driver glymur_tlmm_driver = { diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c index 64494a86490e..c27452eece3e 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c @@ -73,7 +73,7 @@ static const char * const i2s1_ws_groups[] = { "gpio7" }; static const char * const i2s1_data_groups[] = { "gpio8", "gpio9" }; static const char * const wsa_swr_clk_groups[] = { "gpio10" }; static const char * const wsa_swr_data_groups[] = { "gpio11" }; -static const char * const i2s2_data_groups[] = { "gpio12", "gpio12" }; +static const char * const i2s2_data_groups[] = { "gpio12", "gpio13" }; static const struct lpi_pingroup sm8250_groups[] = { LPI_PINGROUP(0, 0, swr_tx_clk, qua_mi2s_sclk, _, _), diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig index 8cbd79a13414..d979e25e5088 100644 --- a/drivers/pinctrl/renesas/Kconfig +++ b/drivers/pinctrl/renesas/Kconfig @@ -308,9 +308,11 @@ config PINCTRL_RZT2H bool "pin control support for RZ/N2H and RZ/T2H" if COMPILE_TEST depends on 64BIT && OF select GPIOLIB + select GPIOLIB_IRQCHIP select GENERIC_PINCTRL_GROUPS select GENERIC_PINMUX_FUNCTIONS select GENERIC_PINCONF + select IRQ_DOMAIN_HIERARCHY help This selects GPIO and pinctrl driver for Renesas RZ/T2H platforms. diff --git a/drivers/pinctrl/renesas/pinctrl-rzt2h.c b/drivers/pinctrl/renesas/pinctrl-rzt2h.c index 4826ff91cd90..9949108a35bb 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzt2h.c +++ b/drivers/pinctrl/renesas/pinctrl-rzt2h.c @@ -18,6 +18,7 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/of_device.h> +#include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/spinlock.h> @@ -51,6 +52,7 @@ #define PFC_MASK GENMASK_ULL(5, 0) #define PFC_PIN_MASK(pin) (PFC_MASK << ((pin) * 8)) +#define PFC_FUNC_INTERRUPT 0 /* * Use 16 lower bits [15:0] for pin identifier @@ -64,6 +66,9 @@ #define RZT2H_MAX_SAFETY_PORTS 12 +#define RZT2H_INTERRUPTS_START 16 +#define RZT2H_INTERRUPTS_NUM 17 + struct rzt2h_pinctrl_data { unsigned int n_port_pins; const u8 *port_pin_configs; @@ -79,9 +84,11 @@ struct rzt2h_pinctrl { struct device *dev; struct gpio_chip gpio_chip; struct pinctrl_gpio_range gpio_range; + DECLARE_BITMAP(used_irqs, RZT2H_INTERRUPTS_NUM); spinlock_t lock; /* lock read/write registers */ struct mutex mutex; /* serialize adding groups and functions */ bool safety_port_enabled; + atomic_t wakeup_path; }; #define RZT2H_GET_BASE(pctrl, port) \ @@ -119,6 +126,19 @@ static int rzt2h_validate_pin(struct rzt2h_pinctrl *pctrl, unsigned int offset) return (pincfg & BIT(pin)) ? 0 : -EINVAL; } +static void rzt2h_pinctrl_set_gpio_en(struct rzt2h_pinctrl *pctrl, + u8 port, u8 pin, bool en) +{ + u8 reg = rzt2h_pinctrl_readb(pctrl, port, PMC(port)); + + if (en) + reg &= ~BIT(pin); + else + reg |= BIT(pin); + + rzt2h_pinctrl_writeb(pctrl, port, reg, PMC(port)); +} + static void rzt2h_pinctrl_set_pfc_mode(struct rzt2h_pinctrl *pctrl, u8 port, u8 pin, u8 func) { @@ -133,8 +153,7 @@ static void rzt2h_pinctrl_set_pfc_mode(struct rzt2h_pinctrl *pctrl, rzt2h_pinctrl_writew(pctrl, port, reg16, PM(port)); /* Temporarily switch to GPIO mode with PMC register */ - reg16 = rzt2h_pinctrl_readb(pctrl, port, PMC(port)); - rzt2h_pinctrl_writeb(pctrl, port, reg16 & ~BIT(pin), PMC(port)); + rzt2h_pinctrl_set_gpio_en(pctrl, port, pin, true); /* Select Pin function mode with PFC register */ reg64 = rzt2h_pinctrl_readq(pctrl, port, PFC(port)); @@ -142,8 +161,7 @@ static void rzt2h_pinctrl_set_pfc_mode(struct rzt2h_pinctrl *pctrl, rzt2h_pinctrl_writeq(pctrl, port, reg64 | ((u64)func << (pin * 8)), PFC(port)); /* Switch to Peripheral pin function with PMC register */ - reg16 = rzt2h_pinctrl_readb(pctrl, port, PMC(port)); - rzt2h_pinctrl_writeb(pctrl, port, reg16 | BIT(pin), PMC(port)); + rzt2h_pinctrl_set_gpio_en(pctrl, port, pin, false); } static int rzt2h_pinctrl_set_mux(struct pinctrl_dev *pctldev, @@ -447,7 +465,6 @@ static int rzt2h_gpio_request(struct gpio_chip *chip, unsigned int offset) u8 port = RZT2H_PIN_ID_TO_PORT(offset); u8 bit = RZT2H_PIN_ID_TO_PIN(offset); int ret; - u8 reg; ret = rzt2h_validate_pin(pctrl, offset); if (ret) @@ -460,9 +477,7 @@ static int rzt2h_gpio_request(struct gpio_chip *chip, unsigned int offset) guard(spinlock_irqsave)(&pctrl->lock); /* Select GPIO mode in PMC Register */ - reg = rzt2h_pinctrl_readb(pctrl, port, PMC(port)); - reg &= ~BIT(bit); - rzt2h_pinctrl_writeb(pctrl, port, reg, PMC(port)); + rzt2h_pinctrl_set_gpio_en(pctrl, port, bit, true); return 0; } @@ -486,6 +501,7 @@ static int rzt2h_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) struct rzt2h_pinctrl *pctrl = gpiochip_get_data(chip); u8 port = RZT2H_PIN_ID_TO_PORT(offset); u8 bit = RZT2H_PIN_ID_TO_PIN(offset); + u64 reg64; u16 reg; int ret; @@ -493,8 +509,25 @@ static int rzt2h_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) if (ret) return ret; - if (rzt2h_pinctrl_readb(pctrl, port, PMC(port)) & BIT(bit)) + guard(spinlock_irqsave)(&pctrl->lock); + + if (rzt2h_pinctrl_readb(pctrl, port, PMC(port)) & BIT(bit)) { + /* + * When a GPIO is being requested as an IRQ, the pinctrl + * framework expects to be able to read the GPIO's direction. + * IRQ function is separate from GPIO, and enabling it takes the + * pin out of GPIO mode. + * At this point, .child_to_parent_hwirq() has already been + * called to enable the IRQ function. + * Default to input direction for IRQ function. + */ + reg64 = rzt2h_pinctrl_readq(pctrl, port, PFC(port)); + reg64 = (reg64 >> (bit * 8)) & PFC_MASK; + if (reg64 == PFC_FUNC_INTERRUPT) + return GPIO_LINE_DIRECTION_IN; + return -EINVAL; + } reg = rzt2h_pinctrl_readw(pctrl, port, PM(port)); reg = (reg >> (bit * 2)) & PM_MASK; @@ -617,14 +650,185 @@ static const char * const rzt2h_gpio_names[] = { "P35_0", "P35_1", "P35_2", "P35_3", "P35_4", "P35_5", "P35_6", "P35_7", }; +/* + * Interrupts 0-15 are for INTCPUn, which are not exposed externally. + * Interrupts 16-31 are for IRQn. SEI is 32. + * This table matches the information found in User Manual's Section + * 17.5, Multiplexed Pin Configurations, Tables 17.5 to 17.40, on the + * Interrupt rows. + * RZ/N2H has the same GPIO to IRQ mapping, except for the pins which + * are not present. + */ +static const u8 rzt2h_gpio_irq_map[] = { + 32, 16, 17, 18, 19, 0, 20, 21, + 22, 0, 0, 0, 0, 0, 0, 0, + 23, 24, 25, 26, 27, 0, 0, 0, + 0, 0, 28, 29, 30, 31, 0, 0, + 0, 0, 0, 0, 0, 32, 16, 17, + 18, 19, 20, 21, 22, 0, 0, 0, + 0, 0, 24, 25, 26, 27, 0, 28, + 29, 30, 31, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 24, 32, 16, + 0, 0, 0, 0, 0, 0, 0, 0, + 20, 23, 17, 18, 19, 0, 16, 25, + 29, 20, 21, 22, 23, 0, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 18, + 0, 0, 19, 0, 0, 20, 0, 30, + 21, 0, 0, 22, 0, 0, 24, 25, + 0, 0, 0, 0, 0, 16, 17, 0, + 18, 0, 0, 26, 27, 0, 0, 0, + 28, 29, 30, 31, 0, 0, 0, 0, + 23, 31, 32, 16, 17, 18, 19, 20, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 27, 0, 0, 21, 22, 23, 24, 25, + 26, 0, 0, 0, 0, 0, 0, 0, + 27, 28, 29, 30, 31, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 28, 32, 16, + 17, 18, 19, 0, 0, 0, 0, 20, + 21, 22, 23, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 25, 0, 0, + 0, 0, 26, 27, 0, 0, 0, 30, + 0, 29, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 28, 29, 30, 31, 0, + 0, 0, 0, 0, 0, 0, 0, 30, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static void rzt2h_gpio_irq_disable(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + unsigned int hwirq = irqd_to_hwirq(d); + + irq_chip_disable_parent(d); + gpiochip_disable_irq(gc, hwirq); +} + +static void rzt2h_gpio_irq_enable(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + unsigned int hwirq = irqd_to_hwirq(d); + + gpiochip_enable_irq(gc, hwirq); + irq_chip_enable_parent(d); +} + +static int rzt2h_gpio_irq_set_wake(struct irq_data *d, unsigned int on) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct rzt2h_pinctrl *pctrl = container_of(gc, struct rzt2h_pinctrl, gpio_chip); + int ret; + + ret = irq_chip_set_wake_parent(d, on); + if (ret) + return ret; + + /* + * If any of the IRQs are in use, put the entire pin controller on the + * device wakeup path. + */ + if (on) + atomic_inc(&pctrl->wakeup_path); + else + atomic_dec(&pctrl->wakeup_path); + + return 0; +} + +static const struct irq_chip rzt2h_gpio_irqchip = { + .name = "rzt2h-gpio", + .irq_disable = rzt2h_gpio_irq_disable, + .irq_enable = rzt2h_gpio_irq_enable, + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_set_type = irq_chip_set_type_parent, + .irq_set_wake = rzt2h_gpio_irq_set_wake, + .irq_eoi = irq_chip_eoi_parent, + .irq_set_affinity = irq_chip_set_affinity_parent, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static int rzt2h_gpio_child_to_parent_hwirq(struct gpio_chip *gc, + unsigned int child, + unsigned int child_type, + unsigned int *parent, + unsigned int *parent_type) +{ + struct rzt2h_pinctrl *pctrl = gpiochip_get_data(gc); + u8 port = RZT2H_PIN_ID_TO_PORT(child); + u8 pin = RZT2H_PIN_ID_TO_PIN(child); + u8 parent_irq; + + parent_irq = rzt2h_gpio_irq_map[child]; + if (parent_irq < RZT2H_INTERRUPTS_START) + return -EINVAL; + + if (test_and_set_bit(parent_irq - RZT2H_INTERRUPTS_START, + pctrl->used_irqs)) + return -EBUSY; + + rzt2h_pinctrl_set_pfc_mode(pctrl, port, pin, PFC_FUNC_INTERRUPT); + + *parent = parent_irq; + *parent_type = child_type; + + return 0; +} + +static void rzt2h_gpio_irq_domain_free(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs) +{ + struct irq_data *d = irq_domain_get_irq_data(domain, virq); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct rzt2h_pinctrl *pctrl = container_of(gc, struct rzt2h_pinctrl, gpio_chip); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + u8 port = RZT2H_PIN_ID_TO_PORT(hwirq); + u8 pin = RZT2H_PIN_ID_TO_PIN(hwirq); + + if (test_and_clear_bit(hwirq - RZT2H_INTERRUPTS_START, pctrl->used_irqs)) + rzt2h_pinctrl_set_gpio_en(pctrl, port, pin, false); + + irq_domain_free_irqs_common(domain, virq, nr_irqs); +} + +static void rzt2h_gpio_init_irq_valid_mask(struct gpio_chip *gc, + unsigned long *valid_mask, + unsigned int ngpios) +{ + struct rzt2h_pinctrl *pctrl = gpiochip_get_data(gc); + unsigned int offset; + + for (offset = 0; offset < ngpios; offset++) { + if (!rzt2h_gpio_irq_map[offset] || rzt2h_validate_pin(pctrl, offset)) + clear_bit(offset, valid_mask); + } +} + static int rzt2h_gpio_register(struct rzt2h_pinctrl *pctrl) { struct pinctrl_gpio_range *range = &pctrl->gpio_range; struct gpio_chip *chip = &pctrl->gpio_chip; + struct device_node *np = pctrl->dev->of_node; + struct irq_domain *parent_domain; struct device *dev = pctrl->dev; struct of_phandle_args of_args; + struct device_node *parent_np; + struct gpio_irq_chip *girq; int ret; + parent_np = of_irq_find_parent(np); + if (!parent_np) + return -ENXIO; + + parent_domain = irq_find_host(parent_np); + of_node_put(parent_np); + if (!parent_domain) + return -EPROBE_DEFER; + ret = of_parse_phandle_with_fixed_args(dev->of_node, "gpio-ranges", 3, 0, &of_args); if (ret) return dev_err_probe(dev, ret, "Unable to parse gpio-ranges\n"); @@ -648,6 +852,17 @@ static int rzt2h_gpio_register(struct rzt2h_pinctrl *pctrl) chip->set = rzt2h_gpio_set; chip->label = dev_name(dev); + if (of_property_present(np, "interrupt-controller")) { + girq = &chip->irq; + gpio_irq_chip_set_chip(girq, &rzt2h_gpio_irqchip); + girq->fwnode = dev_fwnode(pctrl->dev); + girq->parent_domain = parent_domain; + girq->child_to_parent_hwirq = rzt2h_gpio_child_to_parent_hwirq; + girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_twocell; + girq->child_irq_domain_ops.free = rzt2h_gpio_irq_domain_free; + girq->init_valid_mask = rzt2h_gpio_init_irq_valid_mask; + } + range->id = 0; range->pin_base = 0; range->base = 0; @@ -792,10 +1007,25 @@ static const struct of_device_id rzt2h_pinctrl_of_table[] = { { /* sentinel */ } }; +static int rzt2h_pinctrl_suspend_noirq(struct device *dev) +{ + struct rzt2h_pinctrl *pctrl = dev_get_drvdata(dev); + + if (atomic_read(&pctrl->wakeup_path)) + device_set_wakeup_path(dev); + + return 0; +} + +static const struct dev_pm_ops rzt2h_pinctrl_pm_ops = { + NOIRQ_SYSTEM_SLEEP_PM_OPS(rzt2h_pinctrl_suspend_noirq, NULL) +}; + static struct platform_driver rzt2h_pinctrl_driver = { .driver = { .name = DRV_NAME, .of_match_table = of_match_ptr(rzt2h_pinctrl_of_table), + .pm = pm_sleep_ptr(&rzt2h_pinctrl_pm_ops), .suppress_bind_attrs = true, }, .probe = rzt2h_pinctrl_probe, diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c index 627dca504d7a..fe9f92cb037e 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm64.c @@ -1770,6 +1770,123 @@ const struct samsung_pinctrl_of_match_data exynos8895_of_data __initconst = { .num_ctrl = ARRAY_SIZE(exynos8895_pin_ctrl), }; +/* pin banks of exynos9610 pin-controller 0 (ALIVE) */ +static const struct samsung_pin_bank_data exynos9610_pin_banks0[] __initconst = { + EXYNOS850_PIN_BANK_EINTN(6, 0x000, "etc0"), + GS101_PIN_BANK_EINTW(8, 0x020, "gpa0", 0x00, 0x00), + GS101_PIN_BANK_EINTW(8, 0x040, "gpa1", 0x04, 0x08), + GS101_PIN_BANK_EINTW(8, 0x060, "gpa2", 0x08, 0x0c), + EXYNOS850_PIN_BANK_EINTN(5, 0x080, "gpq0"), +}; + +/* pin banks of exynos9610 pin-controller 1 (CMGP) */ +static const struct samsung_pin_bank_data exynos9610_pin_banks1[] __initconst = { + EXYNOS850_PIN_BANK_EINTW(1, 0x000, "gpm0", 0x00), + EXYNOS850_PIN_BANK_EINTW(1, 0x020, "gpm1", 0x04), + EXYNOS850_PIN_BANK_EINTW(1, 0x040, "gpm2", 0x08), + EXYNOS850_PIN_BANK_EINTW(1, 0x060, "gpm3", 0x0C), + EXYNOS850_PIN_BANK_EINTW(1, 0x080, "gpm4", 0x10), + EXYNOS850_PIN_BANK_EINTW(1, 0x0A0, "gpm5", 0x14), + EXYNOS850_PIN_BANK_EINTW(1, 0x0C0, "gpm6", 0x18), + EXYNOS850_PIN_BANK_EINTW(1, 0x0E0, "gpm7", 0x1C), + EXYNOS850_PIN_BANK_EINTW(1, 0x100, "gpm8", 0x20), + EXYNOS850_PIN_BANK_EINTW(1, 0x120, "gpm9", 0x24), + EXYNOS850_PIN_BANK_EINTW(1, 0x140, "gpm10", 0x28), + EXYNOS850_PIN_BANK_EINTW(1, 0x160, "gpm11", 0x2C), + EXYNOS850_PIN_BANK_EINTW(1, 0x180, "gpm12", 0x30), + EXYNOS850_PIN_BANK_EINTW(1, 0x1A0, "gpm13", 0x34), + EXYNOS850_PIN_BANK_EINTW(1, 0x1C0, "gpm14", 0x38), + EXYNOS850_PIN_BANK_EINTW(1, 0x1E0, "gpm15", 0x3C), + EXYNOS850_PIN_BANK_EINTW(1, 0x200, "gpm16", 0x40), + EXYNOS850_PIN_BANK_EINTW(1, 0x220, "gpm17", 0x44), + EXYNOS850_PIN_BANK_EINTW(1, 0x240, "gpm18", 0x48), + EXYNOS850_PIN_BANK_EINTW(1, 0x260, "gpm19", 0x4C), + EXYNOS850_PIN_BANK_EINTW(1, 0x280, "gpm20", 0x50), + EXYNOS850_PIN_BANK_EINTW(1, 0x2A0, "gpm21", 0x54), + EXYNOS850_PIN_BANK_EINTW(1, 0x2C0, "gpm22", 0x58), + EXYNOS850_PIN_BANK_EINTW(1, 0x2E0, "gpm23", 0x5C), + EXYNOS850_PIN_BANK_EINTW(1, 0x300, "gpm24", 0x60), + EXYNOS850_PIN_BANK_EINTW(1, 0x320, "gpm25", 0x64), +}; + +/* pin banks of exynos9610 pin-controller 2 (DISPAUD) */ +static const struct samsung_pin_bank_data exynos9610_pin_banks2[] __initconst = { + GS101_PIN_BANK_EINTG(5, 0x000, "gpb0", 0x00, 0x00), + GS101_PIN_BANK_EINTG(4, 0x020, "gpb1", 0x04, 0x08), + GS101_PIN_BANK_EINTG(5, 0x040, "gpb2", 0x08, 0x0c), +}; + +/* pin banks of exynos9610 pin-controller 3 (FSYS) */ +static const struct samsung_pin_bank_data exynos9610_pin_banks3[] __initconst = { + GS101_PIN_BANK_EINTG(4, 0x000, "gpf0", 0x00, 0x00), + GS101_PIN_BANK_EINTG(8, 0x020, "gpf1", 0x04, 0x04), + GS101_PIN_BANK_EINTG(6, 0x040, "gpf2", 0x08, 0x0c), +}; + +/* pin banks of exynos9610 pin-controller 4 (TOP) */ +static const struct samsung_pin_bank_data exynos9610_pin_banks4[] __initconst = { + GS101_PIN_BANK_EINTG(8, 0x000, "gpp0", 0x00, 0x00), + GS101_PIN_BANK_EINTG(6, 0x020, "gpp1", 0x04, 0x08), + GS101_PIN_BANK_EINTG(8, 0x040, "gpp2", 0x08, 0x10), + GS101_PIN_BANK_EINTG(8, 0x060, "gpc0", 0x0C, 0x18), + GS101_PIN_BANK_EINTG(8, 0x080, "gpc1", 0x10, 0x20), + GS101_PIN_BANK_EINTG(5, 0x0A0, "gpc2", 0x14, 0x28), + GS101_PIN_BANK_EINTG(8, 0x0C0, "gpg0", 0x18, 0x30), + GS101_PIN_BANK_EINTG(8, 0x0E0, "gpg1", 0x1C, 0x38), + GS101_PIN_BANK_EINTG(8, 0x100, "gpg2", 0x20, 0x40), + GS101_PIN_BANK_EINTG(6, 0x120, "gpg3", 0x24, 0x48), + GS101_PIN_BANK_EINTG(3, 0x140, "gpg4", 0x28, 0x50), +}; + +/* pin banks of exynos9610 pin-controller 5 (SHUB) */ +static const struct samsung_pin_bank_data exynos9610_pin_banks5[] __initconst = { + EXYNOS850_PIN_BANK_EINTG(4, 0x000, "gph0", 0x00), + EXYNOS850_PIN_BANK_EINTG(3, 0x020, "gph1", 0x04), +}; + +static const struct samsung_pin_ctrl exynos9610_pin_ctrl[] __initconst = { + { + /* pin-controller instance 0 ALIVE data */ + .pin_banks = exynos9610_pin_banks0, + .nr_banks = ARRAY_SIZE(exynos9610_pin_banks0), + .eint_wkup_init = exynos_eint_wkup_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + }, { + /* pin-controller instance 1 CMGP data */ + .pin_banks = exynos9610_pin_banks1, + .nr_banks = ARRAY_SIZE(exynos9610_pin_banks1), + .eint_wkup_init = exynos_eint_wkup_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + }, { + /* pin-controller instance 2 DISPAUD data */ + .pin_banks = exynos9610_pin_banks2, + .nr_banks = ARRAY_SIZE(exynos9610_pin_banks2), + }, { + /* pin-controller instance 3 FSYS data */ + .pin_banks = exynos9610_pin_banks3, + .nr_banks = ARRAY_SIZE(exynos9610_pin_banks3), + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + }, { + /* pin-controller instance 4 TOP data */ + .pin_banks = exynos9610_pin_banks4, + .nr_banks = ARRAY_SIZE(exynos9610_pin_banks4), + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, + }, { + /* pin-controller instance 5 SHUB data */ + .pin_banks = exynos9610_pin_banks5, + .nr_banks = ARRAY_SIZE(exynos9610_pin_banks5), + }, +}; + +const struct samsung_pinctrl_of_match_data exynos9610_of_data __initconst = { + .ctrl = exynos9610_pin_ctrl, + .num_ctrl = ARRAY_SIZE(exynos9610_pin_ctrl), +}; + /* * Pinctrl driver data for Tesla FSD SoC. FSD SoC includes three * gpio/pin-mux/pinconfig controllers. diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index e374effba25a..5ac6f6b02327 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -1504,6 +1504,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = { .data = &exynos8890_of_data }, { .compatible = "samsung,exynos8895-pinctrl", .data = &exynos8895_of_data }, + { .compatible = "samsung,exynos9610-pinctrl", + .data = &exynos9610_of_data }, { .compatible = "samsung,exynos9810-pinctrl", .data = &exynos9810_of_data }, { .compatible = "samsung,exynos990-pinctrl", diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index 0f7b2ea98158..937600430a6e 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -398,6 +398,7 @@ extern const struct samsung_pinctrl_of_match_data exynos7885_of_data; extern const struct samsung_pinctrl_of_match_data exynos850_of_data; extern const struct samsung_pinctrl_of_match_data exynos8890_of_data; extern const struct samsung_pinctrl_of_match_data exynos8895_of_data; +extern const struct samsung_pinctrl_of_match_data exynos9610_of_data; extern const struct samsung_pinctrl_of_match_data exynos9810_of_data; extern const struct samsung_pinctrl_of_match_data exynos990_of_data; extern const struct samsung_pinctrl_of_match_data exynosautov9_of_data; diff --git a/drivers/pinctrl/sophgo/pinctrl-cv18xx.h b/drivers/pinctrl/sophgo/pinctrl-cv18xx.h index 759c0e604acf..973ab9a38fcf 100644 --- a/drivers/pinctrl/sophgo/pinctrl-cv18xx.h +++ b/drivers/pinctrl/sophgo/pinctrl-cv18xx.h @@ -6,11 +6,7 @@ #ifndef _PINCTRL_SOPHGO_CV18XX_H #define _PINCTRL_SOPHGO_CV18XX_H -#include <linux/bits.h> #include <linux/bitfield.h> -#include <linux/mutex.h> -#include <linux/spinlock.h> -#include <linux/platform_device.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinconf.h> diff --git a/drivers/pinctrl/sophgo/pinctrl-sg2042.h b/drivers/pinctrl/sophgo/pinctrl-sg2042.h index d481973fcf97..1a2b00dde1fa 100644 --- a/drivers/pinctrl/sophgo/pinctrl-sg2042.h +++ b/drivers/pinctrl/sophgo/pinctrl-sg2042.h @@ -6,12 +6,6 @@ #ifndef _PINCTRL_SOPHGO_SG2042_H #define _PINCTRL_SOPHGO_SG2042_H -#include <linux/bits.h> -#include <linux/bitfield.h> -#include <linux/device.h> -#include <linux/mutex.h> -#include <linux/spinlock.h> -#include <linux/platform_device.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinconf.h> diff --git a/drivers/pinctrl/spacemit/Kconfig b/drivers/pinctrl/spacemit/Kconfig index d6f6017fd097..c021d51033d1 100644 --- a/drivers/pinctrl/spacemit/Kconfig +++ b/drivers/pinctrl/spacemit/Kconfig @@ -4,7 +4,7 @@ # config PINCTRL_SPACEMIT_K1 - bool "SpacemiT K1 SoC Pinctrl driver" + bool "SpacemiT K1/K3 SoC Pinctrl driver" depends on ARCH_SPACEMIT || COMPILE_TEST depends on OF default ARCH_SPACEMIT @@ -12,7 +12,7 @@ config PINCTRL_SPACEMIT_K1 select GENERIC_PINMUX_FUNCTIONS select GENERIC_PINCONF help - Say Y to select the pinctrl driver for K1 SoC. + Say Y to select the pinctrl driver for K1/K3 SoC. This pin controller allows selecting the mux function for each pin. This driver can also be built as a module called pinctrl-k1. diff --git a/drivers/pinctrl/spacemit/pinctrl-k1.c b/drivers/pinctrl/spacemit/pinctrl-k1.c index 33af9b5791c1..71390402aaa6 100644 --- a/drivers/pinctrl/spacemit/pinctrl-k1.c +++ b/drivers/pinctrl/spacemit/pinctrl-k1.c @@ -7,8 +7,10 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/platform_device.h> +#include <linux/regmap.h> #include <linux/seq_file.h> #include <linux/spinlock.h> +#include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/mutex.h> @@ -24,11 +26,12 @@ #include "pinctrl-k1.h" /* - * +---------+----------+-----------+--------+--------+----------+--------+ - * | pull | drive | schmitter | slew | edge | strong | mux | - * | up/down | strength | trigger | rate | detect | pull | mode | - * +---------+----------+-----------+--------+--------+----------+--------+ - * 3 bits 3 bits 2 bits 1 bit 3 bits 1 bit 3 bits + * | pull | drive | schmitter | slew | edge | strong | mux | + * SoC | up/down | strength | trigger | rate | detect | pull | mode | + *-----+---------+----------+-----------+-------+--------+--------+--------+ + * K1 | 3 bits | 3 bits | 2 bits | 1 bit | 3 bits | 1 bit | 3 bits | + *-----+---------+----------+-----------+-------+--------+--------+--------+ + * K3 | 3 bits | 4 bits | 1 bits | 1 bit | 3 bits | 1 bit | 3 bits | */ #define PAD_MUX GENMASK(2, 0) @@ -38,12 +41,50 @@ #define PAD_EDGE_CLEAR BIT(6) #define PAD_SLEW_RATE GENMASK(12, 11) #define PAD_SLEW_RATE_EN BIT(7) -#define PAD_SCHMITT GENMASK(9, 8) -#define PAD_DRIVE GENMASK(12, 10) +#define PAD_SCHMITT_K1 GENMASK(9, 8) +#define PAD_DRIVE_K1 GENMASK(12, 10) +#define PAD_SCHMITT_K3 BIT(8) +#define PAD_DRIVE_K3 GENMASK(12, 9) #define PAD_PULLDOWN BIT(13) #define PAD_PULLUP BIT(14) #define PAD_PULL_EN BIT(15) +#define IO_PWR_DOMAIN_OFFSET 0x800 + +#define IO_PWR_DOMAIN_GPIO2_Kx 0x0c +#define IO_PWR_DOMAIN_MMC_Kx 0x1c + +#define IO_PWR_DOMAIN_GPIO3_K1 0x10 +#define IO_PWR_DOMAIN_QSPI_K1 0x20 + +#define IO_PWR_DOMAIN_GPIO1_K3 0x04 +#define IO_PWR_DOMAIN_GPIO5_K3 0x10 +#define IO_PWR_DOMAIN_GPIO4_K3 0x20 +#define IO_PWR_DOMAIN_QSPI_K3 0x2c + +#define IO_PWR_DOMAIN_V18EN BIT(2) + +#define APBC_ASFAR 0x50 +#define APBC_ASSAR 0x54 + +#define APBC_ASFAR_AKEY 0xbaba +#define APBC_ASSAR_AKEY 0xeb10 + +struct spacemit_pin_drv_strength { + u8 val; + u32 mA; +}; + +struct spacemit_pinctrl_dconf { + u64 schmitt_mask; + u64 drive_mask; + + struct spacemit_pin_drv_strength *ds_1v8_tbl; + size_t ds_1v8_tbl_num; + struct spacemit_pin_drv_strength *ds_3v3_tbl; + size_t ds_3v3_tbl_num; +}; + struct spacemit_pin { u16 pin; u16 flags; @@ -60,12 +101,17 @@ struct spacemit_pinctrl { raw_spinlock_t lock; void __iomem *regs; + + struct regmap *regmap_apbc; }; struct spacemit_pinctrl_data { const struct pinctrl_pin_desc *pins; const struct spacemit_pin *data; u16 npins; + unsigned int (*pin_to_offset)(unsigned int pin); + unsigned int (*pin_to_io_pd_offset)(unsigned int pin); + const struct spacemit_pinctrl_dconf *dconf; }; struct spacemit_pin_mux_config { @@ -73,13 +119,8 @@ struct spacemit_pin_mux_config { u32 config; }; -struct spacemit_pin_drv_strength { - u8 val; - u32 mA; -}; - /* map pin id to pinctrl register offset, refer MFPR definition */ -static unsigned int spacemit_pin_to_offset(unsigned int pin) +static unsigned int spacemit_k1_pin_to_offset(unsigned int pin) { unsigned int offset = 0; @@ -124,10 +165,67 @@ static unsigned int spacemit_pin_to_offset(unsigned int pin) return offset << 2; } +static unsigned int spacemit_k3_pin_to_offset(unsigned int pin) +{ + unsigned int offset = pin > 130 ? (pin + 2) : pin; + + return offset << 2; +} + +static unsigned int spacemit_k1_pin_to_io_pd_offset(unsigned int pin) +{ + unsigned int offset = 0; + + switch (pin) { + case 47 ... 52: + offset = IO_PWR_DOMAIN_GPIO3_K1; + break; + case 75 ... 80: + offset = IO_PWR_DOMAIN_GPIO2_Kx; + break; + case 98 ... 103: + offset = IO_PWR_DOMAIN_QSPI_K1; + break; + case 104 ... 109: + offset = IO_PWR_DOMAIN_MMC_Kx; + break; + } + + return offset; +} + +static unsigned int spacemit_k3_pin_to_io_pd_offset(unsigned int pin) +{ + unsigned int offset = 0; + + switch (pin) { + case 0 ... 20: + offset = IO_PWR_DOMAIN_GPIO1_K3; + break; + case 21 ... 41: + offset = IO_PWR_DOMAIN_GPIO2_Kx; + break; + case 76 ... 98: + offset = IO_PWR_DOMAIN_GPIO4_K3; + break; + case 99 ... 127: + offset = IO_PWR_DOMAIN_GPIO5_K3; + break; + case 132 ... 137: + offset = IO_PWR_DOMAIN_MMC_Kx; + break; + case 138 ... 144: + offset = IO_PWR_DOMAIN_QSPI_K3; + break; + } + + return offset; +} + static inline void __iomem *spacemit_pin_to_reg(struct spacemit_pinctrl *pctrl, unsigned int pin) { - return pctrl->regs + spacemit_pin_to_offset(pin); + return pctrl->regs + pctrl->data->pin_to_offset(pin); } static u16 spacemit_dt_get_pin(u32 value) @@ -177,7 +275,7 @@ static void spacemit_pctrl_dbg_show(struct pinctrl_dev *pctldev, void __iomem *reg; u32 value; - seq_printf(seq, "offset: 0x%04x ", spacemit_pin_to_offset(pin)); + seq_printf(seq, "offset: 0x%04x ", pctrl->data->pin_to_offset(pin)); seq_printf(seq, "type: %s ", io_type_desc[type]); reg = spacemit_pin_to_reg(pctrl, pin); @@ -185,23 +283,70 @@ static void spacemit_pctrl_dbg_show(struct pinctrl_dev *pctldev, seq_printf(seq, "mux: %ld reg: 0x%04x", (value & PAD_MUX), value); } -/* use IO high level output current as the table */ -static struct spacemit_pin_drv_strength spacemit_ds_1v8_tbl[4] = { - { 0, 11 }, - { 2, 21 }, - { 4, 32 }, - { 6, 42 }, +static const struct spacemit_pinctrl_dconf k1_drive_conf = { + .drive_mask = PAD_DRIVE_K1, + .schmitt_mask = PAD_SCHMITT_K1, + .ds_1v8_tbl = (struct spacemit_pin_drv_strength[]) { + { 0, 11 }, + { 2, 21 }, + { 4, 32 }, + { 6, 42 }, + }, + .ds_1v8_tbl_num = 4, + .ds_3v3_tbl = (struct spacemit_pin_drv_strength[]) { + { 0, 7 }, + { 2, 10 }, + { 4, 13 }, + { 6, 16 }, + { 1, 19 }, + { 3, 23 }, + { 5, 26 }, + { 7, 29 }, + }, + .ds_3v3_tbl_num = 8, }; -static struct spacemit_pin_drv_strength spacemit_ds_3v3_tbl[8] = { - { 0, 7 }, - { 2, 10 }, - { 4, 13 }, - { 6, 16 }, - { 1, 19 }, - { 3, 23 }, - { 5, 26 }, - { 7, 29 }, +static const struct spacemit_pinctrl_dconf k3_drive_conf = { + .drive_mask = PAD_DRIVE_K3, + .schmitt_mask = PAD_SCHMITT_K3, + .ds_1v8_tbl = (struct spacemit_pin_drv_strength[]) { + { 0, 2 }, + { 1, 4 }, + { 2, 6 }, + { 3, 7 }, + { 4, 9 }, + { 5, 11 }, + { 6, 13 }, + { 7, 14 }, + { 8, 21 }, + { 9, 23 }, + { 10, 25 }, + { 11, 26 }, + { 12, 28 }, + { 13, 30 }, + { 14, 31 }, + { 15, 33 }, + }, + .ds_1v8_tbl_num = 16, + .ds_3v3_tbl = (struct spacemit_pin_drv_strength[]) { + { 0, 3 }, + { 1, 5 }, + { 2, 7 }, + { 3, 9 }, + { 4, 11 }, + { 5, 13 }, + { 6, 15 }, + { 7, 17 }, + { 8, 25 }, + { 9, 27 }, + { 10, 29 }, + { 11, 31 }, + { 12, 33 }, + { 13, 35 }, + { 14, 37 }, + { 15, 38 }, + }, + .ds_3v3_tbl_num = 16, }; static inline u8 spacemit_get_ds_value(struct spacemit_pin_drv_strength *tbl, @@ -229,16 +374,17 @@ static inline u32 spacemit_get_ds_mA(struct spacemit_pin_drv_strength *tbl, } static inline u8 spacemit_get_driver_strength(enum spacemit_pin_io_type type, + const struct spacemit_pinctrl_dconf *dconf, u32 mA) { switch (type) { case IO_TYPE_1V8: - return spacemit_get_ds_value(spacemit_ds_1v8_tbl, - ARRAY_SIZE(spacemit_ds_1v8_tbl), + return spacemit_get_ds_value(dconf->ds_1v8_tbl, + dconf->ds_1v8_tbl_num, mA); case IO_TYPE_3V3: - return spacemit_get_ds_value(spacemit_ds_3v3_tbl, - ARRAY_SIZE(spacemit_ds_3v3_tbl), + return spacemit_get_ds_value(dconf->ds_3v3_tbl, + dconf->ds_3v3_tbl_num, mA); default: return 0; @@ -246,16 +392,17 @@ static inline u8 spacemit_get_driver_strength(enum spacemit_pin_io_type type, } static inline u32 spacemit_get_drive_strength_mA(enum spacemit_pin_io_type type, + const struct spacemit_pinctrl_dconf *dconf, u32 value) { switch (type) { case IO_TYPE_1V8: - return spacemit_get_ds_mA(spacemit_ds_1v8_tbl, - ARRAY_SIZE(spacemit_ds_1v8_tbl), - value & 0x6); + return spacemit_get_ds_mA(dconf->ds_1v8_tbl, + dconf->ds_1v8_tbl_num, + value); case IO_TYPE_3V3: - return spacemit_get_ds_mA(spacemit_ds_3v3_tbl, - ARRAY_SIZE(spacemit_ds_3v3_tbl), + return spacemit_get_ds_mA(dconf->ds_3v3_tbl, + dconf->ds_3v3_tbl_num, value); default: return 0; @@ -294,6 +441,42 @@ static int spacemit_pctrl_check_power(struct pinctrl_dev *pctldev, return 0; } +static void spacemit_set_io_pwr_domain(struct spacemit_pinctrl *pctrl, + const struct spacemit_pin *spin, + const enum spacemit_pin_io_type type) +{ + u32 offset, val = 0; + + if (!pctrl->regmap_apbc) + return; + + offset = pctrl->data->pin_to_io_pd_offset(spin->pin); + + /* Other bits are reserved so don't need to save them */ + if (type == IO_TYPE_1V8) + val = IO_PWR_DOMAIN_V18EN; + + /* + * IO power domain registers are protected and cannot be accessed + * directly. Before performing any read or write to the IO power + * domain registers, an explicit unlock sequence must be issued + * via the AIB Secure Access Register (ASAR). + * + * The unlock sequence allows exactly one subsequent access to the + * IO power domain registers. After that access completes, the ASAR + * keys are automatically cleared, and the registers become locked + * again. + * + * This mechanism ensures that IO power domain configuration is + * performed intentionally, as incorrect voltage settings may + * result in functional failures or hardware damage. + */ + regmap_write(pctrl->regmap_apbc, APBC_ASFAR, APBC_ASFAR_AKEY); + regmap_write(pctrl->regmap_apbc, APBC_ASSAR, APBC_ASSAR_AKEY); + + writel_relaxed(val, pctrl->regs + IO_PWR_DOMAIN_OFFSET + offset); +} + static int spacemit_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np, struct pinctrl_map **maps, @@ -501,7 +684,9 @@ static int spacemit_pinconf_get(struct pinctrl_dev *pctldev, #define ENABLE_DRV_STRENGTH BIT(1) #define ENABLE_SLEW_RATE BIT(2) -static int spacemit_pinconf_generate_config(const struct spacemit_pin *spin, +static int spacemit_pinconf_generate_config(struct spacemit_pinctrl *pctrl, + const struct spacemit_pin *spin, + const struct spacemit_pinctrl_dconf *dconf, unsigned long *configs, unsigned int num_configs, u32 *value) @@ -539,8 +724,8 @@ static int spacemit_pinconf_generate_config(const struct spacemit_pin *spin, drv_strength = arg; break; case PIN_CONFIG_INPUT_SCHMITT: - v &= ~PAD_SCHMITT; - v |= FIELD_PREP(PAD_SCHMITT, arg); + v &= ~dconf->schmitt_mask; + v |= (arg << __ffs(dconf->schmitt_mask)) & dconf->schmitt_mask; break; case PIN_CONFIG_POWER_SOURCE: voltage = arg; @@ -574,12 +759,13 @@ static int spacemit_pinconf_generate_config(const struct spacemit_pin *spin, default: return -EINVAL; } + spacemit_set_io_pwr_domain(pctrl, spin, type); } - val = spacemit_get_driver_strength(type, drv_strength); + val = spacemit_get_driver_strength(type, dconf, drv_strength); - v &= ~PAD_DRIVE; - v |= FIELD_PREP(PAD_DRIVE, val); + v &= ~dconf->drive_mask; + v |= (val << __ffs(dconf->drive_mask)) & dconf->drive_mask; } if (flag & ENABLE_SLEW_RATE) { @@ -629,7 +815,8 @@ static int spacemit_pinconf_set(struct pinctrl_dev *pctldev, const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin); u32 value; - if (spacemit_pinconf_generate_config(spin, configs, num_configs, &value)) + if (spacemit_pinconf_generate_config(pctrl, spin, pctrl->data->dconf, + configs, num_configs, &value)) return -EINVAL; return spacemit_pin_set_config(pctrl, pin, value); @@ -651,7 +838,8 @@ static int spacemit_pinconf_group_set(struct pinctrl_dev *pctldev, return -EINVAL; spin = spacemit_get_pin(pctrl, group->grp.pins[0]); - if (spacemit_pinconf_generate_config(spin, configs, num_configs, &value)) + if (spacemit_pinconf_generate_config(pctrl, spin, pctrl->data->dconf, + configs, num_configs, &value)) return -EINVAL; for (i = 0; i < group->grp.npins; i++) @@ -685,6 +873,7 @@ static void spacemit_pinconf_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *seq, unsigned int pin) { struct spacemit_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct spacemit_pinctrl_dconf *dconf = pctrl->data->dconf; const struct spacemit_pin *spin = spacemit_get_pin(pctrl, pin); enum spacemit_pin_io_type type = spacemit_to_pin_io_type(spin); void __iomem *reg = spacemit_pin_to_reg(pctrl, pin); @@ -695,17 +884,17 @@ static void spacemit_pinconf_dbg_show(struct pinctrl_dev *pctldev, seq_printf(seq, ", io type (%s)", io_type_desc[type]); - tmp = FIELD_GET(PAD_DRIVE, value); + tmp = (value & dconf->drive_mask) >> __ffs(dconf->drive_mask); if (type == IO_TYPE_1V8 || type == IO_TYPE_3V3) { - mA = spacemit_get_drive_strength_mA(type, tmp); + mA = spacemit_get_drive_strength_mA(type, dconf, tmp); seq_printf(seq, ", drive strength (%d mA)", mA); } /* drive strength depend on power source, so show all values */ if (type == IO_TYPE_EXTERNAL) seq_printf(seq, ", drive strength (%d or %d mA)", - spacemit_get_drive_strength_mA(IO_TYPE_1V8, tmp), - spacemit_get_drive_strength_mA(IO_TYPE_3V3, tmp)); + spacemit_get_drive_strength_mA(IO_TYPE_1V8, dconf, tmp), + spacemit_get_drive_strength_mA(IO_TYPE_3V3, dconf, tmp)); seq_printf(seq, ", register (0x%04x)", value); } @@ -720,6 +909,7 @@ static const struct pinconf_ops spacemit_pinconf_ops = { static int spacemit_pinctrl_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; struct spacemit_pinctrl *pctrl; struct clk *func_clk, *bus_clk; @@ -741,6 +931,12 @@ static int spacemit_pinctrl_probe(struct platform_device *pdev) if (IS_ERR(pctrl->regs)) return PTR_ERR(pctrl->regs); + pctrl->regmap_apbc = syscon_regmap_lookup_by_phandle(np, "spacemit,apbc"); + if (IS_ERR(pctrl->regmap_apbc)) { + dev_warn(dev, "no syscon found, disable power voltage switch functionality\n"); + pctrl->regmap_apbc = NULL; + } + func_clk = devm_clk_get_enabled(dev, "func"); if (IS_ERR(func_clk)) return dev_err_probe(dev, PTR_ERR(func_clk), "failed to get func clock\n"); @@ -1042,10 +1238,352 @@ static const struct spacemit_pinctrl_data k1_pinctrl_data = { .pins = k1_pin_desc, .data = k1_pin_data, .npins = ARRAY_SIZE(k1_pin_desc), + .pin_to_offset = spacemit_k1_pin_to_offset, + .pin_to_io_pd_offset = spacemit_k1_pin_to_io_pd_offset, + .dconf = &k1_drive_conf, +}; + +static const struct pinctrl_pin_desc k3_pin_desc[] = { + PINCTRL_PIN(0, "GPIO_00"), + PINCTRL_PIN(1, "GPIO_01"), + PINCTRL_PIN(2, "GPIO_02"), + PINCTRL_PIN(3, "GPIO_03"), + PINCTRL_PIN(4, "GPIO_04"), + PINCTRL_PIN(5, "GPIO_05"), + PINCTRL_PIN(6, "GPIO_06"), + PINCTRL_PIN(7, "GPIO_07"), + PINCTRL_PIN(8, "GPIO_08"), + PINCTRL_PIN(9, "GPIO_09"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(104, "GPIO_104"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "GPIO_113"), + PINCTRL_PIN(114, "GPIO_114"), + PINCTRL_PIN(115, "GPIO_115"), + PINCTRL_PIN(116, "GPIO_116"), + PINCTRL_PIN(117, "GPIO_117"), + PINCTRL_PIN(118, "GPIO_118"), + PINCTRL_PIN(119, "GPIO_119"), + PINCTRL_PIN(120, "GPIO_120"), + PINCTRL_PIN(121, "GPIO_121"), + PINCTRL_PIN(122, "GPIO_122"), + PINCTRL_PIN(123, "GPIO_123"), + PINCTRL_PIN(124, "GPIO_124"), + PINCTRL_PIN(125, "GPIO_125"), + PINCTRL_PIN(126, "GPIO_126"), + PINCTRL_PIN(127, "GPIO_127"), + PINCTRL_PIN(128, "PWR_SCL"), + PINCTRL_PIN(129, "PWR_SDA"), + PINCTRL_PIN(130, "VCXO_EN"), + PINCTRL_PIN(131, "PMIC_INT_N"), + PINCTRL_PIN(132, "MMC1_DAT3"), + PINCTRL_PIN(133, "MMC1_DAT2"), + PINCTRL_PIN(134, "MMC1_DAT1"), + PINCTRL_PIN(135, "MMC1_DAT0"), + PINCTRL_PIN(136, "MMC1_CMD"), + PINCTRL_PIN(137, "MMC1_CLK"), + PINCTRL_PIN(138, "QSPI_DAT0"), + PINCTRL_PIN(139, "QSPI_DAT1"), + PINCTRL_PIN(140, "QSPI_DAT2"), + PINCTRL_PIN(141, "QSPI_DAT3"), + PINCTRL_PIN(142, "QSPI_CS0"), + PINCTRL_PIN(143, "QSPI_CS1"), + PINCTRL_PIN(144, "QSPI_CLK"), + PINCTRL_PIN(145, "PRI_TDI"), + PINCTRL_PIN(146, "PRI_TMS"), + PINCTRL_PIN(147, "PRI_TCK"), + PINCTRL_PIN(148, "PRI_TDO"), + PINCTRL_PIN(149, "PWR_SSP_SCLK"), + PINCTRL_PIN(150, "PWR_SSP_FRM"), + PINCTRL_PIN(151, "PWR_SSP_TXD"), + PINCTRL_PIN(152, "PWR_SSP_RXD"), +}; + +static const struct spacemit_pin k3_pin_data[ARRAY_SIZE(k3_pin_desc)] = { + /* GPIO1 bank */ + K1_FUNC_PIN(0, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(1, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(2, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(3, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(4, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(5, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(6, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(7, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(8, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(9, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(10, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(11, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(12, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(13, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(14, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(15, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(16, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(17, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(18, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(19, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(20, 0, IO_TYPE_EXTERNAL), + + /* GPIO2 bank */ + K1_FUNC_PIN(21, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(22, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(23, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(24, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(25, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(26, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(27, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(28, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(29, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(30, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(31, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(32, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(33, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(34, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(35, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(36, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(37, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(38, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(39, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(40, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(41, 0, IO_TYPE_EXTERNAL), + + /* GPIO3 bank */ + K1_FUNC_PIN(42, 0, IO_TYPE_1V8), + K1_FUNC_PIN(43, 0, IO_TYPE_1V8), + K1_FUNC_PIN(44, 0, IO_TYPE_1V8), + K1_FUNC_PIN(45, 0, IO_TYPE_1V8), + K1_FUNC_PIN(46, 0, IO_TYPE_1V8), + K1_FUNC_PIN(47, 0, IO_TYPE_1V8), + K1_FUNC_PIN(48, 0, IO_TYPE_1V8), + K1_FUNC_PIN(49, 0, IO_TYPE_1V8), + K1_FUNC_PIN(50, 0, IO_TYPE_1V8), + K1_FUNC_PIN(51, 0, IO_TYPE_1V8), + K1_FUNC_PIN(52, 0, IO_TYPE_1V8), + K1_FUNC_PIN(53, 0, IO_TYPE_1V8), + K1_FUNC_PIN(54, 0, IO_TYPE_1V8), + K1_FUNC_PIN(55, 0, IO_TYPE_1V8), + K1_FUNC_PIN(56, 0, IO_TYPE_1V8), + K1_FUNC_PIN(57, 0, IO_TYPE_1V8), + K1_FUNC_PIN(58, 0, IO_TYPE_1V8), + K1_FUNC_PIN(59, 0, IO_TYPE_1V8), + K1_FUNC_PIN(60, 0, IO_TYPE_1V8), + K1_FUNC_PIN(61, 0, IO_TYPE_1V8), + K1_FUNC_PIN(62, 0, IO_TYPE_1V8), + K1_FUNC_PIN(63, 0, IO_TYPE_1V8), + K1_FUNC_PIN(64, 0, IO_TYPE_1V8), + K1_FUNC_PIN(65, 0, IO_TYPE_1V8), + K1_FUNC_PIN(66, 0, IO_TYPE_1V8), + K1_FUNC_PIN(67, 0, IO_TYPE_1V8), + K1_FUNC_PIN(68, 0, IO_TYPE_1V8), + K1_FUNC_PIN(69, 0, IO_TYPE_1V8), + K1_FUNC_PIN(70, 0, IO_TYPE_1V8), + K1_FUNC_PIN(71, 0, IO_TYPE_1V8), + K1_FUNC_PIN(72, 0, IO_TYPE_1V8), + K1_FUNC_PIN(73, 0, IO_TYPE_1V8), + K1_FUNC_PIN(74, 0, IO_TYPE_1V8), + K1_FUNC_PIN(75, 0, IO_TYPE_1V8), + + /* GPIO4 bank */ + K1_FUNC_PIN(76, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(77, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(78, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(79, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(80, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(81, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(82, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(83, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(84, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(85, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(86, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(87, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(88, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(89, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(90, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(91, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(92, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(93, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(94, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(95, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(96, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(97, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(98, 0, IO_TYPE_EXTERNAL), + + /* GPIO5 bank */ + K1_FUNC_PIN(99, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(100, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(101, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(102, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(103, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(104, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(105, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(106, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(107, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(108, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(109, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(110, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(111, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(112, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(113, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(114, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(115, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(116, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(117, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(118, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(119, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(120, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(121, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(122, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(123, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(124, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(125, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(126, 0, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(127, 0, IO_TYPE_EXTERNAL), + + /* PMIC */ + K1_FUNC_PIN(128, 0, IO_TYPE_1V8), + K1_FUNC_PIN(129, 0, IO_TYPE_1V8), + K1_FUNC_PIN(130, 0, IO_TYPE_1V8), + K1_FUNC_PIN(131, 0, IO_TYPE_1V8), + + /* SD/MMC1 */ + K1_FUNC_PIN(132, 1, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(133, 1, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(134, 1, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(135, 1, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(136, 1, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(137, 1, IO_TYPE_EXTERNAL), + + /* QSPI */ + K1_FUNC_PIN(138, 1, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(139, 1, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(140, 1, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(141, 1, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(142, 1, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(143, 1, IO_TYPE_EXTERNAL), + K1_FUNC_PIN(144, 1, IO_TYPE_EXTERNAL), + + /* PMIC */ + K1_FUNC_PIN(145, 1, IO_TYPE_1V8), + K1_FUNC_PIN(146, 1, IO_TYPE_1V8), + K1_FUNC_PIN(147, 1, IO_TYPE_1V8), + K1_FUNC_PIN(148, 1, IO_TYPE_1V8), + K1_FUNC_PIN(149, 1, IO_TYPE_1V8), + K1_FUNC_PIN(150, 1, IO_TYPE_1V8), + K1_FUNC_PIN(151, 1, IO_TYPE_1V8), + K1_FUNC_PIN(152, 1, IO_TYPE_1V8), +}; + +static const struct spacemit_pinctrl_data k3_pinctrl_data = { + .pins = k3_pin_desc, + .data = k3_pin_data, + .npins = ARRAY_SIZE(k3_pin_desc), + .pin_to_offset = spacemit_k3_pin_to_offset, + .pin_to_io_pd_offset = spacemit_k3_pin_to_io_pd_offset, + .dconf = &k3_drive_conf, }; static const struct of_device_id k1_pinctrl_ids[] = { { .compatible = "spacemit,k1-pinctrl", .data = &k1_pinctrl_data }, + { .compatible = "spacemit,k3-pinctrl", .data = &k3_pinctrl_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, k1_pinctrl_ids); @@ -1061,5 +1599,5 @@ static struct platform_driver k1_pinctrl_driver = { builtin_platform_driver(k1_pinctrl_driver); MODULE_AUTHOR("Yixun Lan <dlan@gentoo.org>"); -MODULE_DESCRIPTION("Pinctrl driver for the SpacemiT K1 SoC"); +MODULE_DESCRIPTION("Pinctrl driver for the SpacemiT K1/K3 SoC"); MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c index 9b67063a0b0b..44f84e4c29bf 100644 --- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c +++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c @@ -7,14 +7,11 @@ */ #include <linux/bits.h> -#include <linux/clk.h> #include <linux/gpio/driver.h> #include <linux/io.h> #include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/mutex.h> #include <linux/platform_device.h> -#include <linux/reset.h> #include <linux/spinlock.h> #include <linux/pinctrl/pinctrl.h> diff --git a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c index 49c5edeba87f..c6a51bb21215 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c @@ -474,14 +474,14 @@ static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = { #endif }; -static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) +static void tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) { u32 value; - mutex_lock(&padctl->lock); + guard(mutex)(&padctl->lock); if (padctl->enable++ > 0) - goto out; + return; value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; @@ -498,23 +498,19 @@ static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - -out: - mutex_unlock(&padctl->lock); - return 0; } -static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) +static void tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) { u32 value; - mutex_lock(&padctl->lock); + guard(mutex)(&padctl->lock); if (WARN_ON(padctl->enable == 0)) - goto out; + return; if (--padctl->enable > 0) - goto out; + return; value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; @@ -531,24 +527,24 @@ static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - -out: - mutex_unlock(&padctl->lock); - return 0; } static int tegra_xusb_phy_init(struct phy *phy) { struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - return tegra_xusb_padctl_enable(padctl); + tegra_xusb_padctl_enable(padctl); + + return 0; } static int tegra_xusb_phy_exit(struct phy *phy) { struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - return tegra_xusb_padctl_disable(padctl); + tegra_xusb_padctl_disable(padctl); + + return 0; } static int pcie_phy_power_on(struct phy *phy) diff --git a/include/linux/pinctrl/devinfo.h b/include/linux/pinctrl/devinfo.h index bb6653af4f92..de4228eea90a 100644 --- a/include/linux/pinctrl/devinfo.h +++ b/include/linux/pinctrl/devinfo.h @@ -43,7 +43,6 @@ struct dev_pin_info { #endif }; -extern int pinctrl_bind_pins(struct device *dev); extern int pinctrl_init_done(struct device *dev); static inline struct pinctrl *dev_pinctrl(struct device *dev) @@ -58,11 +57,6 @@ static inline struct pinctrl *dev_pinctrl(struct device *dev) /* Stubs if we're not using pinctrl */ -static inline int pinctrl_bind_pins(struct device *dev) -{ - return 0; -} - static inline int pinctrl_init_done(struct device *dev) { return 0; diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h index 1be4032071c2..89277808ea61 100644 --- a/include/linux/pinctrl/pinconf-generic.h +++ b/include/linux/pinctrl/pinconf-generic.h @@ -250,9 +250,4 @@ static inline int pinconf_generic_dt_node_to_map_all(struct pinctrl_dev *pctldev return pinconf_generic_dt_node_to_map(pctldev, np_config, map, num_maps, PIN_MAP_TYPE_INVALID); } - -int pinconf_generic_dt_node_to_map_pinmux(struct pinctrl_dev *pctldev, - struct device_node *np, - struct pinctrl_map **map, - unsigned int *num_maps); #endif /* __LINUX_PINCTRL_PINCONF_GENERIC_H */ diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index 1a8084e29405..c329cc693139 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h @@ -187,9 +187,6 @@ extern struct pinctrl_dev *devm_pinctrl_register(struct device *dev, const struct pinctrl_desc *pctldesc, void *driver_data); -extern void devm_pinctrl_unregister(struct device *dev, - struct pinctrl_dev *pctldev); - extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range); extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev, |
