60e2723
From patchwork Tue Feb 20 12:19:31 2018
60e2723
Content-Type: text/plain; charset="utf-8"
60e2723
MIME-Version: 1.0
60e2723
Content-Transfer-Encoding: 7bit
60e2723
Subject: [v5,1/5] ARM: bcm2835: sync firmware properties with downstream
60e2723
From: Baruch Siach <baruch@tkos.co.il>
60e2723
X-Patchwork-Id: 10229963
60e2723
Message-Id: <e7d1f1d0789f11d37957a8998bee23d035115aeb.1519128054.git.baruch@tkos.co.il>
60e2723
To: Linus Walleij <linus.walleij@linaro.org>,
60e2723
 Dave Stevenson <dave.stevenson@raspberrypi.org>,
60e2723
 Eric Anholt <eric@anholt.net>, Stefan Wahren <stefan.wahren@i2se.com>
60e2723
Cc: devicetree@vger.kernel.org, Baruch Siach <baruch@tkos.co.il>,
60e2723
 linux-gpio@vger.kernel.org, Michael Zoran <mzoran@crowfest.net>,
60e2723
 Rob Herring <robh+dt@kernel.org>, linux-rpi-kernel@lists.infradead.org,
60e2723
 Frank Rowand <frowand.list@gmail.com>, linux-arm-kernel@lists.infradead.org
60e2723
Date: Tue, 20 Feb 2018 14:19:31 +0200
60e2723
60e2723
Add latest firmware property tags from the latest Raspberry Pi downstream
60e2723
kernel. This is needed for the GPIO tags, so we can control the GPIO
60e2723
multiplexor lines.
60e2723
60e2723
Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
60e2723
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
60e2723
---
60e2723
v4: No change
60e2723
60e2723
v3: Add Stefan's ack
60e2723
60e2723
v2: No change
60e2723
---
60e2723
 include/soc/bcm2835/raspberrypi-firmware.h | 18 ++++++++++++++++++
60e2723
 1 file changed, 18 insertions(+)
