projects/RPi*: add RPi 3 support

Signed-off-by: Stephan Raue <stephan@openelec.tv>
This commit is contained in:
Stephan Raue 2016-02-28 01:54:10 +01:00
parent 655d9214aa
commit 8c20ca7ce4
4 changed files with 1122 additions and 0 deletions

View File

@ -1603,6 +1603,7 @@ CONFIG_GPIO_SYSFS=y
#
# CONFIG_GPIO_74XX_MMIO is not set
# CONFIG_GPIO_ALTERA is not set
CONFIG_GPIO_BCM_VIRT=y
# CONFIG_GPIO_DWAPB is not set
# CONFIG_GPIO_EM is not set
# CONFIG_GPIO_GENERIC_PLATFORM is not set

View File

@ -0,0 +1,560 @@
From 669972f088089e7d2ac95ce0e3a9fd9a7f05bc4e Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 23 Feb 2016 19:56:04 +0000
Subject: [PATCH 1/3] bcm2835-virtgpio: Virtual GPIO driver
Add a virtual GPIO driver that uses the firmware mailbox interface to
request that the VPU toggles LEDs.
---
arch/arm/configs/bcm2709_defconfig | 1 +
drivers/gpio/Kconfig | 6 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-bcm-virt.c | 180 +++++++++++++++++++++++++++++
include/soc/bcm2835/raspberrypi-firmware.h | 1 +
5 files changed, 189 insertions(+)
create mode 100644 drivers/gpio/gpio-bcm-virt.c
diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig
index 4bcb1d8..bead8f4 100644
--- a/arch/arm/configs/bcm2709_defconfig
+++ b/arch/arm/configs/bcm2709_defconfig
@@ -607,6 +607,7 @@ CONFIG_PPS=m
CONFIG_PPS_CLIENT_LDISC=m
CONFIG_PPS_CLIENT_GPIO=m
CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_BCM_VIRT=y
CONFIG_GPIO_ARIZONA=m
CONFIG_GPIO_STMPE=y
CONFIG_W1=m
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index caefe80..8394d1e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -126,6 +126,12 @@ config GPIO_BCM_KONA
help
Turn on GPIO support for Broadcom "Kona" chips.
+config GPIO_BCM_VIRT
+ bool "Broadcom Virt GPIO"
+ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST)
+ help
+ Turn on virtual GPIO support for Broadcom BCM283X chips.
+
config GPIO_CLPS711X
tristate "CLPS711X GPIO support"
depends on ARCH_CLPS711X || COMPILE_TEST
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index f71bb97..7234ba8 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
+obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c
new file mode 100644
index 0000000..53edcb4
--- /dev/null
+++ b/drivers/gpio/gpio-bcm-virt.c
@@ -0,0 +1,180 @@
+/*
+ * brcmvirt GPIO driver
+ *
+ * Copyright (C) 2012,2013 Dom Cobley <popcornmix@gmail.com>
+ * Based on gpio-clps711x.c by Alexander Shiyan <shc_work@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/basic_mmio_gpio.h>
+#include <linux/platform_device.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+#define MODULE_NAME "brcmvirt-gpio"
+#define NUM_GPIO 2
+
+struct brcmvirt_gpio {
+ struct gpio_chip gc;
+ u32 __iomem *ts_base;
+ /* two packed 16-bit counts of enabled and disables
+ Allows host to detect a brief enable that was missed */
+ u32 enables_disables[NUM_GPIO];
+};
+
+static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off)
+{
+ struct brcmvirt_gpio *gpio;
+ gpio = container_of(gc, struct brcmvirt_gpio, gc);
+ return -EINVAL;
+}
+
+static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val)
+{
+ struct brcmvirt_gpio *gpio;
+ gpio = container_of(gc, struct brcmvirt_gpio, gc);
+ return 0;
+}
+
+static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off)
+{
+ struct brcmvirt_gpio *gpio;
+ unsigned v;
+ gpio = container_of(gc, struct brcmvirt_gpio, gc);
+ v = readl(gpio->ts_base + off);
+ return (v >> off) & 1;
+}
+
+static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val)
+{
+ struct brcmvirt_gpio *gpio;
+ u16 enables, disables;
+ s16 diff;
+ bool lit;
+ gpio = container_of(gc, struct brcmvirt_gpio, gc);
+ enables = gpio->enables_disables[off] >> 16;
+ disables = gpio->enables_disables[off] >> 0;
+ diff = (s16)(enables - disables);
+ lit = diff > 0;
+ if ((val && lit) || (!val && !lit))
+ return;
+ if (val)
+ enables++;
+ else
+ disables++;
+ diff = (s16)(enables - disables);
+ BUG_ON(diff != 0 && diff != 1);
+ gpio->enables_disables[off] = (enables << 16) | (disables << 0);
+ writel(gpio->enables_disables[off], gpio->ts_base + off);
+}
+
+static int brcmvirt_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *fw_node;
+ struct rpi_firmware *fw;
+ struct brcmvirt_gpio *ucb;
+ u32 gpiovirtbuf;
+ int err = 0;
+
+ fw_node = of_parse_phandle(np, "firmware", 0);
+ if (!fw_node) {
+ dev_err(dev, "Missing firmware node\n");
+ return -ENOENT;
+ }
+
+ fw = rpi_firmware_get(fw_node);
+ if (!fw)
+ return -EPROBE_DEFER;
+
+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF,
+ &gpiovirtbuf, sizeof(gpiovirtbuf));
+
+ if (err) {
+ dev_err(dev, "Failed to get gpiovirtbuf\n");
+ goto err;
+ }
+
+ if (!gpiovirtbuf) {
+ dev_err(dev, "No virtgpio buffer\n");
+ err = -ENOENT;
+ goto err;
+ }
+
+ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL);
+ if (!ucb) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ // mmap the physical memory
+ gpiovirtbuf &= ~0xc0000000;
+ ucb->ts_base = ioremap(gpiovirtbuf, 4096);
+ if (ucb->ts_base == NULL) {
+ dev_err(dev, "Failed to map physical address\n");
+ err = -ENOENT;
+ goto err;
+ }
+
+ ucb->gc.label = MODULE_NAME;
+ ucb->gc.owner = THIS_MODULE;
+ ucb->gc.dev = dev;
+ ucb->gc.of_node = np;
+ ucb->gc.base = 100;
+ ucb->gc.ngpio = NUM_GPIO;
+
+ ucb->gc.direction_input = brcmvirt_gpio_dir_in;
+ ucb->gc.direction_output = brcmvirt_gpio_dir_out;
+ ucb->gc.get = brcmvirt_gpio_get;
+ ucb->gc.set = brcmvirt_gpio_set;
+ ucb->gc.can_sleep = true;
+
+ err = gpiochip_add(&ucb->gc);
+ if (err)
+ goto err;
+
+ platform_set_drvdata(pdev, ucb);
+
+err:
+ return err;
+
+}
+
+static int brcmvirt_gpio_remove(struct platform_device *pdev)
+{
+ int err = 0;
+ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev);
+
+ gpiochip_remove(&ucb->gc);
+ iounmap(ucb->ts_base);
+ return err;
+}
+
+static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = {
+ { .compatible = "brcm,bcm2835-virtgpio" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids);
+
+static struct platform_driver brcmvirt_gpio_driver = {
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(brcmvirt_gpio_ids),
+ },
+ .probe = brcmvirt_gpio_probe,
+ .remove = brcmvirt_gpio_remove,
+};
+module_platform_driver(brcmvirt_gpio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dom Cobley <popcornmix@gmail.com>");
+MODULE_DESCRIPTION("brcmvirt GPIO driver");
+MODULE_ALIAS("platform:brcmvirt-gpio");
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index ffb0f82..c3965ee 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -90,6 +90,7 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001,
RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
--
1.9.1
From bb7b6bb6fe766c5dfc940143dbff402df8a3637c Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 16 Feb 2016 15:11:58 +0000
Subject: [PATCH 2/3] BCM270X_DT: Add Pi3 support
---
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 186 ++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/bcm2710.dtsi | 76 ++++++++++++++
3 files changed, 263 insertions(+)
create mode 100644 arch/arm/boot/dts/bcm2710-rpi-3-b.dts
create mode 100644 arch/arm/boot/dts/bcm2710.dtsi
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index faf293f..71c77cc 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -4,6 +4,7 @@ dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b.dtb
dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b-plus.dtb
dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-cm.dtb
dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb
+dtb-$(CONFIG_BCM2709_DT) += bcm2710-rpi-3-b.dtb
# Raspberry Pi
ifeq ($(CONFIG_BCM2708_DT),y)
diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
new file mode 100644
index 0000000..5074c88
--- /dev/null
+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
@@ -0,0 +1,186 @@
+/dts-v1/;
+
+/include/ "bcm2710.dtsi"
+
+/ {
+ model = "Raspberry Pi 3 Model B";
+};
+
+&gpio {
+ sdhost_pins: sdhost_pins {
+ brcm,pins = <48 49 50 51 52 53>;
+ brcm,function = <4>; /* alt0 */
+ };
+
+ spi0_pins: spi0_pins {
+ brcm,pins = <7 8 9 10 11>;
+ brcm,function = <4>; /* alt0 */
+ };
+
+ i2c0_pins: i2c0 {
+ brcm,pins = <0 1>;
+ brcm,function = <4>;
+ };
+
+ i2c1_pins: i2c1 {
+ brcm,pins = <2 3>;
+ brcm,function = <4>;
+ };
+
+ i2s_pins: i2s {
+ brcm,pins = <18 19 20 21>;
+ brcm,function = <4>; /* alt0 */
+ };
+
+ sdio_pins: sdio_pins {
+ brcm,pins = <34 35 36 37 38 39>;
+ brcm,function = <7 7 7 7 7 7>; /* alt3 = SD1 */
+ brcm,pull = <0 2 2 2 2 2>;
+ };
+
+ bt_pins: bt_pins {
+ brcm,pins = <28 29 30 31 43>;
+ brcm,function = <6 6 6 6 4>; /* alt2:PCM alt0:GPCLK2 */
+ brcm,pull = <0 0 0 0 0>;
+ };
+
+ uart0_pins: uart0_pins {
+ brcm,pins = <32 33>;
+ brcm,function = <7>; /* alt3=UART0 */
+ brcm,pull = <0 0>;
+ };
+
+ uart1_pins: uart1_pins {
+ brcm,pins = <14 15>;
+ brcm,function = <2>; /* alt5=UART1 */
+ brcm,pull = <0 0>;
+ };
+};
+
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_pins>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&mmc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio_pins>;
+ non-removable;
+ bus-width = <4>;
+ status = "okay";
+ brcm,overclock-50 = <0>;
+};
+
+&soc {
+ virtgpio: virtgpio {
+ compatible = "brcm,bcm2835-virtgpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ firmware = <&firmware>;
+ status = "okay";
+ };
+};
+
+&fb {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins &bt_pins>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>;
+ status = "okay";
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>;
+ cs-gpios = <0 0>;
+
+ spidev@0{
+ compatible = "spidev";
+ reg = <0>; /* CE0 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-max-frequency = <500000>;
+ };
+
+ spidev@1{
+ compatible = "spidev";
+ reg = <1>; /* CE1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-max-frequency = <500000>;
+ };
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ clock-frequency = <100000>;
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ clock-frequency = <100000>;
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+};
+
+&i2s {
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s_pins>;
+};
+
+&random {
+ status = "okay";
+};
+
+&leds {
+ act_led: act {
+ label = "led0";
+ linux,default-trigger = "mmc0";
+ gpios = <&virtgpio 0 0>;
+ };
+};
+
+/ {
+ chosen {
+ bootargs = "8250.nr_uarts=1";
+ };
+};
+
+/ {
+ __overrides__ {
+ uart0 = <&uart0>,"status";
+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0";
+ i2s = <&i2s>,"status";
+ spi = <&spi0>,"status";
+ i2c0 = <&i2c0>,"status";
+ i2c1 = <&i2c1>,"status";
+ i2c2_iknowwhatimdoing = <&i2c2>,"status";
+ i2c0_baudrate = <&i2c0>,"clock-frequency:0";
+ i2c1_baudrate = <&i2c1>,"clock-frequency:0";
+ i2c2_baudrate = <&i2c2>,"clock-frequency:0";
+ core_freq = <&clk_core>,"clock-frequency:0";
+
+ act_led_gpio = <&act_led>,"gpios:4";
+ act_led_activelow = <&act_led>,"gpios:8";
+ act_led_trigger = <&act_led>,"linux,default-trigger";
+
+ audio = <&audio>,"status";
+ watchdog = <&watchdog>,"status";
+ random = <&random>,"status";
+ };
+};
diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi
new file mode 100644
index 0000000..dce553c
--- /dev/null
+++ b/arch/arm/boot/dts/bcm2710.dtsi
@@ -0,0 +1,76 @@
+/include/ "bcm2708_common.dtsi"
+
+/ {
+ compatible = "brcm,bcm2710","brcm,bcm2709";
+ model = "BCM2710";
+
+ chosen {
+ /* No padding required - the boot loader can do that. */
+ bootargs = "";
+ };
+
+ soc {
+ ranges = <0x7e000000 0x3f000000 0x01000000>;
+
+ arm-pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <3 9>;
+ };
+
+ gpiomem {
+ compatible = "brcm,bcm2835-gpiomem";
+ reg = <0x7e200000 0x1000>;
+ status = "okay";
+ };
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ clock-frequency = <19200000>;
+ interrupts = <3 0>, // PHYS_SECURE_PPI
+ <3 1>, // PHYS_NONSECURE_PPI
+ <3 3>, // VIRT_PPI
+ <3 2>; // HYP_PPI
+ always-on;
+ };
+
+ cpus: cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ v7_cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x000>;
+ clock-frequency = <800000000>;
+ };
+
+ v7_cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x001>;
+ clock-frequency = <800000000>;
+ };
+
+ v7_cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x002>;
+ clock-frequency = <800000000>;
+ };
+
+ v7_cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x003>;
+ clock-frequency = <800000000>;
+ };
+ };
+
+ __overrides__ {
+ arm_freq = <&v7_cpu0>, "clock-frequency:0",
+ <&v7_cpu1>, "clock-frequency:0",
+ <&v7_cpu2>, "clock-frequency:0",
+ <&v7_cpu3>, "clock-frequency:0";
+ };
+};
--
1.9.1

