aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/firmware/fsl,scu.yaml5
-rw-r--r--Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml7
-rw-r--r--Documentation/devicetree/bindings/gpio/fsl,imx8qxp-sc-gpio.yaml39
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-stmpe.txt3
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-xilinx.txt48
-rw-r--r--Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml18
-rw-r--r--Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml154
-rw-r--r--drivers/gpio/Kconfig4
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-imx-scu.c139
-rw-r--r--drivers/gpio/gpio-rockchip.c21
-rw-r--r--drivers/gpio/gpio-ucb1400.c1
-rw-r--r--include/linux/ucb1400.h2
13 files changed, 372 insertions, 70 deletions
diff --git a/Documentation/devicetree/bindings/firmware/fsl,scu.yaml b/Documentation/devicetree/bindings/firmware/fsl,scu.yaml
index b40b0ef56978..557e524786c2 100644
--- a/Documentation/devicetree/bindings/firmware/fsl,scu.yaml
+++ b/Documentation/devicetree/bindings/firmware/fsl,scu.yaml
@@ -30,6 +30,11 @@ properties:
Clock controller node that provides the clocks controlled by the SCU
$ref: /schemas/clock/fsl,scu-clk.yaml
+ gpio:
+ description:
+ Control the GPIO PINs on SCU domain over the firmware APIs
+ $ref: /schemas/gpio/fsl,imx8qxp-sc-gpio.yaml
+
ocotp:
description:
OCOTP controller node provided by the SCU
diff --git a/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml b/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
index a99e7842ca17..c0ad70e66f76 100644
--- a/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
+++ b/Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml
@@ -33,8 +33,6 @@ properties:
description: GPIO connected to the OE (Output Enable) pin.
maxItems: 1
- spi-max-frequency: true
-
patternProperties:
"^(hog-[0-9]+|.+-hog(-[0-9]+)?)$":
type: object
@@ -59,7 +57,10 @@ required:
- '#gpio-cells'
- registers-number
-additionalProperties: false
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/gpio/fsl,imx8qxp-sc-gpio.yaml b/Documentation/devicetree/bindings/gpio/fsl,imx8qxp-sc-gpio.yaml
new file mode 100644
index 000000000000..b7b32220935d
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/fsl,imx8qxp-sc-gpio.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/fsl,imx8qxp-sc-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GPIO driver over IMX SCU firmware API
+
+maintainers:
+ - Shenwei Wang <[email protected]>
+
+description: |
+ This module provides the standard interface to control the
+ resource pins in SCU domain on i.MX8 platforms.
+
+properties:
+ compatible:
+ enum:
+ - fsl,imx8qxp-sc-gpio
+
+ "#gpio-cells":
+ const: 2
+
+ gpio-controller: true
+
+required:
+ - compatible
+ - "#gpio-cells"
+ - gpio-controller
+
+additionalProperties: false
+
+examples:
+ - |
+ gpio0: gpio {
+ compatible = "fsl,imx8qxp-sc-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt b/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt
index a0e4cf885213..b33f8f02c0d7 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt
@@ -8,8 +8,7 @@ Optional properties:
- st,norequest-mask: bitmask specifying which GPIOs should _not_ be requestable
due to different usage (e.g. touch, keypad)
-Node name must be stmpe_gpio and should be child node of stmpe node to which it
-belongs.
+Node should be child node of stmpe node to which it belongs.
Example:
stmpe_gpio {
diff --git a/Documentation/devicetree/bindings/gpio/gpio-xilinx.txt b/Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
deleted file mode 100644
index e506f30e1a95..000000000000
--- a/Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-Xilinx plb/axi GPIO controller
-
-Dual channel GPIO controller with configurable number of pins
-(from 1 to 32 per channel). Every pin can be configured as
-input/output/tristate. Both channels share the same global IRQ but
-local interrupts can be enabled on channel basis.
-
-Required properties:
-- compatible : Should be "xlnx,xps-gpio-1.00.a"
-- reg : Address and length of the register set for the device
-- #gpio-cells : Should be two. The first cell is the pin number and the
- second cell is used to specify optional parameters (currently unused).
-- gpio-controller : Marks the device node as a GPIO controller.
-
-Optional properties:
-- clocks : Input clock specifier. Refer to common clock bindings.
-- interrupts : Interrupt mapping for GPIO IRQ.
-- xlnx,all-inputs : if n-th bit is setup, GPIO-n is input
-- xlnx,dout-default : if n-th bit is 1, GPIO-n default value is 1
-- xlnx,gpio-width : gpio width
-- xlnx,tri-default : if n-th bit is 1, GPIO-n is in tristate mode
-- xlnx,is-dual : if 1, controller also uses the second channel
-- xlnx,all-inputs-2 : as above but for the second channel
-- xlnx,dout-default-2 : as above but the second channel
-- xlnx,gpio2-width : as above but for the second channel
-- xlnx,tri-default-2 : as above but for the second channel
-
-
-Example:
-gpio: gpio@40000000 {
- #gpio-cells = <2>;
- compatible = "xlnx,xps-gpio-1.00.a";
- clocks = <&clkc25>;
- gpio-controller ;
- interrupt-parent = <&microblaze_0_intc>;
- interrupts = < 6 2 >;
- reg = < 0x40000000 0x10000 >;
- xlnx,all-inputs = <0x0>;
- xlnx,all-inputs-2 = <0x0>;
- xlnx,dout-default = <0x0>;
- xlnx,dout-default-2 = <0x0>;
- xlnx,gpio-width = <0x2>;
- xlnx,gpio2-width = <0x2>;
- xlnx,interrupt-present = <0x1>;
- xlnx,is-dual = <0x1>;
- xlnx,tri-default = <0xffffffff>;
- xlnx,tri-default-2 = <0xffffffff>;
-} ;
diff --git a/Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml b/Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml
index 110651eafa70..fdc16822fd4b 100644
--- a/Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml
@@ -44,6 +44,24 @@ properties:
gpio-controller: true
+patternProperties:
+ "^.+-hog(-[0-9]+)?$":
+ type: object
+
+ additionalProperties: false
+
+ properties:
+ gpio-hog: true
+ gpios: true
+ input: true
+ output-high: true
+ output-low: true
+ line-name: true
+
+ required:
+ - gpio-hog
+ - gpios
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml b/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
new file mode 100644
index 000000000000..f333ee2288e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/xlnx,gpio-xilinx.yaml
@@ -0,0 +1,154 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/xlnx,gpio-xilinx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx AXI GPIO controller
+
+maintainers:
+ - Neeli Srinivas <[email protected]>
+
+description:
+ The AXI GPIO design provides a general purpose input/output interface
+ to an AXI4-Lite interface. The AXI GPIO can be configured as either
+ a single or a dual-channel device. The width of each channel is
+ independently configurable. The channels can be configured to
+ generate an interrupt when a transition on any of their inputs occurs.
+
+properties:
+ compatible:
+ enum:
+ - xlnx,xps-gpio-1.00.a
+
+ reg:
+ maxItems: 1
+
+ "#gpio-cells":
+ const: 2
+
+ interrupts:
+ maxItems: 1
+
+ gpio-controller: true
+
+ gpio-line-names:
+ description: strings describing the names of each gpio line
+ minItems: 1
+ maxItems: 64
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 2
+
+ clocks:
+ maxItems: 1
+
+ interrupt-names: true
+
+ xlnx,all-inputs:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: This option sets this GPIO channel1 bits in input mode.
+
+ xlnx,all-inputs-2:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: This option sets this GPIO channel2 bits in input mode.
+
+ xlnx,all-outputs:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: This option sets this GPIO channel1 bits in output mode.
+
+ xlnx,all-outputs-2:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: This option sets this GPIO channel2 bits in output mode.
+
+ xlnx,dout-default:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Sets the default value of all the enabled bits of
+ channel1.
+ default: 0
+
+ xlnx,dout-default-2:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Sets the default value of all the enabled bits of
+ channel2.
+ default: 0
+
+ xlnx,gpio-width:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: The value defines the bit width of the GPIO channel1.
+ minimum: 1
+ maximum: 32
+ default: 32
+
+ xlnx,gpio2-width:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: The value defines the bit width of the GPIO channel2.
+ minimum: 1
+ maximum: 32
+ default: 32
+
+ xlnx,interrupt-present:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: This parameter enables interrupt control logic
+ and interrupt registers in GPIO module.
+ minimum: 0
+ maximum: 1
+ default: 0
+
+ xlnx,is-dual:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: This parameter enables a second GPIO channel (GPIO2).
+ minimum: 0
+ maximum: 1
+ default: 0
+
+ xlnx,tri-default:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: This value configures the input or output mode
+ of each bit of GPIO channel1.
+
+ xlnx,tri-default-2:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: This value configures the input or output mode
+ of each bit of GPIO channel2.
+
+required:
+ - reg
+ - compatible
+ - gpio-controller
+ - "#gpio-cells"
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ gpio@e000a000 {
+ compatible = "xlnx,xps-gpio-1.00.a";
+ reg = <0xa0020000 0x10000>;
+ #gpio-cells = <2>;
+ #interrupt-cells = <0x2>;
+ clocks = <&zynqmp_clk 71>;
+ gpio-controller;
+ interrupt-controller;
+ interrupt-names = "ip2intc_irpt";
+ interrupt-parent = <&gic>;
+ interrupts = <0 89 4>;
+ xlnx,all-inputs = <0x0>;
+ xlnx,all-inputs-2 = <0x0>;
+ xlnx,all-outputs = <0x0>;
+ xlnx,all-outputs-2 = <0x0>;
+ xlnx,dout-default = <0x0>;
+ xlnx,dout-default-2 = <0x0>;
+ xlnx,gpio-width = <0x20>;
+ xlnx,gpio2-width = <0x20>;
+ xlnx,interrupt-present = <0x1>;
+ xlnx,is-dual = <0x1>;
+ xlnx,tri-default = <0xFFFFFFFF>;
+ xlnx,tri-default-2 = <0xFFFFFFFF>;
+ };
+
+...
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 3f64345fe40b..ed9e71d6713e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -341,6 +341,10 @@ config GPIO_ICH
If unsure, say N.
+config GPIO_IMX_SCU
+ def_bool y
+ depends on IMX_SCU
+
config GPIO_IOP
tristate "Intel IOP GPIO"
depends on ARCH_IOP32X || COMPILE_TEST
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index a0985d30f51b..b67e29d348cf 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
obj-$(CONFIG_GPIO_I8255) += gpio-i8255.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_IDT3243X) += gpio-idt3243x.o
+obj-$(CONFIG_GPIO_IMX_SCU) += gpio-imx-scu.o
obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o
diff --git a/drivers/gpio/gpio-imx-scu.c b/drivers/gpio/gpio-imx-scu.c
new file mode 100644
index 000000000000..17be21b8f3b7
--- /dev/null
+++ b/drivers/gpio/gpio-imx-scu.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2021~2022 NXP
+ *
+ * The driver exports a standard gpiochip interface
+ * to control the PIN resources on SCU domain.
+ */
+
+#include <linux/module.h>
+#include <linux/gpio/driver.h>
+#include <linux/platform_device.h>
+#include <linux/firmware/imx/svc/rm.h>
+#include <dt-bindings/firmware/imx/rsrc.h>
+
+struct scu_gpio_priv {
+ struct gpio_chip chip;
+ struct mutex lock;
+ struct device *dev;
+ struct imx_sc_ipc *handle;
+};
+
+static unsigned int scu_rsrc_arr[] = {
+ IMX_SC_R_BOARD_R0,
+ IMX_SC_R_BOARD_R1,
+ IMX_SC_R_BOARD_R2,
+ IMX_SC_R_BOARD_R3,
+ IMX_SC_R_BOARD_R4,
+ IMX_SC_R_BOARD_R5,
+ IMX_SC_R_BOARD_R6,
+ IMX_SC_R_BOARD_R7,
+};
+
+static int imx_scu_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct scu_gpio_priv *priv = gpiochip_get_data(chip);
+ int level;
+ int err;
+
+ if (offset >= chip->ngpio)
+ return -EINVAL;
+
+ mutex_lock(&priv->lock);
+
+ /* to read PIN state via scu api */
+ err = imx_sc_misc_get_control(priv->handle,
+ scu_rsrc_arr[offset], 0, &level);
+ mutex_unlock(&priv->lock);
+
+ if (err) {
+ dev_err(priv->dev, "SCU get failed: %d\n", err);
+ return err;
+ }
+
+ return level;
+}
+
+static void imx_scu_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
+{
+ struct scu_gpio_priv *priv = gpiochip_get_data(chip);
+ int err;
+
+ if (offset >= chip->ngpio)
+ return;
+
+ mutex_lock(&priv->lock);
+
+ /* to set PIN output level via scu api */
+ err = imx_sc_misc_set_control(priv->handle,
+ scu_rsrc_arr[offset], 0, value);
+ mutex_unlock(&priv->lock);
+
+ if (err)
+ dev_err(priv->dev, "SCU set (%d) failed: %d\n",
+ scu_rsrc_arr[offset], err);
+}
+
+static int imx_scu_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ if (offset >= chip->ngpio)
+ return -EINVAL;
+
+ return GPIO_LINE_DIRECTION_OUT;
+}
+
+static int imx_scu_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct scu_gpio_priv *priv;
+ struct gpio_chip *gc;
+ int ret;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ ret = imx_scu_get_handle(&priv->handle);
+ if (ret)
+ return ret;
+
+ priv->dev = dev;
+ mutex_init(&priv->lock);
+
+ gc = &priv->chip;
+ gc->base = -1;
+ gc->parent = dev;
+ gc->ngpio = sizeof(scu_rsrc_arr)/sizeof(unsigned int);
+ gc->label = dev_name(dev);
+ gc->get = imx_scu_gpio_get;
+ gc->set = imx_scu_gpio_set;
+ gc->get_direction = imx_scu_gpio_get_direction;
+
+ platform_set_drvdata(pdev, priv);
+
+ return devm_gpiochip_add_data(dev, gc, priv);
+}
+
+static const struct of_device_id imx_scu_gpio_dt_ids[] = {
+ { .compatible = "fsl,imx8qxp-sc-gpio" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver imx_scu_gpio_driver = {
+ .driver = {
+ .name = "gpio-imx-scu",
+ .of_match_table = imx_scu_gpio_dt_ids,
+ },
+ .probe = imx_scu_gpio_probe,
+};
+
+static int __init _imx_scu_gpio_init(void)
+{
+ return platform_driver_register(&imx_scu_gpio_driver);
+}
+
+subsys_initcall_sync(_imx_scu_gpio_init);
+
+MODULE_AUTHOR("Shenwei Wang <[email protected]>");
+MODULE_DESCRIPTION("NXP GPIO over IMX SCU API");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
index f91e876fd969..ebb50c25a461 100644
--- a/drivers/gpio/gpio-rockchip.c
+++ b/drivers/gpio/gpio-rockchip.c
@@ -325,26 +325,15 @@ static void rockchip_irq_demux(struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
- u32 pend;
+ unsigned long pending;
+ unsigned int irq;
dev_dbg(bank->dev, "got irq for bank %s\n", bank->name);
chained_irq_enter(chip, desc);
- pend = readl_relaxed(bank->reg_base + bank->gpio_regs->int_status);
-
- while (pend) {
- unsigned int irq, virq;
-
- irq = __ffs(pend);
- pend &= ~BIT(irq);
- virq = irq_find_mapping(bank->domain, irq);
-
- if (!virq) {
- dev_err(bank->dev, "unmapped irq %d\n", irq);
- continue;
- }
-
+ pending = readl_relaxed(bank->reg_base + bank->gpio_regs->int_status);
+ for_each_set_bit(irq, &pending, 32) {
dev_dbg(bank->dev, "handling irq %d\n", irq);
/*
@@ -378,7 +367,7 @@ static void rockchip_irq_demux(struct irq_desc *desc)
} while ((data & BIT(irq)) != (data_old & BIT(irq)));
}
- generic_handle_irq(virq);
+ generic_handle_domain_irq(bank->domain, irq);
}
chained_irq_exit(chip, desc);
diff --git a/drivers/gpio/gpio-ucb1400.c b/drivers/gpio/gpio-ucb1400.c
index 386e69300332..676adf1f198a 100644
--- a/drivers/gpio/gpio-ucb1400.c
+++ b/drivers/gpio/gpio-ucb1400.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/ucb1400.h>
+#include <linux/gpio/driver.h>
static int ucb1400_gpio_dir_in(struct gpio_chip *gc, unsigned off)
{
diff --git a/include/linux/ucb1400.h b/include/linux/ucb1400.h
index 22345391350b..2516082cd3a9 100644
--- a/include/linux/ucb1400.h
+++ b/include/linux/ucb1400.h
@@ -23,7 +23,7 @@
#include <sound/ac97_codec.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
/*
* UCB1400 AC-link registers