60e2723
60e2723
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
60e2723
index cb979ad90401..50df5b28d2c9 100644
60e2723
--- a/include/soc/bcm2835/raspberrypi-firmware.h
60e2723
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
60e2723
@@ -63,6 +63,7 @@ enum rpi_firmware_property_tag {
60e2723
 	RPI_FIRMWARE_GET_MIN_VOLTAGE =                        0x00030008,
60e2723
 	RPI_FIRMWARE_GET_TURBO =                              0x00030009,
60e2723
 	RPI_FIRMWARE_GET_MAX_TEMPERATURE =                    0x0003000a,
60e2723
+	RPI_FIRMWARE_GET_STC =                                0x0003000b,
60e2723
 	RPI_FIRMWARE_ALLOCATE_MEMORY =                        0x0003000c,
60e2723
 	RPI_FIRMWARE_LOCK_MEMORY =                            0x0003000d,
60e2723
 	RPI_FIRMWARE_UNLOCK_MEMORY =                          0x0003000e,
60e2723
@@ -72,12 +73,22 @@ enum rpi_firmware_property_tag {
60e2723
 	RPI_FIRMWARE_SET_ENABLE_QPU =                         0x00030012,
60e2723
 	RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE =       0x00030014,
60e2723
 	RPI_FIRMWARE_GET_EDID_BLOCK =                         0x00030020,
60e2723
+	RPI_FIRMWARE_GET_CUSTOMER_OTP =                       0x00030021,
60e2723
 	RPI_FIRMWARE_GET_DOMAIN_STATE =                       0x00030030,
60e2723
 	RPI_FIRMWARE_SET_CLOCK_STATE =                        0x00038001,
60e2723
 	RPI_FIRMWARE_SET_CLOCK_RATE =                         0x00038002,
60e2723
 	RPI_FIRMWARE_SET_VOLTAGE =                            0x00038003,
60e2723
 	RPI_FIRMWARE_SET_TURBO =                              0x00038009,
60e2723
+	RPI_FIRMWARE_SET_CUSTOMER_OTP =                       0x00038021,
60e2723
 	RPI_FIRMWARE_SET_DOMAIN_STATE =                       0x00038030,
60e2723
+	RPI_FIRMWARE_GET_GPIO_STATE =                         0x00030041,
60e2723
+	RPI_FIRMWARE_SET_GPIO_STATE =                         0x00038041,
60e2723
+	RPI_FIRMWARE_SET_SDHOST_CLOCK =                       0x00038042,
60e2723
+	RPI_FIRMWARE_GET_GPIO_CONFIG =                        0x00030043,
60e2723
+	RPI_FIRMWARE_SET_GPIO_CONFIG =                        0x00038043,
60e2723
+	RPI_FIRMWARE_GET_PERIPH_REG =                         0x00030045,
60e2723
+	RPI_FIRMWARE_SET_PERIPH_REG =                         0x00038045,
60e2723
+
60e2723
 
60e2723
 	/* Dispmanx TAGS */
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE =                   0x00040001,
60e2723
@@ -91,6 +102,8 @@ enum rpi_firmware_property_tag {
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET =         0x00040009,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN =               0x0004000a,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE =                0x0004000b,
60e2723
+	RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF =               0x0004000f,
60e2723
+	RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF =            0x00040010,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_RELEASE =                    0x00048001,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT =  0x00044004,
60e2723
@@ -100,6 +113,7 @@ enum rpi_firmware_property_tag {
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET =        0x00044009,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN =              0x0004400a,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE =               0x0004400b,
60e2723
+	RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC =                 0x0004400e,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT =  0x00048003,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT =   0x00048004,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH =                  0x00048005,
60e2723
@@ -108,6 +122,10 @@ enum rpi_firmware_property_tag {
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET =         0x00048009,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN =               0x0004800a,
60e2723
 	RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE =                0x0004800b,
60e2723
+	RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF =               0x0004801f,
60e2723
+	RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF =            0x00048020,
60e2723
+	RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC =                  0x0004800e,
60e2723
+	RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT =              0x0004800f,
60e2723
 
60e2723
 	RPI_FIRMWARE_VCHIQ_INIT =                             0x00048010,
60e2723
 
60e2723
From patchwork Tue Feb 20 12:19:32 2018
60e2723
Content-Type: text/plain; charset="utf-8"
60e2723
MIME-Version: 1.0
60e2723
Content-Transfer-Encoding: 7bit
60e2723
Subject: [v5,2/5] dt-bindings: gpio: add raspberry pi GPIO expander binding
60e2723
From: Baruch Siach <baruch@tkos.co.il>
60e2723
X-Patchwork-Id: 10229965
60e2723
Message-Id: <f400b48cbcd8a138c39d4e8f63d6c1f569090dcc.1519128054.git.baruch@tkos.co.il>
60e2723
To: Linus Walleij <linus.walleij@linaro.org>,
60e2723
 Dave Stevenson <dave.stevenson@raspberrypi.org>,
60e2723
 Eric Anholt <eric@anholt.net>, Stefan Wahren <stefan.wahren@i2se.com>
60e2723
Cc: devicetree@vger.kernel.org, Baruch Siach <baruch@tkos.co.il>,
60e2723
 linux-gpio@vger.kernel.org, Michael Zoran <mzoran@crowfest.net>,
60e2723
 Rob Herring <robh+dt@kernel.org>, linux-rpi-kernel@lists.infradead.org,
60e2723
 Frank Rowand <frowand.list@gmail.com>, linux-arm-kernel@lists.infradead.org
60e2723
Date: Tue, 20 Feb 2018 14:19:32 +0200
60e2723
60e2723
The Raspberry Pi 3 GPIO expander is controlled by the VC4 firmware over
60e2723
I2C. The firmware mailbox interface allows the ARM core to control the
60e2723
GPIO lines.
60e2723
60e2723
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
60e2723
Reviewed-by: Rob Herring <robh@kernel.org>
60e2723
---
60e2723
v5:
60e2723
  * Remove the 'firmware' property
60e2723
  * Note that the gpio node is a child of the firmware node
60e2723
60e2723
v4:
60e2723
  * Move the example gpio node under the firmware node
60e2723
  * Rename gpio node name to plain 'gpio'
60e2723
60e2723
v3:
60e2723
  * Rename node name.
60e2723
60e2723
v2:
60e2723
  * Rename compatible string to raspberrypi,firmware-gpio
60e2723
---
60e2723
 .../bindings/gpio/raspberrypi,firmware-gpio.txt    | 30 ++++++++++++++++++++++
60e2723
 1 file changed, 30 insertions(+)
60e2723
 create mode 100644 Documentation/devicetree/bindings/gpio/raspberrypi,firmware-gpio.txt
60e2723
60e2723
diff --git a/Documentation/devicetree/bindings/gpio/raspberrypi,firmware-gpio.txt b/Documentation/devicetree/bindings/gpio/raspberrypi,firmware-gpio.txt
60e2723
new file mode 100644
60e2723
index 000000000000..ce97265e23ba
60e2723
--- /dev/null
60e2723
+++ b/Documentation/devicetree/bindings/gpio/raspberrypi,firmware-gpio.txt
60e2723
@@ -0,0 +1,30 @@
60e2723
+Raspberry Pi GPIO expander
60e2723
+
60e2723
+The Raspberry Pi 3 GPIO expander is controlled by the VC4 firmware. The
60e2723
+firmware exposes a mailbox interface that allows the ARM core to control the
60e2723
+GPIO lines on the expander.
60e2723
+
60e2723
+The Raspberry Pi GPIO expander node must be a child node of the Raspberry Pi
60e2723
+firmware node.
60e2723
+
60e2723
+Required properties:
60e2723
+
60e2723
+- compatible : Should be "raspberrypi,firmware-gpio"
60e2723
+- gpio-controller : Marks the device node as a gpio controller
60e2723
+- #gpio-cells : Should be two.  The first cell is the pin number, and
60e2723
+  the second cell is used to specify the gpio polarity:
60e2723
+  0 = active high
60e2723
+  1 = active low
60e2723
+
60e2723
+Example:
60e2723
+
60e2723
+firmware: firmware-rpi {
60e2723
+	compatible = "raspberrypi,bcm2835-firmware";
60e2723
+	mboxes = <&mailbox>;
60e2723
+
60e2723
+	expgpio: gpio {
60e2723
+		 compatible = "raspberrypi,firmware-gpio";
60e2723
+		 gpio-controller;
60e2723
+		 #gpio-cells = <2>;
60e2723
+	 };
60e2723
+};
60e2723
From patchwork Tue Feb 20 12:19:33 2018
60e2723
Content-Type: text/plain; charset="utf-8"
60e2723
MIME-Version: 1.0
60e2723
Content-Transfer-Encoding: 7bit
60e2723
Subject: [v5,
60e2723
 3/5] gpio: raspberrypi-exp: Driver for RPi3 GPIO expander via mailbox
60e2723
 service
60e2723
From: Baruch Siach <baruch@tkos.co.il>
60e2723
X-Patchwork-Id: 10229967
60e2723
Message-Id: <8c34f287ee72b340fa9d693aa0e304b25541c74c.1519128054.git.baruch@tkos.co.il>
60e2723
To: Linus Walleij <linus.walleij@linaro.org>,
60e2723
 Dave Stevenson <dave.stevenson@raspberrypi.org>,
60e2723
 Eric Anholt <eric@anholt.net>, Stefan Wahren <stefan.wahren@i2se.com>
60e2723
Cc: devicetree@vger.kernel.org, Baruch Siach <baruch@tkos.co.il>,
60e2723
 linux-gpio@vger.kernel.org, Michael Zoran <mzoran@crowfest.net>,
60e2723
 Rob Herring <robh+dt@kernel.org>, linux-rpi-kernel@lists.infradead.org,
60e2723
 Frank Rowand <frowand.list@gmail.com>, linux-arm-kernel@lists.infradead.org
60e2723
Date: Tue, 20 Feb 2018 14:19:33 +0200
60e2723
60e2723
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
60e2723
60e2723
Pi3 and Compute Module 3 have a GPIO expander that the
60e2723
VPU communicates with.
60e2723
There is a mailbox service that now allows control of this
60e2723
expander, so add a kernel driver that can make use of it.
60e2723
60e2723
Reviewed-by: Stefan Wahren <stefan.wahren@i2se.com>
60e2723
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
60e2723
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
60e2723
---
60e2723
v5:
60e2723
  * Use the parent node to find the firmware
60e2723
60e2723
v4:
60e2723
  * Don't set the .owner driver field
60e2723
  * Add Stefan's review tag
60e2723
60e2723
v3:
60e2723
  * Tweak Kconfig driver prompt
60e2723
  * Make GPIO_RASPBERRYPI_EXP tristate
60e2723
  * Make COMPILE_TEST independent of RASPBERRYPI_FIRMWARE
60e2723
  * Remove redundant DMA header
60e2723
  * Use less code lines for dev_err()
60e2723
  * Check rpi_exp_gpio_get_polarity() return value
60e2723
  * Remove redundant platform_set_drvdata() call
60e2723
60e2723
v2:
60e2723
  * Rename driver to gpio-raspberrypi-exp
60e2723
  * Populate the gpiochip parent device pointer
60e2723
  * Use macro for the mailbox base GPIO number
60e2723
  * Drop linux/gpio.h and GPIOF_DIR_*
60e2723
  * Check and print firmware error value
60e2723
  * Use devm_gpiochip_add_data(); drop .remove
60e2723
  * A few more minor tweaks
60e2723
---
60e2723
 drivers/gpio/Kconfig                |   9 ++
60e2723
 drivers/gpio/Makefile               |   1 +
60e2723
 drivers/gpio/gpio-raspberrypi-exp.c | 252 ++++++++++++++++++++++++++++++++++++
60e2723
 3 files changed, 262 insertions(+)
60e2723
 create mode 100644 drivers/gpio/gpio-raspberrypi-exp.c
60e2723
60e2723
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
60e2723
index 8dbb2280538d..fd0562a37f68 100644
60e2723
--- a/drivers/gpio/Kconfig
60e2723
+++ b/drivers/gpio/Kconfig
60e2723
@@ -122,6 +122,15 @@ config GPIO_ATH79
60e2723
 	  Select this option to enable GPIO driver for
60e2723
 	  Atheros AR71XX/AR724X/AR913X SoC devices.
60e2723
 
60e2723
+config GPIO_RASPBERRYPI_EXP
60e2723
+	tristate "Raspberry Pi 3 GPIO Expander"
60e2723
+	default RASPBERRYPI_FIRMWARE
60e2723
+	depends on OF_GPIO
60e2723
+	depends on (ARCH_BCM2835 && RASPBERRYPI_FIRMWARE) || COMPILE_TEST
60e2723
+	help
60e2723
+	  Turn on GPIO support for the expander on Raspberry Pi 3 boards, using
60e2723
+	  the firmware mailbox to communicate with VideoCore on BCM283x chips.
60e2723
+
60e2723
 config GPIO_BCM_KONA
60e2723
 	bool "Broadcom Kona GPIO"
60e2723
 	depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST)
60e2723
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
60e2723
index cccb0d40846c..76dc0a02bd56 100644
60e2723
--- a/drivers/gpio/Makefile
60e2723
+++ b/drivers/gpio/Makefile
60e2723
@@ -32,6 +32,7 @@ obj-$(CONFIG_GPIO_AMDPT)	+= gpio-amdpt.o
60e2723
 obj-$(CONFIG_GPIO_ARIZONA)	+= gpio-arizona.o
60e2723
 obj-$(CONFIG_GPIO_ATH79)	+= gpio-ath79.o
60e2723
 obj-$(CONFIG_GPIO_ASPEED)	+= gpio-aspeed.o
60e2723
+obj-$(CONFIG_GPIO_RASPBERRYPI_EXP)	+= gpio-raspberrypi-exp.o
60e2723
 obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-kona.o
60e2723
 obj-$(CONFIG_GPIO_BD9571MWV)	+= gpio-bd9571mwv.o
60e2723
 obj-$(CONFIG_GPIO_BRCMSTB)	+= gpio-brcmstb.o
60e2723
diff --git a/drivers/gpio/gpio-raspberrypi-exp.c b/drivers/gpio/gpio-raspberrypi-exp.c
60e2723
new file mode 100644
60e2723
index 000000000000..d6d36d537e37
60e2723
--- /dev/null
60e2723
+++ b/drivers/gpio/gpio-raspberrypi-exp.c
60e2723
@@ -0,0 +1,252 @@
60e2723
+// SPDX-License-Identifier: GPL-2.0+
60e2723
+/*
60e2723
+ *  Raspberry Pi 3 expander GPIO driver
60e2723
+ *
60e2723
+ *  Uses the firmware mailbox service to communicate with the
60e2723
+ *  GPIO expander on the VPU.
60e2723
+ *
60e2723
+ *  Copyright (C) 2017 Raspberry Pi Trading Ltd.
60e2723
+ */
60e2723
+
60e2723
+#include <linux/err.h>
60e2723
+#include <linux/gpio/driver.h>
60e2723
+#include <linux/module.h>
60e2723
+#include <linux/platform_device.h>
60e2723
+#include <soc/bcm2835/raspberrypi-firmware.h>
60e2723
+
60e2723
+#define MODULE_NAME "raspberrypi-exp-gpio"
60e2723
+#define NUM_GPIO 8
60e2723
+
60e2723
+#define RPI_EXP_GPIO_BASE	128
60e2723
+
60e2723
+#define RPI_EXP_GPIO_DIR_IN	0
60e2723
+#define RPI_EXP_GPIO_DIR_OUT	1
60e2723
+
60e2723
+struct rpi_exp_gpio {
60e2723
+	struct gpio_chip gc;
60e2723
+	struct rpi_firmware *fw;
60e2723
+};
60e2723
+
60e2723
+/* VC4 firmware mailbox interface data structures */
60e2723
+
60e2723
+struct gpio_set_config {
60e2723
+	u32 gpio;
60e2723
+	u32 direction;
60e2723
+	u32 polarity;
60e2723
+	u32 term_en;
60e2723
+	u32 term_pull_up;
60e2723
+	u32 state;
60e2723
+};
60e2723
+
60e2723
+struct gpio_get_config {
60e2723
+	u32 gpio;
60e2723
+	u32 direction;
60e2723
+	u32 polarity;
60e2723
+	u32 term_en;
60e2723
+	u32 term_pull_up;
60e2723
+};
60e2723
+
60e2723
+struct gpio_get_set_state {
60e2723
+	u32 gpio;
60e2723
+	u32 state;
60e2723
+};
60e2723
+
60e2723
+static int rpi_exp_gpio_get_polarity(struct gpio_chip *gc, unsigned int off)
60e2723
+{
60e2723
+	struct rpi_exp_gpio *gpio;
60e2723
+	struct gpio_get_config get;
60e2723
+	int ret;
60e2723
+
60e2723
+	gpio = gpiochip_get_data(gc);
60e2723
+
60e2723
+	get.gpio = off + RPI_EXP_GPIO_BASE;	/* GPIO to update */
60e2723
+
60e2723
+	ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG,
60e2723
+				    &get, sizeof(get));
60e2723
+	if (ret || get.gpio != 0) {
60e2723
+		dev_err(gc->parent, "Failed to get GPIO %u config (%d %x)\n",
60e2723
+			off, ret, get.gpio);
60e2723
+		return ret ? ret : -EIO;
60e2723
+	}
60e2723
+	return get.polarity;
60e2723
+}
60e2723
+
60e2723
+static int rpi_exp_gpio_dir_in(struct gpio_chip *gc, unsigned int off)
60e2723
+{
60e2723
+	struct rpi_exp_gpio *gpio;
60e2723
+	struct gpio_set_config set_in;
60e2723
+	int ret;
60e2723
+
60e2723
+	gpio = gpiochip_get_data(gc);
60e2723
+
60e2723
+	set_in.gpio = off + RPI_EXP_GPIO_BASE;	/* GPIO to update */
60e2723
+	set_in.direction = RPI_EXP_GPIO_DIR_IN;
60e2723
+	set_in.term_en = 0;		/* termination disabled */
60e2723
+	set_in.term_pull_up = 0;	/* n/a as termination disabled */
60e2723
+	set_in.state = 0;		/* n/a as configured as an input */
60e2723
+
60e2723
+	ret = rpi_exp_gpio_get_polarity(gc, off);
60e2723
+	if (ret < 0)
60e2723
+		return ret;
60e2723
+	set_in.polarity = ret;		/* Retain existing setting */
60e2723
+
60e2723
+	ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG,
60e2723
+				    &set_in, sizeof(set_in));
60e2723
+	if (ret || set_in.gpio != 0) {
60e2723
+		dev_err(gc->parent, "Failed to set GPIO %u to input (%d %x)\n",
60e2723
+			off, ret, set_in.gpio);
60e2723
+		return ret ? ret : -EIO;
60e2723
+	}
60e2723
+	return 0;
60e2723
+}
60e2723
+
60e2723
+static int rpi_exp_gpio_dir_out(struct gpio_chip *gc, unsigned int off, int val)
60e2723
+{
60e2723
+	struct rpi_exp_gpio *gpio;
60e2723
+	struct gpio_set_config set_out;
60e2723
+	int ret;
60e2723
+
60e2723
+	gpio = gpiochip_get_data(gc);
60e2723
+
60e2723
+	set_out.gpio = off + RPI_EXP_GPIO_BASE;	/* GPIO to update */
60e2723
+	set_out.direction = RPI_EXP_GPIO_DIR_OUT;
60e2723
+	set_out.term_en = 0;		/* n/a as an output */
60e2723
+	set_out.term_pull_up = 0;	/* n/a as termination disabled */
60e2723
+	set_out.state = val;		/* Output state */
60e2723
+
60e2723
+	ret = rpi_exp_gpio_get_polarity(gc, off);
60e2723
+	if (ret < 0)
60e2723
+		return ret;
60e2723
+	set_out.polarity = ret;		/* Retain existing setting */
60e2723
+
60e2723
+	ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG,
60e2723
+				    &set_out, sizeof(set_out));
60e2723
+	if (ret || set_out.gpio != 0) {
60e2723
+		dev_err(gc->parent, "Failed to set GPIO %u to output (%d %x)\n",
60e2723
+			off, ret, set_out.gpio);
60e2723
+		return ret ? ret : -EIO;
60e2723
+	}
60e2723
+	return 0;
60e2723
+}
60e2723
+
60e2723
+static int rpi_exp_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
60e2723
+{
60e2723
+	struct rpi_exp_gpio *gpio;
60e2723
+	struct gpio_get_config get;
60e2723
+	int ret;
60e2723
+
60e2723
+	gpio = gpiochip_get_data(gc);
60e2723
+
60e2723
+	get.gpio = off + RPI_EXP_GPIO_BASE;	/* GPIO to update */
60e2723
+
60e2723
+	ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG,
60e2723
+				    &get, sizeof(get));
60e2723
+	if (ret || get.gpio != 0) {
60e2723
+		dev_err(gc->parent,
60e2723
+			"Failed to get GPIO %u config (%d %x)\n", off, ret,
60e2723
+			get.gpio);
60e2723
+		return ret ? ret : -EIO;
60e2723
+	}
60e2723
+	return !get.direction;
60e2723
+}
60e2723
+
60e2723
+static int rpi_exp_gpio_get(struct gpio_chip *gc, unsigned int off)
60e2723
+{
60e2723
+	struct rpi_exp_gpio *gpio;
60e2723
+	struct gpio_get_set_state get;
60e2723
+	int ret;
60e2723
+
60e2723
+	gpio = gpiochip_get_data(gc);
60e2723
+
60e2723
+	get.gpio = off + RPI_EXP_GPIO_BASE;	/* GPIO to update */
60e2723
+	get.state = 0;		/* storage for returned value */
60e2723
+
60e2723
+	ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_STATE,
60e2723
+					 &get, sizeof(get));
60e2723
+	if (ret || get.gpio != 0) {
60e2723
+		dev_err(gc->parent,
60e2723
+			"Failed to get GPIO %u state (%d %x)\n", off, ret,
60e2723
+			get.gpio);
60e2723
+		return ret ? ret : -EIO;
60e2723
+	}
60e2723
+	return !!get.state;
60e2723
+}
60e2723
+
60e2723
+static void rpi_exp_gpio_set(struct gpio_chip *gc, unsigned int off, int val)
60e2723
+{
60e2723
+	struct rpi_exp_gpio *gpio;
60e2723
+	struct gpio_get_set_state set;
60e2723
+	int ret;
60e2723
+
60e2723
+	gpio = gpiochip_get_data(gc);
60e2723
+
60e2723
+	set.gpio = off + RPI_EXP_GPIO_BASE;	/* GPIO to update */
60e2723
+	set.state = val;	/* Output state */
60e2723
+
60e2723
+	ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_STATE,
60e2723
+					 &set, sizeof(set));
60e2723
+	if (ret || set.gpio != 0)
60e2723
+		dev_err(gc->parent,
60e2723
+			"Failed to set GPIO %u state (%d %x)\n", off, ret,
60e2723
+			set.gpio);
60e2723
+}
60e2723
+
60e2723
+static int rpi_exp_gpio_probe(struct platform_device *pdev)
60e2723
+{
60e2723
+	struct device *dev = &pdev->dev;
60e2723
+	struct device_node *np = dev->of_node;
60e2723
+	struct device_node *fw_node;
60e2723
+	struct rpi_firmware *fw;
60e2723
+	struct rpi_exp_gpio *rpi_gpio;
60e2723
+
60e2723
+	fw_node = of_get_parent(np);
60e2723
+	if (!fw_node) {
60e2723
+		dev_err(dev, "Missing firmware node\n");
60e2723
+		return -ENOENT;
60e2723
+	}
60e2723
+
60e2723
+	fw = rpi_firmware_get(fw_node);
60e2723
+	if (!fw)
60e2723
+		return -EPROBE_DEFER;
60e2723
+
60e2723
+	rpi_gpio = devm_kzalloc(dev, sizeof(*rpi_gpio), GFP_KERNEL);
60e2723
+	if (!rpi_gpio)
60e2723
+		return -ENOMEM;
60e2723
+
60e2723
+	rpi_gpio->fw = fw;
60e2723
+	rpi_gpio->gc.parent = dev;
60e2723
+	rpi_gpio->gc.label = MODULE_NAME;
60e2723
+	rpi_gpio->gc.owner = THIS_MODULE;
60e2723
+	rpi_gpio->gc.of_node = np;
60e2723
+	rpi_gpio->gc.base = -1;
60e2723
+	rpi_gpio->gc.ngpio = NUM_GPIO;
60e2723
+
60e2723
+	rpi_gpio->gc.direction_input = rpi_exp_gpio_dir_in;
60e2723
+	rpi_gpio->gc.direction_output = rpi_exp_gpio_dir_out;
60e2723
+	rpi_gpio->gc.get_direction = rpi_exp_gpio_get_direction;
60e2723
+	rpi_gpio->gc.get = rpi_exp_gpio_get;
60e2723
+	rpi_gpio->gc.set = rpi_exp_gpio_set;
60e2723
+	rpi_gpio->gc.can_sleep = true;
60e2723
+
60e2723
+	return devm_gpiochip_add_data(dev, &rpi_gpio->gc, rpi_gpio);
60e2723
+}
60e2723
+
60e2723
+static const struct of_device_id rpi_exp_gpio_ids[] = {
60e2723
+	{ .compatible = "raspberrypi,firmware-gpio" },
60e2723
+	{ }
60e2723
+};
60e2723
+MODULE_DEVICE_TABLE(of, rpi_exp_gpio_ids);
60e2723
+
60e2723
+static struct platform_driver rpi_exp_gpio_driver = {
60e2723
+	.driver	= {
60e2723
+		.name		= MODULE_NAME,
60e2723
+		.of_match_table	= of_match_ptr(rpi_exp_gpio_ids),
60e2723
+	},
60e2723
+	.probe	= rpi_exp_gpio_probe,
60e2723
+};
60e2723
+module_platform_driver(rpi_exp_gpio_driver);
60e2723
+
60e2723
+MODULE_LICENSE("GPL");
60e2723
+MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.org>");
60e2723
+MODULE_DESCRIPTION("Raspberry Pi 3 expander GPIO driver");
60e2723
+MODULE_ALIAS("platform:rpi-exp-gpio");
60e2723
From patchwork Tue Feb 20 12:19:34 2018
60e2723
Content-Type: text/plain; charset="utf-8"
60e2723
MIME-Version: 1.0
60e2723
Content-Transfer-Encoding: 7bit
60e2723
Subject: [v5,4/5] ARM: dts: bcm2835: make the firmware node into a bus
60e2723
From: Baruch Siach <baruch@tkos.co.il>
60e2723
X-Patchwork-Id: 10229961
60e2723
Message-Id: <43f9082a6835df6d7bcd3e16d79db687c52826d2.1519128054.git.baruch@tkos.co.il>
60e2723
To: Linus Walleij <linus.walleij@linaro.org>,
60e2723
 Dave Stevenson <dave.stevenson@raspberrypi.org>,