View File

@ -1655,6 +1655,7 @@ CONFIG_GPIO_SYSFS=y
#
# CONFIG_GPIO_74XX_MMIO is not set
# CONFIG_GPIO_ALTERA is not set
CONFIG_GPIO_BCM_VIRT=y
# CONFIG_GPIO_DWAPB is not set
# CONFIG_GPIO_EM is not set
# CONFIG_GPIO_GENERIC_PLATFORM is not set

View File

@ -0,0 +1,560 @@
From 669972f088089e7d2ac95ce0e3a9fd9a7f05bc4e Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 23 Feb 2016 19:56:04 +0000
Subject: [PATCH 1/3] bcm2835-virtgpio: Virtual GPIO driver
Add a virtual GPIO driver that uses the firmware mailbox interface to
request that the VPU toggles LEDs.
---
arch/arm/configs/bcm2709_defconfig | 1 +
drivers/gpio/Kconfig | 6 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-bcm-virt.c | 180 +++++++++++++++++++++++++++++
include/soc/bcm2835/raspberrypi-firmware.h | 1 +
5 files changed, 189 insertions(+)
create mode 100644 drivers/gpio/gpio-bcm-virt.c
diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig
index 4bcb1d8..bead8f4 100644
--- a/arch/arm/configs/bcm2709_defconfig
+++ b/arch/arm/configs/bcm2709_defconfig
@@ -607,6 +607,7 @@ CONFIG_PPS=m
CONFIG_PPS_CLIENT_LDISC=m
CONFIG_PPS_CLIENT_GPIO=m
CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_BCM_VIRT=y
CONFIG_GPIO_ARIZONA=m
CONFIG_GPIO_STMPE=y
CONFIG_W1=m
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index caefe80..8394d1e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -126,6 +126,12 @@ config GPIO_BCM_KONA
help
Turn on GPIO support for Broadcom "Kona" chips.
+config GPIO_BCM_VIRT
+ bool "Broadcom Virt GPIO"
+ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST)
+ help
+ Turn on virtual GPIO support for Broadcom BCM283X chips.
+
config GPIO_CLPS711X
tristate "CLPS711X GPIO support"
depends on ARCH_CLPS711X || COMPILE_TEST
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index f71bb97..7234ba8 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
+obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c
new file mode 100644
index 0000000..53edcb4
--- /dev/null
+++ b/drivers/gpio/gpio-bcm-virt.c
@@ -0,0 +1,180 @@
+/*
+ * brcmvirt GPIO driver
+ *
+ * Copyright (C) 2012,2013 Dom Cobley <popcornmix@gmail.com>
+ * Based on gpio-clps711x.c by Alexander Shiyan <shc_work@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/basic_mmio_gpio.h>
+#include <linux/platform_device.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+#define MODULE_NAME "brcmvirt-gpio"
+#define NUM_GPIO 2
+
+struct brcmvirt_gpio {
+ struct gpio_chip gc;
+ u32 __iomem *ts_base;
+ /* two packed 16-bit counts of enabled and disables
+ Allows host to detect a brief enable that was missed */
+ u32 enables_disables[NUM_GPIO];
+};
+
+static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off)
+{
+ struct brcmvirt_gpio *gpio;
+ gpio = container_of(gc, struct brcmvirt_gpio, gc);
+ return -EINVAL;
+}
+
+static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val)
+{
+ struct brcmvirt_gpio *gpio;
+ gpio = container_of(gc, struct brcmvirt_gpio, gc);
+ return 0;
+}
+
+static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off)
+{
+ struct brcmvirt_gpio *gpio;
+ unsigned v;
+ gpio = container_of(gc, struct brcmvirt_gpio, gc);
+ v = readl(gpio->ts_base + off);
+ return (v >> off) & 1;
+}
+
+static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val)
+{
+ struct brcmvirt_gpio *gpio;
+ u16 enables, disables;
+ s16 diff;
+ bool lit;
+ gpio = container_of(gc, struct brcmvirt_gpio, gc);
+ enables = gpio->enables_disables[off] >> 16;
+ disables = gpio->enables_disables[off] >> 0;
+ diff = (s16)(enables - disables);
+ lit = diff > 0;
+ if ((val && lit) || (!val && !lit))
+ return;
+ if (val)
+ enables++;
+ else
+ disables++;
+ diff = (s16)(enables - disables);
+ BUG_ON(diff != 0 && diff != 1);
+ gpio->enables_disables[off] = (enables << 16) | (disables << 0);
+ writel(gpio->enables_disables[off], gpio->ts_base + off);
+}
+
+static int brcmvirt_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *fw_node;
+ struct rpi_firmware *fw;
+ struct brcmvirt_gpio *ucb;
+ u32 gpiovirtbuf;
+ int err = 0;
+
+ fw_node = of_parse_phandle(np, "firmware", 0);
+ if (!fw_node) {
+ dev_err(dev, "Missing firmware node\n");
+ return -ENOENT;
+ }
+
+ fw = rpi_firmware_get(fw_node);
+ if (!fw)
+ return -EPROBE_DEFER;
+
+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF,
+ &gpiovirtbuf, sizeof(gpiovirtbuf));
+
+ if (err) {
+ dev_err(dev, "Failed to get gpiovirtbuf\n");
+ goto err;
+ }
+
+ if (!gpiovirtbuf) {
+ dev_err(dev, "No virtgpio buffer\n");
+ err = -ENOENT;
+ goto err;
+ }
+
+ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL);
+ if (!ucb) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ // mmap the physical memory
+ gpiovirtbuf &= ~0xc0000000;
+ ucb->ts_base = ioremap(gpiovirtbuf, 4096);
+ if (ucb->ts_base == NULL) {
+ dev_err(dev, "Failed to map physical address\n");
+ err = -ENOENT;
+ goto err;
+ }
+
+ ucb->gc.label = MODULE_NAME;
+ ucb->gc.owner = THIS_MODULE;
+ ucb->gc.dev = dev;
+ ucb->gc.of_node = np;
+ ucb->gc.base = 100;
+ ucb->gc.ngpio = NUM_GPIO;
+
+ ucb->gc.direction_input = brcmvirt_gpio_dir_in;
+ ucb->gc.direction_output = brcmvirt_gpio_dir_out;
+ ucb->gc.get = brcmvirt_gpio_get;
+ ucb->gc.set = brcmvirt_gpio_set;
+ ucb->gc.can_sleep = true;
+
+ err = gpiochip_add(&ucb->gc);
+ if (err)
+ goto err;
+
+ platform_set_drvdata(pdev, ucb);
+
+err:
+ return err;
+
+}
+
+static int brcmvirt_gpio_remove(struct platform_device *pdev)
+{
+ int err = 0;
+ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev);
+
+ gpiochip_remove(&ucb->gc);
+ iounmap(ucb->ts_base);
+ return err;
+}
+
+static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = {
+ { .compatible = "brcm,bcm2835-virtgpio" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids);
+
+static struct platform_driver brcmvirt_gpio_driver = {
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(brcmvirt_gpio_ids),
+ },
+ .probe = brcmvirt_gpio_probe,
+ .remove = brcmvirt_gpio_remove,
+};
+module_platform_driver(brcmvirt_gpio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dom Cobley <popcornmix@gmail.com>");
+MODULE_DESCRIPTION("brcmvirt GPIO driver");
+MODULE_ALIAS("platform:brcmvirt-gpio");
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index ffb0f82..c3965ee 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -90,6 +90,7 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
+ RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001,
RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
--
1.9.1
From bb7b6bb6fe766c5dfc940143dbff402df8a3637c Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 16 Feb 2016 15:11:58 +0000
Subject: [PATCH 2/3] BCM270X_DT: Add Pi3 support
---
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 186 ++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/bcm2710.dtsi | 76 ++++++++++++++
3 files changed, 263 insertions(+)
create mode 100644 arch/arm/boot/dts/bcm2710-rpi-3-b.dts
create mode 100644 arch/arm/boot/dts/bcm2710.dtsi
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index faf293f..71c77cc 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -4,6 +4,7 @@ dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b.dtb
dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-b-plus.dtb
dtb-$(CONFIG_BCM2708_DT) += bcm2708-rpi-cm.dtb
dtb-$(CONFIG_BCM2709_DT) += bcm2709-rpi-2-b.dtb
+dtb-$(CONFIG_BCM2709_DT) += bcm2710-rpi-3-b.dtb
# Raspberry Pi
ifeq ($(CONFIG_BCM2708_DT),y)
diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
new file mode 100644
index 0000000..5074c88
--- /dev/null
+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts
@@ -0,0 +1,186 @@
+/dts-v1/;
+
+/include/ "bcm2710.dtsi"
+
+/ {
+ model = "Raspberry Pi 3 Model B";
+};
+
+&gpio {
+ sdhost_pins: sdhost_pins {
+ brcm,pins = <48 49 50 51 52 53>;
+ brcm,function = <4>; /* alt0 */
+ };
+
+ spi0_pins: spi0_pins {
+ brcm,pins = <7 8 9 10 11>;
+ brcm,function = <4>; /* alt0 */
+ };
+
+ i2c0_pins: i2c0 {
+ brcm,pins = <0 1>;
+ brcm,function = <4>;
+ };
+
+ i2c1_pins: i2c1 {
+ brcm,pins = <2 3>;
+ brcm,function = <4>;
+ };
+
+ i2s_pins: i2s {
+ brcm,pins = <18 19 20 21>;
+ brcm,function = <4>; /* alt0 */
+ };
+
+ sdio_pins: sdio_pins {
+ brcm,pins = <34 35 36 37 38 39>;
+ brcm,function = <7 7 7 7 7 7>; /* alt3 = SD1 */
+ brcm,pull = <0 2 2 2 2 2>;
+ };
+
+ bt_pins: bt_pins {
+ brcm,pins = <28 29 30 31 43>;
+ brcm,function = <6 6 6 6 4>; /* alt2:PCM alt0:GPCLK2 */
+ brcm,pull = <0 0 0 0 0>;
+ };
+
+ uart0_pins: uart0_pins {
+ brcm,pins = <32 33>;
+ brcm,function = <7>; /* alt3=UART0 */
+ brcm,pull = <0 0>;
+ };
+
+ uart1_pins: uart1_pins {
+ brcm,pins = <14 15>;
+ brcm,function = <2>; /* alt5=UART1 */
+ brcm,pull = <0 0>;
+ };
+};
+
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_pins>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&mmc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio_pins>;
+ non-removable;
+ bus-width = <4>;
+ status = "okay";
+ brcm,overclock-50 = <0>;
+};
+
+&soc {
+ virtgpio: virtgpio {
+ compatible = "brcm,bcm2835-virtgpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ firmware = <&firmware>;
+ status = "okay";
+ };
+};
+
+&fb {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins &bt_pins>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>;
+ status = "okay";
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>;
+ cs-gpios = <0 0>;
+
+ spidev@0{
+ compatible = "spidev";
+ reg = <0>; /* CE0 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-max-frequency = <500000>;
+ };
+
+ spidev@1{
+ compatible = "spidev";
+ reg = <1>; /* CE1 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-max-frequency = <500000>;
+ };
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ clock-frequency = <100000>;
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ clock-frequency = <100000>;
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+};
+
+&i2s {
+ #sound-dai-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s_pins>;
+};
+
+&random {
+ status = "okay";
+};
+
+&leds {
+ act_led: act {
+ label = "led0";
+ linux,default-trigger = "mmc0";
+ gpios = <&virtgpio 0 0>;
+ };
+};
+
+/ {
+ chosen {
+ bootargs = "8250.nr_uarts=1";
+ };
+};
+
+/ {
+ __overrides__ {
+ uart0 = <&uart0>,"status";
+ uart0_clkrate = <&clk_uart0>,"clock-frequency:0";
+ i2s = <&i2s>,"status";
+ spi = <&spi0>,"status";
+ i2c0 = <&i2c0>,"status";
+ i2c1 = <&i2c1>,"status";
+ i2c2_iknowwhatimdoing = <&i2c2>,"status";
+ i2c0_baudrate = <&i2c0>,"clock-frequency:0";
+ i2c1_baudrate = <&i2c1>,"clock-frequency:0";
+ i2c2_baudrate = <&i2c2>,"clock-frequency:0";
+ core_freq = <&clk_core>,"clock-frequency:0";
+
+ act_led_gpio = <&act_led>,"gpios:4";
+ act_led_activelow = <&act_led>,"gpios:8";
+ act_led_trigger = <&act_led>,"linux,default-trigger";
+
+ audio = <&audio>,"status";
+ watchdog = <&watchdog>,"status";
+ random = <&random>,"status";
+ };
+};
diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi
new file mode 100644
index 0000000..dce553c
--- /dev/null
+++ b/arch/arm/boot/dts/bcm2710.dtsi
@@ -0,0 +1,76 @@
+/include/ "bcm2708_common.dtsi"
+
+/ {
+ compatible = "brcm,bcm2710","brcm,bcm2709";
+ model = "BCM2710";
+
+ chosen {
+ /* No padding required - the boot loader can do that. */
+ bootargs = "";
+ };
+
+ soc {
+ ranges = <0x7e000000 0x3f000000 0x01000000>;
+
+ arm-pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <3 9>;
+ };
+
+ gpiomem {
+ compatible = "brcm,bcm2835-gpiomem";
+ reg = <0x7e200000 0x1000>;
+ status = "okay";
+ };
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ clock-frequency = <19200000>;
+ interrupts = <3 0>, // PHYS_SECURE_PPI
+ <3 1>, // PHYS_NONSECURE_PPI
+ <3 3>, // VIRT_PPI
+ <3 2>; // HYP_PPI
+ always-on;
+ };
+
+ cpus: cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ v7_cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x000>;
+ clock-frequency = <800000000>;
+ };
+
+ v7_cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x001>;
+ clock-frequency = <800000000>;
+ };
+
+ v7_cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x002>;
+ clock-frequency = <800000000>;
+ };
+
+ v7_cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x003>;
+ clock-frequency = <800000000>;
+ };
+ };
+
+ __overrides__ {
+ arm_freq = <&v7_cpu0>, "clock-frequency:0",
+ <&v7_cpu1>, "clock-frequency:0",
+ <&v7_cpu2>, "clock-frequency:0",
+ <&v7_cpu3>, "clock-frequency:0";
+ };
+};
--
1.9.1