60e2723
 Eric Anholt <eric@anholt.net>, Stefan Wahren <stefan.wahren@i2se.com>
60e2723
Cc: devicetree@vger.kernel.org, Baruch Siach <baruch@tkos.co.il>,
60e2723
 linux-gpio@vger.kernel.org, Michael Zoran <mzoran@crowfest.net>,
60e2723
 Rob Herring <robh+dt@kernel.org>, linux-rpi-kernel@lists.infradead.org,
60e2723
 Frank Rowand <frowand.list@gmail.com>, linux-arm-kernel@lists.infradead.org
60e2723
Date: Tue, 20 Feb 2018 14:19:34 +0200
60e2723
60e2723
This allows adding devices for which the firmware exposes control interface
60e2723
via the mailbox. An example of such device is the GPIO expander.
60e2723
60e2723
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
60e2723
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
60e2723
---
60e2723
v4: New patch in this series
60e2723
---
60e2723
 arch/arm/boot/dts/bcm2835-rpi.dtsi | 4 +++-
60e2723
 1 file changed, 3 insertions(+), 1 deletion(-)
60e2723
60e2723
diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi
60e2723
index e36c392a2b8f..0198bd46ef7c 100644
60e2723
--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
60e2723
+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
60e2723
@@ -18,7 +18,9 @@
60e2723
 
60e2723
 	soc {
60e2723
 		firmware: firmware {
60e2723
-			compatible = "raspberrypi,bcm2835-firmware";
60e2723
+			compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
60e2723
+			#address-cells = <0>;
60e2723
+			#size-cells = <0>;
60e2723
 			mboxes = <&mailbox>;
60e2723
 		};
60e2723
 
60e2723
From patchwork Tue Feb 20 12:19:35 2018
60e2723
Content-Type: text/plain; charset="utf-8"
60e2723
MIME-Version: 1.0
60e2723
Content-Transfer-Encoding: 7bit
60e2723
Subject: [v5,5/5] ARM: dts: bcm2837-rpi-3-b: add GPIO expander
60e2723
From: Baruch Siach <baruch@tkos.co.il>
60e2723
X-Patchwork-Id: 10229995
60e2723
Message-Id: <a6d59692dc4847e0b1639a26542e28c95ad5240f.1519128054.git.baruch@tkos.co.il>
60e2723
To: Linus Walleij <linus.walleij@linaro.org>,
60e2723
 Dave Stevenson <dave.stevenson@raspberrypi.org>,
60e2723
 Eric Anholt <eric@anholt.net>, Stefan Wahren <stefan.wahren@i2se.com>
60e2723
Cc: devicetree@vger.kernel.org, Baruch Siach <baruch@tkos.co.il>,
60e2723
 linux-gpio@vger.kernel.org, Michael Zoran <mzoran@crowfest.net>,
60e2723
 Rob Herring <robh+dt@kernel.org>, linux-rpi-kernel@lists.infradead.org,
60e2723
 Frank Rowand <frowand.list@gmail.com>, linux-arm-kernel@lists.infradead.org
60e2723
Date: Tue, 20 Feb 2018 14:19:35 +0200
60e2723
60e2723
Add a description of the RPi3 GPIO expander that the VC4 firmware controls.
60e2723
60e2723
Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
60e2723
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
60e2723
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
60e2723
---
60e2723
v5:
60e2723
  * Drop the 'firmware' property
60e2723
60e2723
v4:
60e2723
  * Move the gpio node under the firmware node
60e2723
  * Rename the gpio node to plain 'gpio'
60e2723
  * Add Stefan's ack
60e2723
60e2723
v3:
60e2723
  * List GPIO names one per line.
60e2723
60e2723
v2:
60e2723
  * Move GPIO expander node out of the soc container
60e2723
  * Rename compatible string
60e2723
  * Add gpio-line-names property
60e2723
---
60e2723
 arch/arm/boot/dts/bcm2837-rpi-3-b.dts | 17 +++++++++++++++++
60e2723
 1 file changed, 17 insertions(+)
60e2723
60e2723
diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
60e2723
index 3e4ed7c5b0b3..0b31d995a066 100644
60e2723
--- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
60e2723
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
60e2723
@@ -25,6 +25,23 @@
60e2723
 	};
60e2723
 };
60e2723
 
60e2723
+&firmware {
60e2723
+	expgpio: gpio {
60e2723
+		compatible = "raspberrypi,firmware-gpio";
60e2723
+		gpio-controller;
60e2723
+		#gpio-cells = <2>;
60e2723
+		gpio-line-names = "BT_ON",
60e2723
+				  "WL_ON",
60e2723
+				  "STATUS_LED",
60e2723
+				  "LAN_RUN",
60e2723
+				  "HPD_N",
60e2723
+				  "CAM_GPIO0",
60e2723
+				  "CAM_GPIO1",
60e2723
+				  "PWR_LOW_N";
60e2723
+		status = "okay";
60e2723
+	};
60e2723
+};
60e2723
+
60e2723
 /* uart0 communicates with the BT module */
60e2723
 &uart0 {
60e2723
 	pinctrl-names = "default";