Hi,
This patchset adds support for the SDHCI controller on Broadcom BCM2712
SoC in order to make it possible to boot (particularly) Raspberry Pi 5
from SD card. This work is heavily based on downstream contributions.
Patch #1 and 2: introduce the dt binding definitions for, respectively,
the new pin cfg/mux controller and the SD host controller as a preparatory
step for the upcoming dts.
Patch #3: add a somewhat reasonable (*almost* bare-minimum) dts to be used
to boot Rpi5 boards. Since till now there was no support at all for any
2712 based chipset, both the SoC and board dts plus definitions for the
new Pin and SD host controller have been added.
Patch #4: the driver supporting the pin controller. Based on [1] and
successive fix commits.
Patch #5: add SDHCI support. Based on [2] and the next 2 fix commits.
Drop the SD Express implementation for now, that will be added by patch
#6.
Patch #6: this patch offers SD Express support and can be considered totally
optional. The callback plumbing is slightly different w.r.t. the downstream
approach (see [3]), as explained in the patch comment. Not sure what is the best,
any comment is highly appreciated.
Tested succesfully on Raspberry Pi 5 using an SDxC card as the boot device.
Still untested:
- SD Express due to the lack of an Express capable card.
Also, it will need PCIe support first.
- card detection pin, since the sd was the booting and root fs device.
Many thanks,
Andrea
Links:
[1] - https://github.com/raspberrypi/linux/commit/d9b655314a826724538867bf9b6c229d04c25d84
[2] - https://github.com/raspberrypi/linux/commit/e3aa070496e840e72a4dc384718690ea4125fa6a
[3] - https://github.com/raspberrypi/linux/commit/eb1df34db2a9a5b752eba40ee298c4ae87e26e87
Andrea della Porta (6):
dt-bindings: pinctrl: Add support for BCM2712 pin controller
dt-bindings: mmc: Add support for BCM2712 SD host controller
arm64: dts: broadcom: Add support for BCM2712
pinctrl: bcm: Add pinconf/pinmux controller driver for BCM2712
mmc: sdhci-brcmstb: Add BCM2712 support
mmc: sdhci-brcmstb: Add BCM2712 SD Express support
.../bindings/mmc/brcm,sdhci-brcmstb.yaml | 51 +-
.../pinctrl/brcm,bcm2712-pinctrl.yaml | 99 ++
arch/arm64/boot/dts/broadcom/Makefile | 1 +
.../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 313 +++++
arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 81 ++
arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 841 +++++++++++
drivers/mmc/host/Kconfig | 1 +
drivers/mmc/host/sdhci-brcmstb.c | 275 ++++
drivers/pinctrl/bcm/Kconfig | 9 +
drivers/pinctrl/bcm/Makefile | 1 +
drivers/pinctrl/bcm/pinctrl-bcm2712.c | 1247 +++++++++++++++++
11 files changed, 2918 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm2712-pinctrl.yaml
create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712.dtsi
create mode 100644 drivers/pinctrl/bcm/pinctrl-bcm2712.c
--
2.35.3
Signed-off-by: Andrea della Porta <[email protected]>
---
.../bindings/mmc/brcm,sdhci-brcmstb.yaml | 51 ++++++++++++++++++-
1 file changed, 50 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
index cbd3d6c6c77f..6aa137d78e4f 100644
--- a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
+++ b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
@@ -13,6 +13,7 @@ maintainers:
properties:
compatible:
oneOf:
+ - const: brcm,bcm2712-sdhci
- items:
- enum:
- brcm,bcm7216-sdhci
@@ -26,12 +27,16 @@ properties:
- const: brcm,sdhci-brcmstb
reg:
- maxItems: 2
+ minItems: 2
+ maxItems: 4
reg-names:
+ minItems: 2
items:
- const: host
- const: cfg
+ - const: busisol
+ - const: lcpll
interrupts:
maxItems: 1
@@ -60,6 +65,7 @@ properties:
description: Specifies that controller should use auto CMD12
allOf:
+ - $ref: sdhci-common.yaml
- $ref: mmc-controller.yaml#
- if:
properties:
@@ -71,6 +77,28 @@ allOf:
required:
- clock-frequency
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: brcm,bcm2712-sdhci
+
+ then:
+ properties:
+ reg:
+ maxItems: 4
+ clock-names:
+ const: "sw_sdio"
+
+ else:
+ properties:
+ reg:
+ minItems: 2
+ maxItems: 2
+ reg-names:
+ minItems: 2
+ maxItems: 2
+
required:
- compatible
- reg
@@ -114,3 +142,24 @@ examples:
clocks = <&scmi_clk 245>;
clock-names = "sw_sdio";
};
+
+ - |
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ mmc@fff000 {
+ compatible = "brcm,bcm2712-sdhci";
+ reg = <0x10 0x00fff000 0x0 0x260>,
+ <0x10 0x00fff400 0x0 0x200>,
+ <0x10 0x015040b0 0x0 0x4>, // Bus isolation control
+ <0x10 0x015200f0 0x0 0x24>; // LCPLL control misc0-8
+ reg-names = "host", "cfg", "busisol", "lcpll";
+ interrupts = <0x0 0x111 0x4>;
+ clocks = <&clk_emmc2>;
+ sdhci-caps-mask = <0x0000C000 0x0>;
+ sdhci-caps = <0x0 0x0>;
+ mmc-ddr-3_3v;
+ clock-names = "sw_sdio";
+ };
+ };
--
2.35.3
Signed-off-by: Andrea della Porta <[email protected]>
---
arch/arm64/boot/dts/broadcom/Makefile | 1 +
.../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 313 +++++++
arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 81 ++
arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 841 ++++++++++++++++++
4 files changed, 1236 insertions(+)
create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712.dtsi
diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile
index 8b4591ddd27c..92565e9781ad 100644
--- a/arch/arm64/boot/dts/broadcom/Makefile
+++ b/arch/arm64/boot/dts/broadcom/Makefile
@@ -6,6 +6,7 @@ DTC_FLAGS := -@
dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb \
bcm2711-rpi-4-b.dtb \
bcm2711-rpi-cm4-io.dtb \
+ bcm2712-rpi-5-b.dtb \
bcm2837-rpi-3-a-plus.dtb \
bcm2837-rpi-3-b.dtb \
bcm2837-rpi-3-b-plus.dtb \
diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
new file mode 100644
index 000000000000..2ce180a54e5b
--- /dev/null
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
@@ -0,0 +1,313 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/reset/raspberrypi,firmware-reset.h>
+
+#define spi0 _spi0
+#define uart0 _uart0
+
+#include "bcm2712.dtsi"
+
+#undef spi0
+#undef uart0
+
+/ {
+ compatible = "raspberrypi,5-model-b", "brcm,bcm2712";
+ model = "Raspberry Pi 5";
+
+ /* Will be filled by the bootloader */
+ memory@0 {
+ device_type = "memory";
+ reg = <0 0 0x28000000>;
+ };
+
+ leds: leds {
+ compatible = "gpio-leds";
+
+ led_act: led-act {
+ label = "ACT";
+ gpios = <&gio_aon 9 GPIO_ACTIVE_LOW>;
+ default-state = "off";
+ linux,default-trigger = "mmc0";
+ };
+ };
+
+ sd_io_1v8_reg: sd_io_1v8_reg {
+ compatible = "regulator-gpio";
+ regulator-name = "vdd-sd-io";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-settling-time-us = <5000>;
+ gpios = <&gio_aon 3 GPIO_ACTIVE_HIGH>;
+ states = <1800000 0x1
+ 3300000 0x0>;
+ status = "okay";
+ };
+
+ sd_vcc_reg: sd_vcc_reg {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-sd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ enable-active-high;
+ gpios = <&gio_aon 4 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ };
+
+ wl_on_reg: wl_on_reg {
+ compatible = "regulator-fixed";
+ regulator-name = "wl-on-regulator";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ pinctrl-0 = <&wl_on_pins>;
+ pinctrl-names = "default";
+
+ gpio = <&gio 28 GPIO_ACTIVE_HIGH>;
+
+ startup-delay-us = <150000>;
+ enable-active-high;
+ };
+
+ clocks: clocks {
+ };
+};
+
+// Add some labels to 2712 device
+
+// The system UART
+uart10: &_uart0 { status = "okay"; };
+
+// The system SPI for the bootloader EEPROM
+spi10: &_spi0 { status = "okay"; };
+
+#include "bcm2712-rpi.dtsi"
+
+/* SDIO1 is used to drive the SD card */
+&sdio1 {
+ pinctrl-0 = <&emmc_sd_pulls>, <&emmc_aon_cd_pins>;
+ pinctrl-names = "default";
+ vqmmc-supply = <&sd_io_1v8_reg>;
+ vmmc-supply = <&sd_vcc_reg>;
+ bus-width = <4>;
+ sd-uhs-sdr50;
+ sd-uhs-ddr50;
+ sd-uhs-sdr104;
+ cd-gpios = <&gio_aon 5 GPIO_ACTIVE_LOW>;
+ //no-1-8-v;
+ status = "okay";
+};
+
+&pinctrl_aon {
+ emmc_aon_cd_pins: emmc_aon_cd_pins {
+ function = "sd_card_g";
+ pins = "aon_gpio5";
+ bias-pull-up;
+ };
+
+ /* Slight hack - only one PWM pin (status LED) is usable */
+ aon_pwm_1pin: aon_pwm_1pin {
+ function = "aon_pwm";
+ pins = "aon_gpio9";
+ };
+};
+
+&pinctrl {
+ pwr_button_pins: pwr_button_pins {
+ function = "gpio";
+ pins = "gpio20";
+ bias-pull-up;
+ };
+
+ wl_on_pins: wl_on_pins {
+ function = "gpio";
+ pins = "gpio28";
+ };
+
+ bt_shutdown_pins: bt_shutdown_pins {
+ function = "gpio";
+ pins = "gpio29";
+ };
+
+ emmc_sd_pulls: emmc_sd_pulls {
+ pins = "emmc_cmd", "emmc_dat0", "emmc_dat1", "emmc_dat2", "emmc_dat3";
+ bias-pull-up;
+ };
+};
+
+/ {
+ chosen: chosen {
+ bootargs = "reboot=w coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
+ stdout-path = "serial10:115200n8";
+ };
+
+ pwr_button {
+ compatible = "gpio-keys";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwr_button_pins>;
+ status = "okay";
+
+ pwr_key: pwr {
+ label = "pwr_button";
+ // linux,code = <205>; // KEY_SUSPEND
+ linux,code = <116>; // KEY_POWER
+ gpios = <&gio 20 GPIO_ACTIVE_LOW>;
+ debounce-interval = <50>; // ms
+ };
+ };
+};
+
+&pinctrl {
+ spi10_gpio2: spi10_gpio2 {
+ function = "vc_spi0";
+ pins = "gpio2", "gpio3", "gpio4";
+ bias-disable;
+ };
+
+ spi10_cs_gpio1: spi10_cs_gpio1 {
+ function = "gpio";
+ pins = "gpio1";
+ bias-pull-up;
+ };
+};
+
+spi10_pins: &spi10_gpio2 {};
+spi10_cs_pins: &spi10_cs_gpio1 {};
+
+&spi10 {
+ pinctrl-names = "default";
+ cs-gpios = <&gio 1 1>;
+ pinctrl-0 = <&spi10_pins &spi10_cs_pins>;
+
+ spidev10: spidev@0 {
+ compatible = "spidev";
+ reg = <0>; /* CE0 */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-max-frequency = <20000000>;
+ status = "okay";
+ };
+};
+
+// =============================================
+// Board specific stuff here
+
+&gio_aon {
+ // Don't use GIO_AON as an interrupt controller because it will
+ // clash with the firmware monitoring the PMIC interrupt via the VPU.
+
+ /delete-property/ interrupt-controller;
+};
+
+&main_aon_irq {
+ // Don't use the MAIN_AON_IRQ interrupt controller because it will
+ // clash with the firmware monitoring the PMIC interrupt via the VPU.
+
+ status = "disabled";
+};
+
+&gio {
+ // The GPIOs above 35 are not used on Pi 5, so shrink the upper bank
+ // to reduce the clutter in gpioinfo/pinctrl
+ brcm,gpio-bank-widths = <32 4>;
+
+ gpio-line-names =
+ "-", // GPIO_000
+ "2712_BOOT_CS_N", // GPIO_001
+ "2712_BOOT_MISO", // GPIO_002
+ "2712_BOOT_MOSI", // GPIO_003
+ "2712_BOOT_SCLK", // GPIO_004
+ "-", // GPIO_005
+ "-", // GPIO_006
+ "-", // GPIO_007
+ "-", // GPIO_008
+ "-", // GPIO_009
+ "-", // GPIO_010
+ "-", // GPIO_011
+ "-", // GPIO_012
+ "-", // GPIO_013
+ "PCIE_SDA", // GPIO_014
+ "PCIE_SCL", // GPIO_015
+ "-", // GPIO_016
+ "-", // GPIO_017
+ "-", // GPIO_018
+ "-", // GPIO_019
+ "PWR_GPIO", // GPIO_020
+ "2712_G21_FS", // GPIO_021
+ "-", // GPIO_022
+ "-", // GPIO_023
+ "BT_RTS", // GPIO_024
+ "BT_CTS", // GPIO_025
+ "BT_TXD", // GPIO_026
+ "BT_RXD", // GPIO_027
+ "WL_ON", // GPIO_028
+ "BT_ON", // GPIO_029
+ "WIFI_SDIO_CLK", // GPIO_030
+ "WIFI_SDIO_CMD", // GPIO_031
+ "WIFI_SDIO_D0", // GPIO_032
+ "WIFI_SDIO_D1", // GPIO_033
+ "WIFI_SDIO_D2", // GPIO_034
+ "WIFI_SDIO_D3"; // GPIO_035
+};
+
+&gio_aon {
+ gpio-line-names =
+ "RP1_SDA", // AON_GPIO_00
+ "RP1_SCL", // AON_GPIO_01
+ "RP1_RUN", // AON_GPIO_02
+ "SD_IOVDD_SEL", // AON_GPIO_03
+ "SD_PWR_ON", // AON_GPIO_04
+ "SD_CDET_N", // AON_GPIO_05
+ "SD_FLG_N", // AON_GPIO_06
+ "-", // AON_GPIO_07
+ "2712_WAKE", // AON_GPIO_08
+ "2712_STAT_LED", // AON_GPIO_09
+ "-", // AON_GPIO_10
+ "-", // AON_GPIO_11
+ "PMIC_INT", // AON_GPIO_12
+ "UART_TX_FS", // AON_GPIO_13
+ "UART_RX_FS", // AON_GPIO_14
+ "-", // AON_GPIO_15
+ "-", // AON_GPIO_16
+
+ // Pad bank0 out to 32 entries
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+
+ "HDMI0_SCL", // AON_SGPIO_00
+ "HDMI0_SDA", // AON_SGPIO_01
+ "HDMI1_SCL", // AON_SGPIO_02
+ "HDMI1_SDA", // AON_SGPIO_03
+ "PMIC_SCL", // AON_SGPIO_04
+ "PMIC_SDA"; // AON_SGPIO_05
+};
+
+/ {
+ aliases {
+ blconfig = &blconfig;
+ blpubkey = &blpubkey;
+ console = &uart10;
+ mailbox = &mailbox;
+ mmc0 = &sdio1;
+ uart10 = &uart10;
+ serial10 = &uart10;
+ gpio1 = &gio;
+ gpio2 = &gio_aon;
+ gpio3 = &pinctrl;
+ gpio4 = &pinctrl_aon;
+ };
+
+ __overrides__ {
+ button_debounce = <&pwr_key>, "debounce-interval:0";
+ random = <&random>, "status";
+ sd_cqe = <&sdio1>, "supports-cqe?";
+ suspend = <&pwr_key>, "linux,code:0=205";
+ act_led_activelow = <&led_act>,"gpios:8";
+ act_led_trigger = <&led_act>, "linux,default-trigger";
+ };
+};
diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
new file mode 100644
index 000000000000..d04e39b9c0b6
--- /dev/null
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/power/raspberrypi-power.h>
+
+&soc {
+ firmware: firmware {
+ compatible = "raspberrypi,bcm2835-firmware", "simple-mfd";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mboxes = <&mailbox>;
+ dma-ranges;
+
+ firmware_clocks: clocks {
+ compatible = "raspberrypi,firmware-clocks";
+ #clock-cells = <1>;
+ };
+
+ reset: reset {
+ compatible = "raspberrypi,firmware-reset";
+ #reset-cells = <1>;
+ };
+ };
+
+ power: power {
+ compatible = "raspberrypi,bcm2835-power";
+ firmware = <&firmware>;
+ #power-domain-cells = <1>;
+ };
+
+ /* Define these notional regulators for use by overlays, etc. */
+ vdd_3v3_reg: fixedregulator_3v3 {
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "3v3";
+ };
+
+ vdd_5v0_reg: fixedregulator_5v0 {
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-max-microvolt = <5000000>;
+ regulator-min-microvolt = <5000000>;
+ regulator-name = "5v0";
+ };
+};
+
+/ {
+ __overrides__ {
+ arm_freq;
+ };
+};
+
+&rmem {
+ /*
+ * RPi5's co-processor will copy the board's bootloader configuration
+ * into memory for the OS to consume. It'll also update this node with
+ * its placement information.
+ */
+ blconfig: nvram@0 {
+ compatible = "raspberrypi,bootloader-config", "nvmem-rmem";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x0 0x0 0x0>;
+ no-map;
+ status = "disabled";
+ };
+ /*
+ * RPi5 will copy the binary public key blob (if present) from the bootloader
+ * into memory for use by the OS.
+ */
+ blpubkey: nvram@1 {
+ compatible = "raspberrypi,bootloader-public-key", "nvmem-rmem";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x0 0x0 0x0>;
+ no-map;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
new file mode 100644
index 000000000000..fd5a19f68b49
--- /dev/null
+++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
@@ -0,0 +1,841 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/bcm2835-pm.h>
+#include <dt-bindings/phy/phy.h>
+
+/ {
+ compatible = "brcm,bcm2712", "brcm,bcm2711";
+ model = "BCM2712";
+
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ interrupt-parent = <&gicv2>;
+
+ rmem: reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges;
+
+ atf@0 {
+ reg = <0x0 0x0 0x80000>;
+ no-map;
+ };
+
+ cma: linux,cma {
+ compatible = "shared-dma-pool";
+ size = <0x4000000>; /* 64MB */
+ reusable;
+ linux,cma-default;
+
+ /*
+ * arm64 reserves the CMA by default somewhere in
+ * ZONE_DMA32, that's not good enough for the BCM2711
+ * as some devices can only address the lower 1G of
+ * memory (ZONE_DMA).
+ */
+ alloc-ranges = <0x0 0x00000000 0x40000000>;
+ };
+ };
+
+ thermal-zones {
+ cpu_thermal: cpu-thermal {
+ polling-delay-passive = <2000>;
+ polling-delay = <1000>;
+ coefficients = <(-550) 450000>;
+ thermal-sensors = <&thermal>;
+
+ thermal_trips: trips {
+ cpu_crit: cpu-crit {
+ temperature = <110000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling_maps: cooling-maps {
+ };
+ };
+ };
+
+ clk_27MHz: clk-27M {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <27000000>;
+ clock-output-names = "27MHz-clock";
+ };
+
+ clk_108MHz: clk-108M {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <108000000>;
+ clock-output-names = "108MHz-clock";
+ };
+
+ soc: soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ ranges = <0x7c000000 0x10 0x7c000000 0x04000000>;
+ /* Emulate a contiguous 30-bit address range for DMA */
+ dma-ranges = <0xc0000000 0x00 0x00000000 0x40000000>,
+ <0x7c000000 0x10 0x7c000000 0x04000000>;
+
+ system_timer: timer@7c003000 {
+ compatible = "brcm,bcm2835-system-timer";
+ reg = <0x7c003000 0x1000>;
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <1000000>;
+ };
+
+ mailbox: mailbox@7c013880 {
+ compatible = "brcm,bcm2835-mbox";
+ reg = <0x7c013880 0x40>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <0>;
+ };
+
+ disp_intr: interrupt-controller@7c502000 {
+ compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc";
+ reg = <0x7c502000 0x30>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ status = "disabled";
+ };
+
+ dvp: clock@7c700000 {
+ compatible = "brcm,brcm2711-dvp";
+ reg = <0x7c700000 0x10>;
+ clocks = <&clk_108MHz>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ /*
+ * This node is the provider for the enable-method for
+ * bringing up secondary cores.
+ */
+ local_intc: local_intc@7cd00000 {
+ compatible = "brcm,bcm2836-l1-intc";
+ reg = <0x7cd00000 0x100>;
+ };
+
+ uart0: serial@7d001000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x7d001000 0x200>;
+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_uart>,
+ <&clk_vpu>;
+ clock-names = "uartclk", "apb_pclk";
+ arm,primecell-periphid = <0x00241011>;
+ status = "disabled";
+ };
+
+ uart2: serial@7d001400 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x7d001400 0x200>;
+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_uart>,
+ <&clk_vpu>;
+ clock-names = "uartclk", "apb_pclk";
+ arm,primecell-periphid = <0x00241011>;
+ status = "disabled";
+ };
+
+ uart5: serial@7d001a00 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x7d001a00 0x200>;
+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_uart>,
+ <&clk_vpu>;
+ clock-names = "uartclk", "apb_pclk";
+ arm,primecell-periphid = <0x00241011>;
+ status = "disabled";
+ };
+
+ sdhost: mmc@7d002000 {
+ compatible = "brcm,bcm2835-sdhost";
+ reg = <0x7d002000 0x100>;
+ //interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ status = "disabled";
+ };
+
+ i2s: i2s@7d003000 {
+ compatible = "brcm,bcm2835-i2s";
+ reg = <0x7d003000 0x24>;
+ //clocks = <&cprman BCM2835_CLOCK_PCM>;
+ status = "disabled";
+ };
+
+ spi0: spi@7d004000 {
+ compatible = "brcm,bcm2835-spi";
+ reg = <0x7d004000 0x200>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ num-cs = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi3: spi@7d004600 {
+ compatible = "brcm,bcm2835-spi";
+ reg = <0x7d004600 0x0200>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi4: spi@7d004800 {
+ compatible = "brcm,bcm2835-spi";
+ reg = <0x7d004800 0x0200>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi5: spi@7d004a00 {
+ compatible = "brcm,bcm2835-spi";
+ reg = <0x7d004a00 0x0200>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi6: spi@7d004c00 {
+ compatible = "brcm,bcm2835-spi";
+ reg = <0x7d004c00 0x0200>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c0: i2c@7d005000 {
+ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
+ reg = <0x7d005000 0x20>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@7d005600 {
+ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
+ reg = <0x7d005600 0x20>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@7d005800 {
+ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
+ reg = <0x7d005800 0x20>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c5: i2c@7d005a00 {
+ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
+ reg = <0x7d005a00 0x20>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c6: i2c@7d005c00 {
+ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
+ reg = <0x7d005c00 0x20>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c8: i2c@7d005e00 {
+ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c";
+ reg = <0x7d005e00 0x20>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_vpu>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ pwm0: pwm@7d00c000 {
+ compatible = "brcm,bcm2835-pwm";
+ reg = <0x7d00c000 0x28>;
+ assigned-clock-rates = <50000000>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pwm1: pwm@7d00c800 {
+ compatible = "brcm,bcm2835-pwm";
+ reg = <0x7d00c800 0x28>;
+ assigned-clock-rates = <50000000>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ cprman: cprman@7d202000 {
+ compatible = "brcm,bcm2711-cprman";
+ reg = <0x7d202000 0x2000>;
+ #clock-cells = <1>;
+
+ /* CPRMAN derives almost everything from the
+ * platform's oscillator. However, the DSI
+ * pixel clocks come from the DSI analog PHY.
+ */
+ clocks = <&clk_osc>;
+ status = "disabled";
+ };
+
+ random: rng@7d208000 {
+ compatible = "brcm,bcm2711-rng200";
+ reg = <0x7d208000 0x28>;
+ status = "okay";
+ };
+
+ cpu_l2_irq: intc@7d503000 {
+ compatible = "brcm,l2-intc";
+ reg = <0x7d503000 0x18>;
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ pinctrl: pinctrl@7d504100 {
+ compatible = "brcm,bcm2712-pinctrl";
+ reg = <0x7d504100 0x30>;
+
+ uarta_24_pins: uarta_24_pins {
+ pin_rts {
+ function = "uart0";
+ pins = "gpio24";
+ bias-disable;
+ };
+ pin_cts {
+ function = "uart0";
+ pins = "gpio25";
+ bias-pull-up;
+ };
+ pin_txd {
+ function = "uart0";
+ pins = "gpio26";
+ bias-disable;
+ };
+ pin_rxd {
+ function = "uart0";
+ pins = "gpio27";
+ bias-pull-up;
+ };
+ };
+
+ sdio2_30_pins: sdio2_30_pins {
+ pin_clk {
+ function = "sd2";
+ pins = "gpio30";
+ bias-disable;
+ };
+ pin_cmd {
+ function = "sd2";
+ pins = "gpio31";
+ bias-pull-up;
+ };
+ pins_dat {
+ function = "sd2";
+ pins = "gpio32", "gpio33", "gpio34", "gpio35";
+ bias-pull-up;
+ };
+ };
+ };
+
+ ddc0: i2c@7d508200 {
+ compatible = "brcm,brcmstb-i2c";
+ reg = <0x7d508200 0x58>;
+ interrupt-parent = <&bsc_irq>;
+ interrupts = <1>;
+ clock-frequency = <97500>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ ddc1: i2c@7d508280 {
+ compatible = "brcm,brcmstb-i2c";
+ reg = <0x7d508280 0x58>;
+ interrupt-parent = <&bsc_irq>;
+ interrupts = <2>;
+ clock-frequency = <97500>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ bscd: i2c@7d508300 {
+ compatible = "brcm,brcmstb-i2c";
+ reg = <0x7d508300 0x58>;
+ interrupt-parent = <&bsc_irq>;
+ interrupts = <0>;
+ clock-frequency = <200000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ bsc_irq: intc@7d508380 {
+ compatible = "brcm,bcm7271-l2-intc";
+ reg = <0x7d508380 0x10>;
+ interrupts = <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ main_irq: intc@7d508400 {
+ compatible = "brcm,bcm7271-l2-intc";
+ reg = <0x7d508400 0x10>;
+ interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gio: gpio@7d508500 {
+ compatible = "brcm,brcmstb-gpio";
+ reg = <0x7d508500 0x40>;
+ interrupt-parent = <&main_irq>;
+ interrupts = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ brcm,gpio-bank-widths = <32 22>;
+ brcm,gpio-direct;
+ };
+
+ uarta: serial@7d50c000 {
+ compatible = "brcm,bcm7271-uart";
+ reg = <0x7d50c000 0x20>;
+ reg-names = "uart";
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ interrupts = <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>;
+ skip-init;
+ status = "disabled";
+ };
+
+ uartb: serial@7d50d000 {
+ compatible = "brcm,bcm7271-uart";
+ reg = <0x7d50d000 0x20>;
+ reg-names = "uart";
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ interrupts = <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>;
+ skip-init;
+ status = "disabled";
+ };
+
+ aon_intr: interrupt-controller@7d510600 {
+ compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc";
+ reg = <0x7d510600 0x30>;
+ interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ status = "disabled";
+ };
+
+ pinctrl_aon: pinctrl@7d510700 {
+ compatible = "brcm,bcm2712-aon-pinctrl";
+ reg = <0x7d510700 0x20>;
+
+ i2c3_m4_agpio0_pins: i2c3_m4_agpio0_pins {
+ function = "vc_i2c3";
+ pins = "aon_gpio0", "aon_gpio1";
+ bias-pull-up;
+ };
+
+ bsc_m1_agpio13_pins: bsc_m1_agpio13_pins {
+ function = "bsc_m1";
+ pins = "aon_gpio13", "aon_gpio14";
+ bias-pull-up;
+ };
+
+ bsc_pmu_sgpio4_pins: bsc_pmu_sgpio4_pins {
+ function = "avs_pmu_bsc";
+ pins = "aon_sgpio4", "aon_sgpio5";
+ };
+
+ bsc_m2_sgpio4_pins: bsc_m2_sgpio4_pins {
+ function = "bsc_m2";
+ pins = "aon_sgpio4", "aon_sgpio5";
+ };
+
+ pwm_aon_agpio1_pins: pwm_aon_agpio1_pins {
+ function = "aon_pwm";
+ pins = "aon_gpio1", "aon_gpio2";
+ };
+
+ pwm_aon_agpio4_pins: pwm_aon_agpio4_pins {
+ function = "vc_pwm0";
+ pins = "aon_gpio4", "aon_gpio5";
+ };
+
+ pwm_aon_agpio7_pins: pwm_aon_agpio7_pins {
+ function = "aon_pwm";
+ pins = "aon_gpio7", "aon_gpio9";
+ };
+ };
+
+ intc@7d517000 {
+ compatible = "brcm,bcm7271-l2-intc";
+ reg = <0x7d517000 0x10>;
+ interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ status = "disabled";
+ };
+
+ bscc: i2c@7d517a00 {
+ compatible = "brcm,brcmstb-i2c";
+ reg = <0x7d517a00 0x58>;
+ interrupt-parent = <&bsc_aon_irq>;
+ interrupts = <0>;
+ clock-frequency = <200000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ pwm_aon: pwm@7d517a80 {
+ compatible = "brcm,bcm7038-pwm";
+ reg = <0x7d517a80 0x28>;
+ #pwm-cells = <3>;
+ clocks = <&clk_27MHz>;
+ };
+
+ main_aon_irq: intc@7d517ac0 {
+ compatible = "brcm,bcm7271-l2-intc";
+ reg = <0x7d517ac0 0x10>;
+ interrupts = <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ bsc_aon_irq: intc@7d517b00 {
+ compatible = "brcm,bcm7271-l2-intc";
+ reg = <0x7d517b00 0x10>;
+ interrupts = <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gio_aon: gpio@7d517c00 {
+ compatible = "brcm,brcmstb-gpio";
+ reg = <0x7d517c00 0x40>;
+ interrupt-parent = <&main_aon_irq>;
+ interrupts = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ brcm,gpio-bank-widths = <17 6>;
+ brcm,gpio-direct;
+ };
+
+ avs_monitor: avs-monitor@7d542000 {
+ compatible = "brcm,bcm2711-avs-monitor",
+ "syscon", "simple-mfd";
+ reg = <0x7d542000 0xf00>;
+ status = "okay";
+
+ thermal: thermal {
+ compatible = "brcm,bcm2711-thermal";
+ #thermal-sensor-cells = <0>;
+ };
+ };
+
+ bsc_pmu: i2c@7d544000 {
+ compatible = "brcm,brcmstb-i2c";
+ reg = <0x7d544000 0x58>;
+ interrupt-parent = <&bsc_aon_irq>;
+ interrupts = <1>;
+ clock-frequency = <200000>;
+ status = "disabled";
+ };
+ };
+
+ arm-pmu {
+ compatible = "arm,cortex-a76-pmu";
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
+ IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
+ IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
+ IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
+ IRQ_TYPE_LEVEL_LOW)>;
+ /* This only applies to the ARMv7 stub */
+ arm,cpu-registers-not-fw-configured;
+ };
+
+ cpus: cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit
+
+ /* Source for d/i cache-line-size, cache-sets, cache-size
+ * https://developer.arm.com/documentation/100798/0401
+ * /L1-memory-system/About-the-L1-memory-system?lang=en
+ */
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a76";
+ reg = <0x000>;
+ enable-method = "psci";
+ d-cache-size = <0x10000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set
+ i-cache-size = <0x10000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set
+ next-level-cache = <&l2_cache_l0>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a76";
+ reg = <0x100>;
+ enable-method = "psci";
+ d-cache-size = <0x10000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set
+ i-cache-size = <0x10000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set
+ next-level-cache = <&l2_cache_l1>;
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a76";
+ reg = <0x200>;
+ enable-method = "psci";
+ d-cache-size = <0x10000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set
+ i-cache-size = <0x10000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set
+ next-level-cache = <&l2_cache_l2>;
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a76";
+ reg = <0x300>;
+ enable-method = "psci";
+ d-cache-size = <0x10000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set
+ i-cache-size = <0x10000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set
+ next-level-cache = <&l2_cache_l3>;
+ };
+
+ /* Source for cache-line-size and cache-sets:
+ * https://developer.arm.com/documentation/100798/0401
+ * /L2-memory-system/About-the-L2-memory-system?lang=en
+ * and for cache-size:
+ * https://www.raspberrypi.com/documentation/computers
+ * /processors.html#bcm2712
+ */
+ l2_cache_l0: l2-cache-l0 {
+ compatible = "cache";
+ cache-size = <0x80000>;
+ cache-line-size = <128>;
+ cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_l1: l2-cache-l1 {
+ compatible = "cache";
+ cache-size = <0x80000>;
+ cache-line-size = <128>;
+ cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_l2: l2-cache-l2 {
+ compatible = "cache";
+ cache-size = <0x80000>;
+ cache-line-size = <128>;
+ cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ l2_cache_l3: l2-cache-l3 {
+ compatible = "cache";
+ cache-size = <0x80000>;
+ cache-line-size = <128>;
+ cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set
+ cache-level = <2>;
+ cache-unified;
+ next-level-cache = <&l3_cache>;
+ };
+
+ /* Source for cache-line-size and cache-sets:
+ * https://developer.arm.com/documentation/100453/0401/L3-cache?lang=en
+ * Source for cache-size:
+ * https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712
+ */
+ l3_cache: l3-cache {
+ compatible = "cache";
+ cache-size = <0x200000>;
+ cache-line-size = <64>;
+ cache-sets = <2048>; // 2MiB(size)/64(line-size)=32768ways/16-way set
+ cache-level = <3>;
+ };
+ };
+
+ psci {
+ method = "smc";
+ compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+ cpu_on = <0xc4000003>;
+ cpu_suspend = <0xc4000001>;
+ cpu_off = <0x84000002>;
+ };
+
+ axi: axi {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ ranges = <0x00 0x00000000 0x00 0x00000000 0x10 0x00000000>,
+ <0x10 0x00000000 0x10 0x00000000 0x01 0x00000000>,
+ <0x14 0x00000000 0x14 0x00000000 0x04 0x00000000>,
+ <0x18 0x00000000 0x18 0x00000000 0x04 0x00000000>,
+ <0x1c 0x00000000 0x1c 0x00000000 0x04 0x00000000>;
+
+ dma-ranges = <0x00 0x00000000 0x00 0x00000000 0x10 0x00000000>,
+ <0x10 0x00000000 0x10 0x00000000 0x01 0x00000000>,
+ <0x14 0x00000000 0x14 0x00000000 0x04 0x00000000>,
+ <0x18 0x00000000 0x18 0x00000000 0x04 0x00000000>,
+ <0x1c 0x00000000 0x1c 0x00000000 0x04 0x00000000>;
+
+ sdio1: mmc@fff000 {
+ compatible = "brcm,bcm2712-sdhci";
+ reg = <0x10 0x00fff000 0x0 0x260>,
+ <0x10 0x00fff400 0x0 0x200>,
+ <0x10 0x015040b0 0x0 0x4>, // Bus isolation control
+ <0x10 0x015200f0 0x0 0x24>; // LCPLL control misc0-8
+ reg-names = "host", "cfg", "busisol", "lcpll";
+ interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_emmc2>;
+ sdhci-caps-mask = <0x0000C000 0x0>;
+ sdhci-caps = <0x0 0x0>;
+ mmc-ddr-3_3v;
+ clock-names = "sw_sdio";
+ };
+
+ sdio2: mmc@1100000 {
+ compatible = "brcm,bcm2712-sdhci";
+ reg = <0x10 0x01100000 0x0 0x260>,
+ <0x10 0x01100400 0x0 0x200>;
+ reg-names = "host", "cfg";
+ interrupts = <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_emmc2>;
+ sdhci-caps-mask = <0x0000C000 0x0>;
+ sdhci-caps = <0x0 0x0>;
+ supports-cqe;
+ mmc-ddr-3_3v;
+ status = "disabled";
+ };
+
+ bcm_reset: reset-controller@1504318 {
+ compatible = "brcm,brcmstb-reset";
+ reg = <0x10 0x01504318 0x0 0x30>;
+ #reset-cells = <1>;
+ };
+
+ gicv2: interrupt-controller@7fff9000 {
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ compatible = "arm,gic-400";
+ reg = <0x10 0x7fff9000 0x0 0x1000>,
+ <0x10 0x7fffa000 0x0 0x2000>,
+ <0x10 0x7fffc000 0x0 0x2000>,
+ <0x10 0x7fffe000 0x0 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) |
+ IRQ_TYPE_LEVEL_HIGH)>;
+ };
+ };
+
+ clocks {
+ /* The oscillator is the root of the clock tree. */
+ clk_osc: clk-osc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-output-names = "osc";
+ clock-frequency = <54000000>;
+ };
+
+ clk_vpu: clk_vpu {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <750000000>;
+ clock-output-names = "vpu-clock";
+ };
+
+ clk_uart: clk_uart {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <9216000>;
+ clock-output-names = "uart-clock";
+ };
+
+ clk_emmc2: clk_emmc2 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <200000000>;
+ clock-output-names = "emmc2-clock";
+ };
+ };
+};
--
2.35.3
Broadcom BCM2712 SoC has an SDHCI card controller using the SDIO CFG
register block present on other STB chips. Add support for BCM2712
SD capabilities of this chipset.
The silicon is SD Express capable but this driver port does not currently
include that feature yet.
Based on downstream driver by raspberry foundation maintained kernel.
Signed-off-by: Andrea della Porta <[email protected]>
---
drivers/mmc/host/sdhci-brcmstb.c | 130 +++++++++++++++++++++++++++++++
1 file changed, 130 insertions(+)
diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index 9053526fa212..907a4947abe5 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -12,6 +12,8 @@
#include <linux/of.h>
#include <linux/bitops.h>
#include <linux/delay.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
#include "sdhci-cqhci.h"
#include "sdhci-pltfm.h"
@@ -30,15 +32,31 @@
#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
+#define SDIO_CFG_CTRL 0x0
+#define SDIO_CFG_CTRL_SDCD_N_TEST_EN BIT(31)
+#define SDIO_CFG_CTRL_SDCD_N_TEST_LEV BIT(30)
+
+#define SDIO_CFG_SD_PIN_SEL 0x44
+#define SDIO_CFG_SD_PIN_SEL_MASK 0x3
+#define SDIO_CFG_SD_PIN_SEL_SD BIT(1)
+#define SDIO_CFG_SD_PIN_SEL_MMC BIT(0)
+
+#define SDIO_CFG_MAX_50MHZ_MODE 0x1ac
+#define SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE BIT(31)
+#define SDIO_CFG_MAX_50MHZ_MODE_ENABLE BIT(0)
+
struct sdhci_brcmstb_priv {
void __iomem *cfg_regs;
unsigned int flags;
struct clk *base_clk;
u32 base_freq_hz;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_default;
};
struct brcmstb_match_priv {
void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
+ void (*cfginit)(struct sdhci_host *host);
struct sdhci_ops *ops;
const unsigned int flags;
};
@@ -124,6 +142,42 @@ static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios)
writel(reg, host->ioaddr + SDHCI_VENDOR);
}
+static void sdhci_bcm2712_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ u16 clk;
+ u32 reg;
+ bool is_emmc_rate = false;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
+
+ host->mmc->actual_clock = 0;
+
+ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+ switch (host->mmc->ios.timing) {
+ case MMC_TIMING_MMC_HS400:
+ case MMC_TIMING_MMC_HS200:
+ case MMC_TIMING_MMC_DDR52:
+ case MMC_TIMING_MMC_HS:
+ is_emmc_rate = true;
+ break;
+ }
+
+ reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
+ reg &= ~SDIO_CFG_SD_PIN_SEL_MASK;
+ if (is_emmc_rate)
+ reg |= SDIO_CFG_SD_PIN_SEL_MMC;
+ else
+ reg |= SDIO_CFG_SD_PIN_SEL_SD;
+ writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
+
+ if (clock == 0)
+ return;
+
+ clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
+ sdhci_enable_clk(host, clk);
+}
+
static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock)
{
u16 clk;
@@ -139,6 +193,17 @@ static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock)
sdhci_enable_clk(host, clk);
}
+static void sdhci_brcmstb_set_power(struct sdhci_host *host, unsigned char mode,
+ unsigned short vdd)
+{
+ if (!IS_ERR(host->mmc->supply.vmmc)) {
+ struct mmc_host *mmc = host->mmc;
+
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
+ }
+ sdhci_set_power_noreg(host, mode, vdd);
+}
+
static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host,
unsigned int timing)
{
@@ -168,6 +233,36 @@ static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host,
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
}
+static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
+ u32 uhs_mask = (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104);
+ u32 hsemmc_mask = (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS200_1_2V_SDR |
+ MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V);
+ u32 reg;
+
+ /*
+ * If we support a speed that requires tuning,
+ * then select the delay line PHY as the clock source.
+ */
+ if ((host->mmc->caps & uhs_mask) || (host->mmc->caps2 & hsemmc_mask)) {
+ reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
+ reg &= ~SDIO_CFG_MAX_50MHZ_MODE_ENABLE;
+ reg |= SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE;
+ writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
+ }
+
+ if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
+ (host->mmc->caps & MMC_CAP_NEEDS_POLL)) {
+ /* Force presence */
+ reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
+ reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV;
+ reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN;
+ writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
+ }
+}
+
static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc)
{
sdhci_dumpregs(mmc_priv(mmc));
@@ -200,6 +295,14 @@ static struct sdhci_ops sdhci_brcmstb_ops = {
.set_uhs_signaling = sdhci_set_uhs_signaling,
};
+static struct sdhci_ops sdhci_brcmstb_ops_2712 = {
+ .set_clock = sdhci_bcm2712_set_clock,
+ .set_power = sdhci_brcmstb_set_power,
+ .set_bus_width = sdhci_set_bus_width,
+ .reset = sdhci_reset,
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
.set_clock = sdhci_brcmstb_set_clock,
.set_bus_width = sdhci_set_bus_width,
@@ -237,7 +340,13 @@ static struct brcmstb_match_priv match_priv_74165b0 = {
.ops = &sdhci_brcmstb_ops_74165b0,
};
+static const struct brcmstb_match_priv match_priv_2712 = {
+ .cfginit = sdhci_brcmstb_cfginit_2712,
+ .ops = &sdhci_brcmstb_ops_2712,
+};
+
static const struct of_device_id __maybe_unused sdhci_brcm_of_match[] = {
+ { .compatible = "brcm,bcm2712-sdhci", .data = &match_priv_2712 },
{ .compatible = "brcm,bcm7425-sdhci", .data = &match_priv_7425 },
{ .compatible = "brcm,bcm7445-sdhci", .data = &match_priv_7445 },
{ .compatible = "brcm,bcm7216-sdhci", .data = &match_priv_7216 },
@@ -314,11 +423,16 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
struct sdhci_brcmstb_priv *priv;
u32 actual_clock_mhz;
struct sdhci_host *host;
+ bool no_pinctrl = false;
struct clk *clk;
struct clk *base_clk = NULL;
int res;
match = of_match_node(sdhci_brcm_of_match, pdev->dev.of_node);
+ if (!match) {
+ dev_err(&pdev->dev, "fail to get matching of_match struct\n");
+ return -EINVAL;
+ }
match_priv = match->data;
dev_dbg(&pdev->dev, "Probe found match for %s\n", match->compatible);
@@ -354,6 +468,19 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
if (res)
goto err;
+ priv->pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR(priv->pinctrl)) {
+ no_pinctrl = true;
+ }
+ priv->pins_default = pinctrl_lookup_state(priv->pinctrl, "default");
+ if (IS_ERR(priv->pins_default)) {
+ dev_dbg(&pdev->dev, "No pinctrl default state\n");
+ no_pinctrl = true;
+ }
+
+ if (no_pinctrl )
+ priv->pinctrl = NULL;
+
/*
* Automatic clock gating does not work for SD cards that may
* voltage switch so only enable it for non-removable devices.
@@ -370,6 +497,9 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
(host->mmc->caps2 & MMC_CAP2_HS400_ES))
host->mmc_host_ops.hs400_enhanced_strobe = match_priv->hs400es;
+ if(match_priv->cfginit)
+ match_priv->cfginit(host);
+
/*
* Supply the existing CAPS, but clear the UHS modes. This
* will allow these modes to be specified by device tree
--
2.35.3
Broadcom BCM2712 SDHCI controller is SD Express capable. Add support
for sde capability where the implementation is based on downstream driver,
diverging from it in the way that init_sd_express callback is invoked:
in downstream the sdhci_ops structure has been augmented with a new
function ptr 'init_sd_express' that just propagate the call to the
driver specific callback so that the callstack from a structure
standpoint is mmc_host_ops -> sdhci_ops. The drawback here is in the
added level of indirection (the newly added init_sd_express is
redundant) and the sdhci_ops structure declaration has to be changed.
To overcome this the presented approach consist in patching the mmc_host_ops
init_sd_express callback to point directly to the custom function defined in
this driver (see struct brcmstb_match_priv).
Signed-off-by: Andrea della Porta <[email protected]>
---
drivers/mmc/host/Kconfig | 1 +
drivers/mmc/host/sdhci-brcmstb.c | 147 ++++++++++++++++++++++++++++++-
2 files changed, 147 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index aebc587f77a7..343ccac1a4e4 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -1018,6 +1018,7 @@ config MMC_SDHCI_BRCMSTB
depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
depends on MMC_SDHCI_PLTFM
select MMC_CQHCI
+ select OF_DYNAMIC
default ARCH_BRCMSTB || BMIPS_GENERIC
help
This selects support for the SDIO/SD/MMC Host Controller on
diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index 907a4947abe5..56fb34a75ec2 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -29,6 +29,7 @@
#define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0)
#define BRCMSTB_PRIV_FLAGS_GATE_CLOCK BIT(1)
+#define BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS BIT(2)
#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
@@ -50,13 +51,19 @@ struct sdhci_brcmstb_priv {
unsigned int flags;
struct clk *base_clk;
u32 base_freq_hz;
+ struct regulator *sde_1v8;
+ struct device_node *sde_pcie;
+ void *__iomem sde_ioaddr;
+ void *__iomem sde_ioaddr2;
struct pinctrl *pinctrl;
struct pinctrl_state *pins_default;
+ struct pinctrl_state *pins_sdex;
};
struct brcmstb_match_priv {
void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
void (*cfginit)(struct sdhci_host *host);
+ int (*init_sd_express)(struct mmc_host *mmc, struct mmc_ios *ios);
struct sdhci_ops *ops;
const unsigned int flags;
};
@@ -263,6 +270,105 @@ static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
}
}
+static int bcm2712_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
+ struct device *dev = host->mmc->parent;
+ u32 ctrl_val;
+ u32 present_state;
+ int ret;
+
+ if (!brcmstb_priv->sde_ioaddr || !brcmstb_priv->sde_ioaddr2)
+ return -EINVAL;
+
+ if (!brcmstb_priv->pinctrl)
+ return -EINVAL;
+
+ /* Turn off the SD clock first */
+ sdhci_set_clock(host, 0);
+
+ /* Disable SD DAT0-3 pulls */
+ pinctrl_select_state(brcmstb_priv->pinctrl, brcmstb_priv->pins_sdex);
+
+ ctrl_val = readl(brcmstb_priv->sde_ioaddr);
+ dev_dbg(dev, "ctrl_val 1 %08x\n", ctrl_val);
+
+ /* Tri-state the SD pins */
+ ctrl_val |= 0x1ff8;
+ writel(ctrl_val, brcmstb_priv->sde_ioaddr);
+ dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr));
+ /* Let voltages settle */
+ udelay(100);
+
+ /* Enable the PCIe sideband pins */
+ ctrl_val &= ~0x6000;
+ writel(ctrl_val, brcmstb_priv->sde_ioaddr);
+ dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr));
+ /* Let voltages settle */
+ udelay(100);
+
+ /* Turn on the 1v8 VDD2 regulator */
+ ret = regulator_enable(brcmstb_priv->sde_1v8);
+ if (ret)
+ return ret;
+
+ /* Wait for Tpvcrl */
+ msleep(1);
+
+ /* Sample DAT2 (CLKREQ#) - if low, card is in PCIe mode */
+ present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
+ present_state = (present_state & SDHCI_DATA_LVL_MASK) >> SDHCI_DATA_LVL_SHIFT;
+ dev_dbg(dev, "state = 0x%08x\n", present_state);
+
+ if (present_state & BIT(2)) {
+ dev_err(dev, "DAT2 still high, abandoning SDex switch\n");
+ return -ENODEV;
+ }
+
+ /* Turn on the LCPLL PTEST mux */
+ ctrl_val = readl(brcmstb_priv->sde_ioaddr2 + 20); // misc5
+ ctrl_val &= ~(0x7 << 7);
+ ctrl_val |= 3 << 7;
+ writel(ctrl_val, brcmstb_priv->sde_ioaddr2 + 20);
+ dev_dbg(dev, "misc 5->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2 + 20));
+
+ /* PTEST diff driver enable */
+ ctrl_val = readl(brcmstb_priv->sde_ioaddr2);
+ ctrl_val |= BIT(21);
+ writel(ctrl_val, brcmstb_priv->sde_ioaddr2);
+
+ dev_dbg(dev, "misc 0->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2));
+
+ /* Wait for more than the minimum Tpvpgl time */
+ msleep(100);
+
+ if (brcmstb_priv->sde_pcie) {
+ struct of_changeset changeset;
+ static struct property okay_property = {
+ .name = "status",
+ .value = "okay",
+ .length = 5,
+ };
+
+ /* Enable the pcie controller */
+ of_changeset_init(&changeset);
+ ret = of_changeset_update_property(&changeset,
+ brcmstb_priv->sde_pcie,
+ &okay_property);
+ if (ret) {
+ dev_err(dev, "%s: failed to update property - %d\n", __func__,
+ ret);
+ return -ENODEV;
+ }
+ ret = of_changeset_apply(&changeset);
+ }
+
+ dev_dbg(dev, "%s -> %d\n", __func__, ret);
+ return ret;
+}
+
static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc)
{
sdhci_dumpregs(mmc_priv(mmc));
@@ -342,6 +448,7 @@ static struct brcmstb_match_priv match_priv_74165b0 = {
static const struct brcmstb_match_priv match_priv_2712 = {
.cfginit = sdhci_brcmstb_cfginit_2712,
+ .init_sd_express = bcm2712_init_sd_express,
.ops = &sdhci_brcmstb_ops_2712,
};
@@ -423,6 +530,7 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
struct sdhci_brcmstb_priv *priv;
u32 actual_clock_mhz;
struct sdhci_host *host;
+ struct resource *iomem;
bool no_pinctrl = false;
struct clk *clk;
struct clk *base_clk = NULL;
@@ -456,6 +564,11 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
match_priv->ops->irq = sdhci_brcmstb_cqhci_irq;
}
+ priv->sde_pcie = of_parse_phandle(pdev->dev.of_node,
+ "sde-pcie", 0);
+ if (priv->sde_pcie)
+ priv->flags |= BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS;
+
/* Map in the non-standard CFG registers */
priv->cfg_regs = devm_platform_get_and_ioremap_resource(pdev, 1, NULL);
if (IS_ERR(priv->cfg_regs)) {
@@ -468,6 +581,24 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
if (res)
goto err;
+ priv->sde_1v8 = devm_regulator_get_optional(&pdev->dev, "sde-1v8");
+ if (IS_ERR(priv->sde_1v8))
+ priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS;
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ if (iomem) {
+ priv->sde_ioaddr = devm_ioremap_resource(&pdev->dev, iomem);
+ if (IS_ERR(priv->sde_ioaddr))
+ priv->sde_ioaddr = NULL;
+ }
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+ if (iomem) {
+ priv->sde_ioaddr2 = devm_ioremap_resource(&pdev->dev, iomem);
+ if (IS_ERR(priv->sde_ioaddr2))
+ priv->sde_ioaddr = NULL;
+ }
+
priv->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(priv->pinctrl)) {
no_pinctrl = true;
@@ -478,8 +609,16 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
no_pinctrl = true;
}
- if (no_pinctrl )
+ priv->pins_sdex = pinctrl_lookup_state(priv->pinctrl, "sd-express");
+ if (IS_ERR(priv->pins_sdex)) {
+ dev_dbg(&pdev->dev, "No pinctrl sd-express state\n");
+ no_pinctrl = true;
+ }
+
+ if (no_pinctrl || !priv->sde_ioaddr || !priv->sde_ioaddr2) {
priv->pinctrl = NULL;
+ priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS;
+ }
/*
* Automatic clock gating does not work for SD cards that may
@@ -497,6 +636,12 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
(host->mmc->caps2 & MMC_CAP2_HS400_ES))
host->mmc_host_ops.hs400_enhanced_strobe = match_priv->hs400es;
+ if (match_priv->init_sd_express &&
+ (priv->flags & BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS)) {
+ host->mmc->caps2 |= MMC_CAP2_SD_EXP;
+ host->mmc_host_ops.init_sd_express = match_priv->init_sd_express;
+ }
+
if(match_priv->cfginit)
match_priv->cfginit(host);
--
2.35.3
Add a pincontrol driver for BCM2712. BCM2712 allows muxing GPIOs
and setting configuration on pads.
Originally-by: Jonathan Bell <[email protected]>
Originally-by: Phil Elwell <[email protected]>
Signed-off-by: Andrea della Porta <[email protected]>
---
drivers/pinctrl/bcm/Kconfig | 9 +
drivers/pinctrl/bcm/Makefile | 1 +
drivers/pinctrl/bcm/pinctrl-bcm2712.c | 1247 +++++++++++++++++++++++++
3 files changed, 1257 insertions(+)
create mode 100644 drivers/pinctrl/bcm/pinctrl-bcm2712.c
diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig
index 35b51ce4298e..62ede44460bc 100644
--- a/drivers/pinctrl/bcm/Kconfig
+++ b/drivers/pinctrl/bcm/Kconfig
@@ -3,6 +3,15 @@
# Broadcom pinctrl drivers
#
+config PINCTRL_BCM2712
+ bool "Broadcom BCM2712 PINCONF driver"
+ depends on OF && (ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST)
+ select PINMUX
+ select PINCONF
+ select GENERIC_PINCONF
+ help
+ Say Y here to enable the Broadcom BCM2712 PINCONF driver.
+
config PINCTRL_BCM281XX
bool "Broadcom BCM281xx pinctrl driver"
depends on OF && (ARCH_BCM_MOBILE || COMPILE_TEST)
diff --git a/drivers/pinctrl/bcm/Makefile b/drivers/pinctrl/bcm/Makefile
index 82b868ec1471..d298e4785829 100644
--- a/drivers/pinctrl/bcm/Makefile
+++ b/drivers/pinctrl/bcm/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
# Broadcom pinctrl support
+obj-$(CONFIG_PINCTRL_BCM2712) += pinctrl-bcm2712.o
obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
obj-$(CONFIG_PINCTRL_BCM4908) += pinctrl-bcm4908.o
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2712.c b/drivers/pinctrl/bcm/pinctrl-bcm2712.c
new file mode 100644
index 000000000000..f9359e9eff14
--- /dev/null
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2712.c
@@ -0,0 +1,1247 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for Broadcom BCM2712 GPIO units (pinctrl only)
+ *
+ * Copyright (C) 2021-3 Raspberry Pi Ltd.
+ * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren
+ *
+ * Based heavily on the BCM2835 GPIO & pinctrl driver, which was inspired by:
+ * pinctrl-nomadik.c, please see original file for copyright information
+ * pinctrl-tegra.c, please see original file for copyright information
+ */
+
+#include <linux/bitmap.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#define MODULE_NAME "pinctrl-bcm2712"
+
+/* Register offsets */
+
+#define BCM2712_PULL_NONE 0
+#define BCM2712_PULL_DOWN 1
+#define BCM2712_PULL_UP 2
+#define BCM2712_PULL_MASK 0x3
+
+#define BCM2712_FSEL_COUNT 9
+#define BCM2712_FSEL_MASK 0xf
+
+#define FUNC(f) \
+ [func_##f] = #f
+#define PIN(i, f1, f2, f3, f4, f5, f6, f7, f8) \
+ [i] = { \
+ .funcs = { \
+ func_##f1, \
+ func_##f2, \
+ func_##f3, \
+ func_##f4, \
+ func_##f5, \
+ func_##f6, \
+ func_##f7, \
+ func_##f8, \
+ }, \
+ }
+
+#define MUX_BIT_VALID 0x8000
+#define REG_BIT_INVALID 0xffff
+
+#define BIT_TO_REG(b) (((b) >> 5) << 2)
+#define BIT_TO_SHIFT(b) ((b) & 0x1f)
+
+#define MUX_BIT(mr, mb) (MUX_BIT_VALID + ((mr)*4)*8 + (mb)*4)
+#define GPIO_REGS(n, mr, mb, pr, pb) \
+ [n] = { MUX_BIT(mr, mb), ((pr)*4)*8 + (pb)*2 }
+
+#define EMMC_REGS(n, pr, pb) \
+ [n] = { 0, ((pr)*4)*8 + (pb)*2 }
+
+#define AGPIO_REGS(n, mr, mb, pr, pb) \
+ [n] = { MUX_BIT(mr, mb), ((pr)*4)*8 + (pb)*2 }
+
+#define SGPIO_REGS(n, mr, mb) \
+ [n+32] = { MUX_BIT(mr, mb), REG_BIT_INVALID }
+
+#define GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
+#define AGPIO_PIN(a) PINCTRL_PIN(a, "aon_gpio" #a)
+#define SGPIO_PIN(a) PINCTRL_PIN(a+32, "aon_sgpio" #a)
+
+struct pin_regs {
+ u16 mux_bit;
+ u16 pad_bit;
+};
+
+struct bcm2712_pinctrl {
+ struct device *dev;
+ void __iomem *base;
+ struct pinctrl_dev *pctl_dev;
+ struct pinctrl_desc pctl_desc;
+ const struct pin_regs *pin_regs;
+ const struct bcm2712_pin_funcs *pin_funcs;
+ const char *const *gpio_groups;
+ struct pinctrl_gpio_range gpio_range;
+ spinlock_t lock;
+};
+
+struct bcm_plat_data {
+ const struct pinctrl_desc *pctl_desc;
+ const struct pinctrl_gpio_range *gpio_range;
+ const struct pin_regs *pin_regs;
+ const struct bcm2712_pin_funcs *pin_funcs;
+};
+
+struct bcm2712_pin_funcs {
+ u8 funcs[BCM2712_FSEL_COUNT - 1];
+};
+
+enum bcm2712_funcs {
+ func_gpio,
+ func_alt1,
+ func_alt2,
+ func_alt3,
+ func_alt4,
+ func_alt5,
+ func_alt6,
+ func_alt7,
+ func_alt8,
+ func_aon_cpu_standbyb,
+ func_aon_fp_4sec_resetb,
+ func_aon_gpclk,
+ func_aon_pwm,
+ func_arm_jtag,
+ func_aud_fs_clk0,
+ func_avs_pmu_bsc,
+ func_bsc_m0,
+ func_bsc_m1,
+ func_bsc_m2,
+ func_bsc_m3,
+ func_clk_observe,
+ func_ctl_hdmi_5v,
+ func_enet0,
+ func_enet0_mii,
+ func_enet0_rgmii,
+ func_ext_sc_clk,
+ func_fl0,
+ func_fl1,
+ func_gpclk0,
+ func_gpclk1,
+ func_gpclk2,
+ func_hdmi_tx0_auto_i2c,
+ func_hdmi_tx0_bsc,
+ func_hdmi_tx1_auto_i2c,
+ func_hdmi_tx1_bsc,
+ func_i2s_in,
+ func_i2s_out,
+ func_ir_in,
+ func_mtsif,
+ func_mtsif_alt,
+ func_mtsif_alt1,
+ func_pdm,
+ func_pkt,
+ func_pm_led_out,
+ func_sc0,
+ func_sd0,
+ func_sd2,
+ func_sd_card_a,
+ func_sd_card_b,
+ func_sd_card_c,
+ func_sd_card_d,
+ func_sd_card_e,
+ func_sd_card_f,
+ func_sd_card_g,
+ func_spdif_out,
+ func_spi_m,
+ func_spi_s,
+ func_sr_edm_sense,
+ func_te0,
+ func_te1,
+ func_tsio,
+ func_uart0,
+ func_uart1,
+ func_uart2,
+ func_usb_pwr,
+ func_usb_vbus,
+ func_uui,
+ func_vc_i2c0,
+ func_vc_i2c3,
+ func_vc_i2c4,
+ func_vc_i2c5,
+ func_vc_i2csl,
+ func_vc_pcm,
+ func_vc_pwm0,
+ func_vc_pwm1,
+ func_vc_spi0,
+ func_vc_spi3,
+ func_vc_spi4,
+ func_vc_spi5,
+ func_vc_uart0,
+ func_vc_uart2,
+ func_vc_uart3,
+ func_vc_uart4,
+ func__,
+ func_count = func__
+};
+
+static const struct pin_regs bcm2712_c0_gpio_pin_regs[] = {
+ GPIO_REGS(0, 0, 0, 7, 7),
+ GPIO_REGS(1, 0, 1, 7, 8),
+ GPIO_REGS(2, 0, 2, 7, 9),
+ GPIO_REGS(3, 0, 3, 7, 10),
+ GPIO_REGS(4, 0, 4, 7, 11),
+ GPIO_REGS(5, 0, 5, 7, 12),
+ GPIO_REGS(6, 0, 6, 7, 13),
+ GPIO_REGS(7, 0, 7, 7, 14),
+ GPIO_REGS(8, 1, 0, 8, 0),
+ GPIO_REGS(9, 1, 1, 8, 1),
+ GPIO_REGS(10, 1, 2, 8, 2),
+ GPIO_REGS(11, 1, 3, 8, 3),
+ GPIO_REGS(12, 1, 4, 8, 4),
+ GPIO_REGS(13, 1, 5, 8, 5),
+ GPIO_REGS(14, 1, 6, 8, 6),
+ GPIO_REGS(15, 1, 7, 8, 7),
+ GPIO_REGS(16, 2, 0, 8, 8),
+ GPIO_REGS(17, 2, 1, 8, 9),
+ GPIO_REGS(18, 2, 2, 8, 10),
+ GPIO_REGS(19, 2, 3, 8, 11),
+ GPIO_REGS(20, 2, 4, 8, 12),
+ GPIO_REGS(21, 2, 5, 8, 13),
+ GPIO_REGS(22, 2, 6, 8, 14),
+ GPIO_REGS(23, 2, 7, 9, 0),
+ GPIO_REGS(24, 3, 0, 9, 1),
+ GPIO_REGS(25, 3, 1, 9, 2),
+ GPIO_REGS(26, 3, 2, 9, 3),
+ GPIO_REGS(27, 3, 3, 9, 4),
+ GPIO_REGS(28, 3, 4, 9, 5),
+ GPIO_REGS(29, 3, 5, 9, 6),
+ GPIO_REGS(30, 3, 6, 9, 7),
+ GPIO_REGS(31, 3, 7, 9, 8),
+ GPIO_REGS(32, 4, 0, 9, 9),
+ GPIO_REGS(33, 4, 1, 9, 10),
+ GPIO_REGS(34, 4, 2, 9, 11),
+ GPIO_REGS(35, 4, 3, 9, 12),
+ GPIO_REGS(36, 4, 4, 9, 13),
+ GPIO_REGS(37, 4, 5, 9, 14),
+ GPIO_REGS(38, 4, 6, 10, 0),
+ GPIO_REGS(39, 4, 7, 10, 1),
+ GPIO_REGS(40, 5, 0, 10, 2),
+ GPIO_REGS(41, 5, 1, 10, 3),
+ GPIO_REGS(42, 5, 2, 10, 4),
+ GPIO_REGS(43, 5, 3, 10, 5),
+ GPIO_REGS(44, 5, 4, 10, 6),
+ GPIO_REGS(45, 5, 5, 10, 7),
+ GPIO_REGS(46, 5, 6, 10, 8),
+ GPIO_REGS(47, 5, 7, 10, 9),
+ GPIO_REGS(48, 6, 0, 10, 10),
+ GPIO_REGS(49, 6, 1, 10, 11),
+ GPIO_REGS(50, 6, 2, 10, 12),
+ GPIO_REGS(51, 6, 3, 10, 13),
+ GPIO_REGS(52, 6, 4, 10, 14),
+ GPIO_REGS(53, 6, 5, 11, 0),
+ EMMC_REGS(54, 11, 1), /* EMMC_CMD */
+ EMMC_REGS(55, 11, 2), /* EMMC_DS */
+ EMMC_REGS(56, 11, 3), /* EMMC_CLK */
+ EMMC_REGS(57, 11, 4), /* EMMC_DAT0 */
+ EMMC_REGS(58, 11, 5), /* EMMC_DAT1 */
+ EMMC_REGS(59, 11, 6), /* EMMC_DAT2 */
+ EMMC_REGS(60, 11, 7), /* EMMC_DAT3 */
+ EMMC_REGS(61, 11, 8), /* EMMC_DAT4 */
+ EMMC_REGS(62, 11, 9), /* EMMC_DAT5 */
+ EMMC_REGS(63, 11, 10), /* EMMC_DAT6 */
+ EMMC_REGS(64, 11, 11), /* EMMC_DAT7 */
+};
+
+static struct pin_regs bcm2712_c0_aon_gpio_pin_regs[] = {
+ AGPIO_REGS(0, 3, 0, 6, 10),
+ AGPIO_REGS(1, 3, 1, 6, 11),
+ AGPIO_REGS(2, 3, 2, 6, 12),
+ AGPIO_REGS(3, 3, 3, 6, 13),
+ AGPIO_REGS(4, 3, 4, 6, 14),
+ AGPIO_REGS(5, 3, 5, 7, 0),
+ AGPIO_REGS(6, 3, 6, 7, 1),
+ AGPIO_REGS(7, 3, 7, 7, 2),
+ AGPIO_REGS(8, 4, 0, 7, 3),
+ AGPIO_REGS(9, 4, 1, 7, 4),
+ AGPIO_REGS(10, 4, 2, 7, 5),
+ AGPIO_REGS(11, 4, 3, 7, 6),
+ AGPIO_REGS(12, 4, 4, 7, 7),
+ AGPIO_REGS(13, 4, 5, 7, 8),
+ AGPIO_REGS(14, 4, 6, 7, 9),
+ AGPIO_REGS(15, 4, 7, 7, 10),
+ AGPIO_REGS(16, 5, 0, 7, 11),
+ SGPIO_REGS(0, 0, 0),
+ SGPIO_REGS(1, 0, 1),
+ SGPIO_REGS(2, 0, 2),
+ SGPIO_REGS(3, 0, 3),
+ SGPIO_REGS(4, 1, 0),
+ SGPIO_REGS(5, 2, 0),
+};
+
+static const struct pinctrl_pin_desc bcm2712_c0_gpio_pins[] = {
+ GPIO_PIN(0),
+ GPIO_PIN(1),
+ GPIO_PIN(2),
+ GPIO_PIN(3),
+ GPIO_PIN(4),
+ GPIO_PIN(5),
+ GPIO_PIN(6),
+ GPIO_PIN(7),
+ GPIO_PIN(8),
+ GPIO_PIN(9),
+ GPIO_PIN(10),
+ GPIO_PIN(11),
+ GPIO_PIN(12),
+ GPIO_PIN(13),
+ GPIO_PIN(14),
+ GPIO_PIN(15),
+ GPIO_PIN(16),
+ GPIO_PIN(17),
+ GPIO_PIN(18),
+ GPIO_PIN(19),
+ GPIO_PIN(20),
+ GPIO_PIN(21),
+ GPIO_PIN(22),
+ GPIO_PIN(23),
+ GPIO_PIN(24),
+ GPIO_PIN(25),
+ GPIO_PIN(26),
+ GPIO_PIN(27),
+ GPIO_PIN(28),
+ GPIO_PIN(29),
+ GPIO_PIN(30),
+ GPIO_PIN(31),
+ GPIO_PIN(32),
+ GPIO_PIN(33),
+ GPIO_PIN(34),
+ GPIO_PIN(35),
+ GPIO_PIN(36),
+ GPIO_PIN(37),
+ GPIO_PIN(38),
+ GPIO_PIN(39),
+ GPIO_PIN(40),
+ GPIO_PIN(41),
+ GPIO_PIN(42),
+ GPIO_PIN(43),
+ GPIO_PIN(44),
+ GPIO_PIN(45),
+ GPIO_PIN(46),
+ GPIO_PIN(47),
+ GPIO_PIN(48),
+ GPIO_PIN(49),
+ GPIO_PIN(50),
+ GPIO_PIN(51),
+ GPIO_PIN(52),
+ GPIO_PIN(53),
+ PINCTRL_PIN(54, "emmc_cmd"),
+ PINCTRL_PIN(55, "emmc_ds"),
+ PINCTRL_PIN(56, "emmc_clk"),
+ PINCTRL_PIN(57, "emmc_dat0"),
+ PINCTRL_PIN(58, "emmc_dat1"),
+ PINCTRL_PIN(59, "emmc_dat2"),
+ PINCTRL_PIN(60, "emmc_dat3"),
+ PINCTRL_PIN(61, "emmc_dat4"),
+ PINCTRL_PIN(62, "emmc_dat5"),
+ PINCTRL_PIN(63, "emmc_dat6"),
+ PINCTRL_PIN(64, "emmc_dat7"),
+};
+
+static struct pinctrl_pin_desc bcm2712_c0_aon_gpio_pins[] = {
+ AGPIO_PIN(0),
+ AGPIO_PIN(1),
+ AGPIO_PIN(2),
+ AGPIO_PIN(3),
+ AGPIO_PIN(4),
+ AGPIO_PIN(5),
+ AGPIO_PIN(6),
+ AGPIO_PIN(7),
+ AGPIO_PIN(8),
+ AGPIO_PIN(9),
+ AGPIO_PIN(10),
+ AGPIO_PIN(11),
+ AGPIO_PIN(12),
+ AGPIO_PIN(13),
+ AGPIO_PIN(14),
+ AGPIO_PIN(15),
+ AGPIO_PIN(16),
+ SGPIO_PIN(0),
+ SGPIO_PIN(1),
+ SGPIO_PIN(2),
+ SGPIO_PIN(3),
+ SGPIO_PIN(4),
+ SGPIO_PIN(5),
+};
+
+static const struct pin_regs bcm2712_d0_gpio_pin_regs[] = {
+ GPIO_REGS(1, 0, 0, 4, 5),
+ GPIO_REGS(2, 0, 1, 4, 6),
+ GPIO_REGS(3, 0, 2, 4, 7),
+ GPIO_REGS(4, 0, 3, 4, 8),
+ GPIO_REGS(10, 0, 4, 4, 9),
+ GPIO_REGS(11, 0, 5, 4, 10),
+ GPIO_REGS(12, 0, 6, 4, 11),
+ GPIO_REGS(13, 0, 7, 4, 12),
+ GPIO_REGS(14, 1, 0, 4, 13),
+ GPIO_REGS(15, 1, 1, 4, 14),
+ GPIO_REGS(18, 1, 2, 5, 0),
+ GPIO_REGS(19, 1, 3, 5, 1),
+ GPIO_REGS(20, 1, 4, 5, 2),
+ GPIO_REGS(21, 1, 5, 5, 3),
+ GPIO_REGS(22, 1, 6, 5, 4),
+ GPIO_REGS(23, 1, 7, 5, 5),
+ GPIO_REGS(24, 2, 0, 5, 6),
+ GPIO_REGS(25, 2, 1, 5, 7),
+ GPIO_REGS(26, 2, 2, 5, 8),
+ GPIO_REGS(27, 2, 3, 5, 9),
+ GPIO_REGS(28, 2, 4, 5, 10),
+ GPIO_REGS(29, 2, 5, 5, 11),
+ GPIO_REGS(30, 2, 6, 5, 12),
+ GPIO_REGS(31, 2, 7, 5, 13),
+ GPIO_REGS(32, 3, 0, 5, 14),
+ GPIO_REGS(33, 3, 1, 6, 0),
+ GPIO_REGS(34, 3, 2, 6, 1),
+ GPIO_REGS(35, 3, 3, 6, 2),
+ EMMC_REGS(36, 6, 3), /* EMMC_CMD */
+ EMMC_REGS(37, 6, 4), /* EMMC_DS */
+ EMMC_REGS(38, 6, 5), /* EMMC_CLK */
+ EMMC_REGS(39, 6, 6), /* EMMC_DAT0 */
+ EMMC_REGS(40, 6, 7), /* EMMC_DAT1 */
+ EMMC_REGS(41, 6, 8), /* EMMC_DAT2 */
+ EMMC_REGS(42, 6, 9), /* EMMC_DAT3 */
+ EMMC_REGS(43, 6, 10), /* EMMC_DAT4 */
+ EMMC_REGS(44, 6, 11), /* EMMC_DAT5 */
+ EMMC_REGS(45, 6, 12), /* EMMC_DAT6 */
+ EMMC_REGS(46, 6, 13), /* EMMC_DAT7 */
+};
+
+static struct pin_regs bcm2712_d0_aon_gpio_pin_regs[] = {
+ AGPIO_REGS(0, 3, 0, 5, 9),
+ AGPIO_REGS(1, 3, 1, 5, 10),
+ AGPIO_REGS(2, 3, 2, 5, 11),
+ AGPIO_REGS(3, 3, 3, 5, 12),
+ AGPIO_REGS(4, 3, 4, 5, 13),
+ AGPIO_REGS(5, 3, 5, 5, 14),
+ AGPIO_REGS(6, 3, 6, 6, 0),
+ AGPIO_REGS(8, 3, 7, 6, 1),
+ AGPIO_REGS(9, 4, 0, 6, 2),
+ AGPIO_REGS(12, 4, 1, 6, 3),
+ AGPIO_REGS(13, 4, 2, 6, 4),
+ AGPIO_REGS(14, 4, 3, 6, 5),
+ SGPIO_REGS(0, 0, 0),
+ SGPIO_REGS(1, 0, 1),
+ SGPIO_REGS(2, 0, 2),
+ SGPIO_REGS(3, 0, 3),
+ SGPIO_REGS(4, 1, 0),
+ SGPIO_REGS(5, 2, 0),
+};
+
+static const struct pinctrl_pin_desc bcm2712_d0_gpio_pins[] = {
+ GPIO_PIN(1),
+ GPIO_PIN(2),
+ GPIO_PIN(3),
+ GPIO_PIN(4),
+ GPIO_PIN(10),
+ GPIO_PIN(11),
+ GPIO_PIN(12),
+ GPIO_PIN(13),
+ GPIO_PIN(14),
+ GPIO_PIN(15),
+ GPIO_PIN(18),
+ GPIO_PIN(19),
+ GPIO_PIN(20),
+ GPIO_PIN(21),
+ GPIO_PIN(22),
+ GPIO_PIN(23),
+ GPIO_PIN(24),
+ GPIO_PIN(25),
+ GPIO_PIN(26),
+ GPIO_PIN(27),
+ GPIO_PIN(28),
+ GPIO_PIN(29),
+ GPIO_PIN(30),
+ GPIO_PIN(31),
+ GPIO_PIN(32),
+ GPIO_PIN(33),
+ GPIO_PIN(34),
+ GPIO_PIN(35),
+ PINCTRL_PIN(36, "emmc_cmd"),
+ PINCTRL_PIN(37, "emmc_ds"),
+ PINCTRL_PIN(38, "emmc_clk"),
+ PINCTRL_PIN(39, "emmc_dat0"),
+ PINCTRL_PIN(40, "emmc_dat1"),
+ PINCTRL_PIN(41, "emmc_dat2"),
+ PINCTRL_PIN(42, "emmc_dat3"),
+ PINCTRL_PIN(43, "emmc_dat4"),
+ PINCTRL_PIN(44, "emmc_dat5"),
+ PINCTRL_PIN(45, "emmc_dat6"),
+ PINCTRL_PIN(46, "emmc_dat7"),
+};
+
+static struct pinctrl_pin_desc bcm2712_d0_aon_gpio_pins[] = {
+ AGPIO_PIN(0),
+ AGPIO_PIN(1),
+ AGPIO_PIN(2),
+ AGPIO_PIN(3),
+ AGPIO_PIN(4),
+ AGPIO_PIN(5),
+ AGPIO_PIN(6),
+ AGPIO_PIN(8),
+ AGPIO_PIN(9),
+ AGPIO_PIN(12),
+ AGPIO_PIN(13),
+ AGPIO_PIN(14),
+ SGPIO_PIN(0),
+ SGPIO_PIN(1),
+ SGPIO_PIN(2),
+ SGPIO_PIN(3),
+ SGPIO_PIN(4),
+ SGPIO_PIN(5),
+};
+
+static const char * const bcm2712_func_names[] = {
+ FUNC(gpio),
+ FUNC(alt1),
+ FUNC(alt2),
+ FUNC(alt3),
+ FUNC(alt4),
+ FUNC(alt5),
+ FUNC(alt6),
+ FUNC(alt7),
+ FUNC(alt8),
+ FUNC(aon_cpu_standbyb),
+ FUNC(aon_fp_4sec_resetb),
+ FUNC(aon_gpclk),
+ FUNC(aon_pwm),
+ FUNC(arm_jtag),
+ FUNC(aud_fs_clk0),
+ FUNC(avs_pmu_bsc),
+ FUNC(bsc_m0),
+ FUNC(bsc_m1),
+ FUNC(bsc_m2),
+ FUNC(bsc_m3),
+ FUNC(clk_observe),
+ FUNC(ctl_hdmi_5v),
+ FUNC(enet0),
+ FUNC(enet0_mii),
+ FUNC(enet0_rgmii),
+ FUNC(ext_sc_clk),
+ FUNC(fl0),
+ FUNC(fl1),
+ FUNC(gpclk0),
+ FUNC(gpclk1),
+ FUNC(gpclk2),
+ FUNC(hdmi_tx0_auto_i2c),
+ FUNC(hdmi_tx0_bsc),
+ FUNC(hdmi_tx1_auto_i2c),
+ FUNC(hdmi_tx1_bsc),
+ FUNC(i2s_in),
+ FUNC(i2s_out),
+ FUNC(ir_in),
+ FUNC(mtsif),
+ FUNC(mtsif_alt),
+ FUNC(mtsif_alt1),
+ FUNC(pdm),
+ FUNC(pkt),
+ FUNC(pm_led_out),
+ FUNC(sc0),
+ FUNC(sd0),
+ FUNC(sd2),
+ FUNC(sd_card_a),
+ FUNC(sd_card_b),
+ FUNC(sd_card_c),
+ FUNC(sd_card_d),
+ FUNC(sd_card_e),
+ FUNC(sd_card_f),
+ FUNC(sd_card_g),
+ FUNC(spdif_out),
+ FUNC(spi_m),
+ FUNC(spi_s),
+ FUNC(sr_edm_sense),
+ FUNC(te0),
+ FUNC(te1),
+ FUNC(tsio),
+ FUNC(uart0),
+ FUNC(uart1),
+ FUNC(uart2),
+ FUNC(usb_pwr),
+ FUNC(usb_vbus),
+ FUNC(uui),
+ FUNC(vc_i2c0),
+ FUNC(vc_i2c3),
+ FUNC(vc_i2c4),
+ FUNC(vc_i2c5),
+ FUNC(vc_i2csl),
+ FUNC(vc_pcm),
+ FUNC(vc_pwm0),
+ FUNC(vc_pwm1),
+ FUNC(vc_spi0),
+ FUNC(vc_spi3),
+ FUNC(vc_spi4),
+ FUNC(vc_spi5),
+ FUNC(vc_uart0),
+ FUNC(vc_uart2),
+ FUNC(vc_uart3),
+ FUNC(vc_uart4),
+};
+
+static const struct bcm2712_pin_funcs bcm2712_c0_aon_gpio_pin_funcs[] = {
+ PIN(0, ir_in, vc_spi0, vc_uart3, vc_i2c3, te0, vc_i2c0, _, _),
+ PIN(1, vc_pwm0, vc_spi0, vc_uart3, vc_i2c3, te1, aon_pwm, vc_i2c0, vc_pwm1),
+ PIN(2, vc_pwm0, vc_spi0, vc_uart3, ctl_hdmi_5v, fl0, aon_pwm, ir_in, vc_pwm1),
+ PIN(3, ir_in, vc_spi0, vc_uart3, aon_fp_4sec_resetb, fl1, sd_card_g, aon_gpclk, _),
+ PIN(4, gpclk0, vc_spi0, vc_i2csl, aon_gpclk, pm_led_out, aon_pwm, sd_card_g, vc_pwm0),
+ PIN(5, gpclk1, ir_in, vc_i2csl, clk_observe, aon_pwm, sd_card_g, vc_pwm0, _),
+ PIN(6, uart1, vc_uart4, gpclk2, ctl_hdmi_5v, vc_uart0, vc_spi3, _, _),
+ PIN(7, uart1, vc_uart4, gpclk0, aon_pwm, vc_uart0, vc_spi3, _, _),
+ PIN(8, uart1, vc_uart4, vc_i2csl, ctl_hdmi_5v, vc_uart0, vc_spi3, _, _),
+ PIN(9, uart1, vc_uart4, vc_i2csl, aon_pwm, vc_uart0, vc_spi3, _, _),
+ PIN(10, tsio, ctl_hdmi_5v, sc0, spdif_out, vc_spi5, usb_pwr, aon_gpclk, sd_card_f),
+ PIN(11, tsio, uart0, sc0, aud_fs_clk0, vc_spi5, usb_vbus, vc_uart2, sd_card_f),
+ PIN(12, tsio, uart0, vc_uart0, tsio, vc_spi5, usb_pwr, vc_uart2, sd_card_f),
+ PIN(13, bsc_m1, uart0, vc_uart0, uui, vc_spi5, arm_jtag, vc_uart2, vc_i2c3),
+ PIN(14, bsc_m1, uart0, vc_uart0, uui, vc_spi5, arm_jtag, vc_uart2, vc_i2c3),
+ PIN(15, ir_in, aon_fp_4sec_resetb, vc_uart0, pm_led_out, ctl_hdmi_5v, aon_pwm, aon_gpclk, _),
+ PIN(16, aon_cpu_standbyb, gpclk0, pm_led_out, ctl_hdmi_5v, vc_pwm0, usb_pwr, aud_fs_clk0, _),
+};
+
+static const struct bcm2712_pin_funcs bcm2712_c0_aon_sgpio_pin_funcs[] = {
+ PIN(0, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _),
+ PIN(1, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _),
+ PIN(2, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c4, ctl_hdmi_5v, _, _, _),
+ PIN(3, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c4, _, _, _, _),
+ PIN(4, avs_pmu_bsc, bsc_m2, vc_i2c5, ctl_hdmi_5v, _, _, _, _),
+ PIN(5, avs_pmu_bsc, bsc_m2, vc_i2c5, _, _, _, _, _),
+};
+
+static const struct bcm2712_pin_funcs bcm2712_c0_gpio_pin_funcs[] = {
+ PIN(0, bsc_m3, vc_i2c0, gpclk0, enet0, vc_pwm1, vc_spi0, ir_in, _),
+ PIN(1, bsc_m3, vc_i2c0, gpclk1, enet0, vc_pwm1, sr_edm_sense, vc_spi0, vc_uart3),
+ PIN(2, pdm, i2s_in, gpclk2, vc_spi4, pkt, vc_spi0, vc_uart3, _),
+ PIN(3, pdm, i2s_in, vc_spi4, pkt, vc_spi0, vc_uart3, _, _),
+ PIN(4, pdm, i2s_in, arm_jtag, vc_spi4, pkt, vc_spi0, vc_uart3, _),
+ PIN(5, pdm, vc_i2c3, arm_jtag, sd_card_e, vc_spi4, pkt, vc_pcm, vc_i2c5),
+ PIN(6, pdm, vc_i2c3, arm_jtag, sd_card_e, vc_spi4, pkt, vc_pcm, vc_i2c5),
+ PIN(7, i2s_out, spdif_out, arm_jtag, sd_card_e, vc_i2c3, enet0_rgmii, vc_pcm, vc_spi4),
+ PIN(8, i2s_out, aud_fs_clk0, arm_jtag, sd_card_e, vc_i2c3, enet0_mii, vc_pcm, vc_spi4),
+ PIN(9, i2s_out, aud_fs_clk0, arm_jtag, sd_card_e, enet0_mii, sd_card_c, vc_spi4, _),
+ PIN(10, bsc_m3, mtsif_alt1, i2s_in, i2s_out, vc_spi5, enet0_mii, sd_card_c, vc_spi4),
+ PIN(11, bsc_m3, mtsif_alt1, i2s_in, i2s_out, vc_spi5, enet0_mii, sd_card_c, vc_spi4),
+ PIN(12, spi_s, mtsif_alt1, i2s_in, i2s_out, vc_spi5, vc_i2csl, sd0, sd_card_d),
+ PIN(13, spi_s, mtsif_alt1, i2s_out, usb_vbus, vc_spi5, vc_i2csl, sd0, sd_card_d),
+ PIN(14, spi_s, vc_i2csl, enet0_rgmii, arm_jtag, vc_spi5, vc_pwm0, vc_i2c4, sd_card_d),
+ PIN(15, spi_s, vc_i2csl, vc_spi3, arm_jtag, vc_pwm0, vc_i2c4, gpclk0, _),
+ PIN(16, sd_card_b, i2s_out, vc_spi3, i2s_in, sd0, enet0_rgmii, gpclk1, _),
+ PIN(17, sd_card_b, i2s_out, vc_spi3, i2s_in, ext_sc_clk, sd0, enet0_rgmii, gpclk2),
+ PIN(18, sd_card_b, i2s_out, vc_spi3, i2s_in, sd0, enet0_rgmii, vc_pwm1, _),
+ PIN(19, sd_card_b, usb_pwr, vc_spi3, pkt, spdif_out, sd0, ir_in, vc_pwm1),
+ PIN(20, sd_card_b, uui, vc_uart0, arm_jtag, uart2, usb_pwr, vc_pcm, vc_uart4),
+ PIN(21, usb_pwr, uui, vc_uart0, arm_jtag, uart2, sd_card_b, vc_pcm, vc_uart4),
+ PIN(22, usb_pwr, enet0, vc_uart0, mtsif, uart2, usb_vbus, vc_pcm, vc_i2c5),
+ PIN(23, usb_vbus, enet0, vc_uart0, mtsif, uart2, i2s_out, vc_pcm, vc_i2c5),
+ PIN(24, mtsif, pkt, uart0, enet0_rgmii, enet0_rgmii, vc_i2c4, vc_uart3, _),
+ PIN(25, mtsif, pkt, sc0, uart0, enet0_rgmii, enet0_rgmii, vc_i2c4, vc_uart3),
+ PIN(26, mtsif, pkt, sc0, uart0, enet0_rgmii, vc_uart4, vc_spi5, _),
+ PIN(27, mtsif, pkt, sc0, uart0, enet0_rgmii, vc_uart4, vc_spi5, _),
+ PIN(28, mtsif, pkt, sc0, enet0_rgmii, vc_uart4, vc_spi5, _, _),
+ PIN(29, mtsif, pkt, sc0, enet0_rgmii, vc_uart4, vc_spi5, _, _),
+ PIN(30, mtsif, pkt, sc0, sd2, enet0_rgmii, gpclk0, vc_pwm0, _),
+ PIN(31, mtsif, pkt, sc0, sd2, enet0_rgmii, vc_spi3, vc_pwm0, _),
+ PIN(32, mtsif, pkt, sc0, sd2, enet0_rgmii, vc_spi3, vc_uart3, _),
+ PIN(33, mtsif, pkt, sd2, enet0_rgmii, vc_spi3, vc_uart3, _, _),
+ PIN(34, mtsif, pkt, ext_sc_clk, sd2, enet0_rgmii, vc_spi3, vc_i2c5, _),
+ PIN(35, mtsif, pkt, sd2, enet0_rgmii, vc_spi3, vc_i2c5, _, _),
+ PIN(36, sd0, mtsif, sc0, i2s_in, vc_uart3, vc_uart2, _, _),
+ PIN(37, sd0, mtsif, sc0, vc_spi0, i2s_in, vc_uart3, vc_uart2, _),
+ PIN(38, sd0, mtsif_alt, sc0, vc_spi0, i2s_in, vc_uart3, vc_uart2, _),
+ PIN(39, sd0, mtsif_alt, sc0, vc_spi0, vc_uart3, vc_uart2, _, _),
+ PIN(40, sd0, mtsif_alt, sc0, vc_spi0, bsc_m3, _, _, _),
+ PIN(41, sd0, mtsif_alt, sc0, vc_spi0, bsc_m3, _, _, _),
+ PIN(42, vc_spi0, mtsif_alt, vc_i2c0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m),
+ PIN(43, vc_spi0, mtsif_alt, vc_i2c0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m),
+ PIN(44, vc_spi0, mtsif_alt, enet0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m),
+ PIN(45, vc_spi0, mtsif_alt, enet0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m),
+ PIN(46, vc_spi0, mtsif_alt, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m, _),
+ PIN(47, enet0, mtsif_alt, i2s_out, mtsif_alt1, arm_jtag, _, _, _),
+ PIN(48, sc0, usb_pwr, spdif_out, mtsif, _, _, _, _),
+ PIN(49, sc0, usb_pwr, aud_fs_clk0, mtsif, _, _, _, _),
+ PIN(50, sc0, usb_vbus, sc0, _, _, _, _, _),
+ PIN(51, sc0, enet0, sc0, sr_edm_sense, _, _, _, _),
+ PIN(52, sc0, enet0, vc_pwm1, _, _, _, _, _),
+ PIN(53, sc0, enet0_rgmii, ext_sc_clk, _, _, _, _, _),
+};
+
+static const struct bcm2712_pin_funcs bcm2712_d0_aon_gpio_pin_funcs[] = {
+ PIN(0, ir_in, vc_spi0, vc_uart0, vc_i2c3, uart0, vc_i2c0, _, _),
+ PIN(1, vc_pwm0, vc_spi0, vc_uart0, vc_i2c3, uart0, aon_pwm, vc_i2c0, vc_pwm1),
+ PIN(2, vc_pwm0, vc_spi0, vc_uart0, ctl_hdmi_5v, uart0, aon_pwm, ir_in, vc_pwm1),
+ PIN(3, ir_in, vc_spi0, vc_uart0, uart0, sd_card_g, aon_gpclk, _, _),
+ PIN(4, gpclk0, vc_spi0, pm_led_out, aon_pwm, sd_card_g, vc_pwm0, _, _),
+ PIN(5, gpclk1, ir_in, aon_pwm, sd_card_g, vc_pwm0, _, _, _),
+ PIN(6, uart1, vc_uart2, ctl_hdmi_5v, gpclk2, vc_spi3, _, _, _),
+ PIN(7, _, _, _, _, _, _, _, _),
+ PIN(8, uart1, vc_uart2, ctl_hdmi_5v, vc_spi0, vc_spi3, _, _, _),
+ PIN(9, uart1, vc_uart2, vc_uart0, aon_pwm, vc_spi0, vc_uart2, vc_spi3, _),
+ PIN(10, _, _, _, _, _, _, _, _),
+ PIN(11, _, _, _, _, _, _, _, _),
+ PIN(12, uart1, vc_uart2, vc_uart0, vc_spi0, usb_pwr, vc_uart2, vc_spi3, _),
+ PIN(13, bsc_m1, vc_uart0, uui, vc_spi0, arm_jtag, vc_uart2, vc_i2c3, _),
+ PIN(14, bsc_m1, aon_gpclk, vc_uart0, uui, vc_spi0, arm_jtag, vc_uart2, vc_i2c3),
+};
+
+static const struct bcm2712_pin_funcs bcm2712_d0_aon_sgpio_pin_funcs[] = {
+ PIN(0, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _),
+ PIN(1, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _),
+ PIN(2, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c0, ctl_hdmi_5v, _, _, _),
+ PIN(3, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c0, _, _, _, _),
+ PIN(4, avs_pmu_bsc, bsc_m2, vc_i2c3, ctl_hdmi_5v, _, _, _, _),
+ PIN(5, avs_pmu_bsc, bsc_m2, vc_i2c3, _, _, _, _, _),
+};
+
+static const struct bcm2712_pin_funcs bcm2712_d0_gpio_pin_funcs[] = {
+ PIN(1, vc_i2c0, usb_pwr, gpclk0, sd_card_e, vc_spi3, sr_edm_sense, vc_spi0, vc_uart0),
+ PIN(2, vc_i2c0, usb_pwr, gpclk1, sd_card_e, vc_spi3, clk_observe, vc_spi0, vc_uart0),
+ PIN(3, vc_i2c3, usb_vbus, gpclk2, sd_card_e, vc_spi3, vc_spi0, vc_uart0, _),
+ PIN(4, vc_i2c3, vc_pwm1, vc_spi3, sd_card_e, vc_spi3, vc_spi0, vc_uart0, _),
+ PIN(10, bsc_m3, vc_pwm1, vc_spi3, sd_card_e, vc_spi3, gpclk0, _, _),
+ PIN(11, bsc_m3, vc_spi3, clk_observe, sd_card_c, gpclk1, _, _, _),
+ PIN(12, spi_s, vc_spi3, sd_card_c, sd_card_d, _, _, _, _),
+ PIN(13, spi_s, vc_spi3, sd_card_c, sd_card_d, _, _, _, _),
+ PIN(14, spi_s, uui, arm_jtag, vc_pwm0, vc_i2c0, sd_card_d, _, _),
+ PIN(15, spi_s, uui, arm_jtag, vc_pwm0, vc_i2c0, gpclk0, _, _),
+ PIN(18, sd_card_f, vc_pwm1, _, _, _, _, _, _),
+ PIN(19, sd_card_f, usb_pwr, vc_pwm1, _, _, _, _, _),
+ PIN(20, vc_i2c3, uui, vc_uart0, arm_jtag, vc_uart2, _, _, _),
+ PIN(21, vc_i2c3, uui, vc_uart0, arm_jtag, vc_uart2, _, _, _),
+ PIN(22, sd_card_f, vc_uart0, vc_i2c3, _, _, _, _, _),
+ PIN(23, vc_uart0, vc_i2c3, _, _, _, _, _, _),
+ PIN(24, sd_card_b, vc_spi0, arm_jtag, uart0, usb_pwr, vc_uart2, vc_uart0, _),
+ PIN(25, sd_card_b, vc_spi0, arm_jtag, uart0, usb_pwr, vc_uart2, vc_uart0, _),
+ PIN(26, sd_card_b, vc_spi0, arm_jtag, uart0, usb_vbus, vc_uart2, vc_spi0, _),
+ PIN(27, sd_card_b, vc_spi0, arm_jtag, uart0, vc_uart2, vc_spi0, _, _),
+ PIN(28, sd_card_b, vc_spi0, arm_jtag, vc_i2c0, vc_spi0, _, _, _),
+ PIN(29, arm_jtag, vc_i2c0, vc_spi0, _, _, _, _, _),
+ PIN(30, sd2, gpclk0, vc_pwm0, _, _, _, _, _),
+ PIN(31, sd2, vc_spi3, vc_pwm0, _, _, _, _, _),
+ PIN(32, sd2, vc_spi3, vc_uart3, _, _, _, _, _),
+ PIN(33, sd2, vc_spi3, vc_uart3, _, _, _, _, _),
+ PIN(34, sd2, vc_spi3, vc_i2c5, _, _, _, _, _),
+ PIN(35, sd2, vc_spi3, vc_i2c5, _, _, _, _, _),
+};
+
+static inline u32 bcm2712_reg_rd(struct bcm2712_pinctrl *pc, unsigned reg)
+{
+ return readl(pc->base + reg);
+}
+
+static inline void bcm2712_reg_wr(struct bcm2712_pinctrl *pc, unsigned reg,
+ u32 val)
+{
+ writel(val, pc->base + reg);
+}
+
+static enum bcm2712_funcs bcm2712_pinctrl_fsel_get(
+ struct bcm2712_pinctrl *pc, unsigned pin)
+{
+ u32 bit = pc->pin_regs[pin].mux_bit;
+ enum bcm2712_funcs func;
+ int fsel;
+ u32 val;
+
+ if (!bit)
+ return func_gpio;
+ bit &= ~MUX_BIT_VALID;
+
+ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit));
+ fsel = (val >> BIT_TO_SHIFT(bit)) & BCM2712_FSEL_MASK;
+ func = pc->pin_funcs[pin].funcs[fsel];
+ if (func >= func_count)
+ func = (enum bcm2712_funcs)fsel;
+
+ dev_dbg(pc->dev, "get %04x: %08x (%u => %s)\n",
+ BIT_TO_REG(bit), val, pin,
+ bcm2712_func_names[func]);
+
+ return func;
+}
+
+static void bcm2712_pinctrl_fsel_set(
+ struct bcm2712_pinctrl *pc, unsigned pin,
+ enum bcm2712_funcs func)
+{
+ u32 bit = pc->pin_regs[pin].mux_bit, val;
+ const u8 *pin_funcs;
+ unsigned long flags;
+ int fsel;
+ int cur;
+ int i;
+
+ if (!bit || func >= func_count)
+ return;
+ bit &= ~MUX_BIT_VALID;
+
+ fsel = BCM2712_FSEL_COUNT;
+
+ if (func >= BCM2712_FSEL_COUNT) {
+ /* Convert to an fsel number */
+ pin_funcs = pc->pin_funcs[pin].funcs;
+ for (i = 1; i < BCM2712_FSEL_COUNT; i++) {
+ if (pin_funcs[i - 1] == func) {
+ fsel = i;
+ break;
+ }
+ }
+ } else {
+ fsel = (enum bcm2712_funcs)func;
+ }
+ if (fsel >= BCM2712_FSEL_COUNT)
+ return;
+
+ spin_lock_irqsave(&pc->lock, flags);
+
+ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit));
+ cur = (val >> BIT_TO_SHIFT(bit)) & BCM2712_FSEL_MASK;
+
+ dev_dbg(pc->dev, "read %04x: %08x (%u => %s)\n",
+ BIT_TO_REG(bit), val, pin,
+ bcm2712_func_names[cur]);
+
+ if (cur != fsel) {
+ val &= ~(BCM2712_FSEL_MASK << BIT_TO_SHIFT(bit));
+ val |= fsel << BIT_TO_SHIFT(bit);
+
+ dev_dbg(pc->dev, "write %04x: %08x (%u <= %s)\n",
+ BIT_TO_REG(bit), val, pin,
+ bcm2712_func_names[fsel]);
+ bcm2712_reg_wr(pc, BIT_TO_REG(bit), val);
+ }
+
+ spin_unlock_irqrestore(&pc->lock, flags);
+}
+
+static int bcm2712_pctl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+
+ return pc->pctl_desc.npins;
+}
+
+static const char *bcm2712_pctl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+
+ return pc->gpio_groups[selector];
+}
+
+static int bcm2712_pctl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const unsigned **pins,
+ unsigned *num_pins)
+{
+ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+
+ *pins = &pc->pctl_desc.pins[selector].number;
+ *num_pins = 1;
+
+ return 0;
+}
+
+static void bcm2712_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+ unsigned offset)
+{
+ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+ enum bcm2712_funcs fsel = bcm2712_pinctrl_fsel_get(pc, offset);
+ const char *fname = bcm2712_func_names[fsel];
+
+ seq_printf(s, "function %s", fname);
+}
+
+static void bcm2712_pctl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *maps, unsigned num_maps)
+{
+ int i;
+
+ for (i = 0; i < num_maps; i++)
+ if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
+ kfree(maps[i].data.configs.configs);
+
+ kfree(maps);
+}
+
+static const struct pinctrl_ops bcm2712_pctl_ops = {
+ .get_groups_count = bcm2712_pctl_get_groups_count,
+ .get_group_name = bcm2712_pctl_get_group_name,
+ .get_group_pins = bcm2712_pctl_get_group_pins,
+ .pin_dbg_show = bcm2712_pctl_pin_dbg_show,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+ .dt_free_map = bcm2712_pctl_dt_free_map,
+};
+
+static int bcm2712_pmx_free(struct pinctrl_dev *pctldev,
+ unsigned offset)
+{
+ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable by setting to GPIO */
+ bcm2712_pinctrl_fsel_set(pc, offset, func_gpio);
+ return 0;
+}
+
+static int bcm2712_pmx_get_functions_count(struct pinctrl_dev *pctldev)
+{
+ return func_count;
+}
+
+static const char *bcm2712_pmx_get_function_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return (selector < func_count) ? bcm2712_func_names[selector] : NULL;
+}
+
+static int bcm2712_pmx_get_function_groups(struct pinctrl_dev *pctldev,
+ unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+ /* every pin can do every function */
+ *groups = pc->gpio_groups;
+ *num_groups = pc->pctl_desc.npins;
+
+ return 0;
+}
+
+static int bcm2712_pmx_set(struct pinctrl_dev *pctldev,
+ unsigned func_selector,
+ unsigned group_selector)
+{
+ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+ const struct pinctrl_desc *pctldesc = &pc->pctl_desc;
+ const struct pinctrl_pin_desc *pindesc;
+
+ if (group_selector >= pctldesc->npins)
+ return -EINVAL;
+ pindesc = &pctldesc->pins[group_selector];
+ bcm2712_pinctrl_fsel_set(pc, pindesc->number, func_selector);
+
+ return 0;
+}
+static int bcm2712_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned pin)
+{
+ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+
+ bcm2712_pinctrl_fsel_set(pc, pin, func_gpio);
+
+ return 0;
+}
+
+static void bcm2712_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+
+ /* disable by setting to GPIO */
+ bcm2712_pinctrl_fsel_set(pc, offset, func_gpio);
+}
+
+static const struct pinmux_ops bcm2712_pmx_ops = {
+ .free = bcm2712_pmx_free,
+ .get_functions_count = bcm2712_pmx_get_functions_count,
+ .get_function_name = bcm2712_pmx_get_function_name,
+ .get_function_groups = bcm2712_pmx_get_function_groups,
+ .set_mux = bcm2712_pmx_set,
+ .gpio_request_enable = bcm2712_pmx_gpio_request_enable,
+ .gpio_disable_free = bcm2712_pmx_gpio_disable_free,
+};
+
+static unsigned int bcm2712_pull_config_get(struct bcm2712_pinctrl *pc,
+ unsigned int pin)
+{
+ u32 bit = pc->pin_regs[pin].pad_bit, val;
+
+ if (unlikely(bit == REG_BIT_INVALID))
+ return BCM2712_PULL_NONE;
+
+ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit));
+ return (val >> BIT_TO_SHIFT(bit)) & BCM2712_PULL_MASK;
+}
+
+static void bcm2712_pull_config_set(struct bcm2712_pinctrl *pc,
+ unsigned int pin, unsigned int arg)
+{
+ u32 bit = pc->pin_regs[pin].pad_bit, val;
+ unsigned long flags;
+
+ if (unlikely(bit == REG_BIT_INVALID)) {
+ dev_warn(pc->dev, "can't set pulls for %s\n", pc->gpio_groups[pin]);
+ return;
+ }
+
+ spin_lock_irqsave(&pc->lock, flags);
+
+ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit));
+ val &= ~(BCM2712_PULL_MASK << BIT_TO_SHIFT(bit));
+ val |= (arg << BIT_TO_SHIFT(bit));
+ bcm2712_reg_wr(pc, BIT_TO_REG(bit), val);
+
+ spin_unlock_irqrestore(&pc->lock, flags);
+}
+
+static int bcm2712_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned pin, unsigned long *config)
+{
+ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+ enum pin_config_param param = pinconf_to_config_param(*config);
+ u32 arg;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_NONE);
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_DOWN);
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_UP);
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return -ENOTSUPP;
+}
+
+static int bcm2712_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+ u32 param, arg;
+ int i;
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_NONE);
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_DOWN);
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_UP);
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+ } /* for each config */
+
+ return 0;
+}
+
+static const struct pinconf_ops bcm2712_pinconf_ops = {
+ .is_generic = true,
+ .pin_config_get = bcm2712_pinconf_get,
+ .pin_config_set = bcm2712_pinconf_set,
+};
+
+static const struct pinctrl_desc bcm2712_c0_pinctrl_desc = {
+ .name = "pinctrl-bcm2712",
+ .pins = bcm2712_c0_gpio_pins,
+ .npins = ARRAY_SIZE(bcm2712_c0_gpio_pins),
+ .pctlops = &bcm2712_pctl_ops,
+ .pmxops = &bcm2712_pmx_ops,
+ .confops = &bcm2712_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static const struct pinctrl_desc bcm2712_c0_aon_pinctrl_desc = {
+ .name = "aon-pinctrl-bcm2712",
+ .pins = bcm2712_c0_aon_gpio_pins,
+ .npins = ARRAY_SIZE(bcm2712_c0_aon_gpio_pins),
+ .pctlops = &bcm2712_pctl_ops,
+ .pmxops = &bcm2712_pmx_ops,
+ .confops = &bcm2712_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static const struct pinctrl_desc bcm2712_d0_pinctrl_desc = {
+ .name = "pinctrl-bcm2712",
+ .pins = bcm2712_d0_gpio_pins,
+ .npins = ARRAY_SIZE(bcm2712_d0_gpio_pins),
+ .pctlops = &bcm2712_pctl_ops,
+ .pmxops = &bcm2712_pmx_ops,
+ .confops = &bcm2712_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static const struct pinctrl_desc bcm2712_d0_aon_pinctrl_desc = {
+ .name = "aon-pinctrl-bcm2712",
+ .pins = bcm2712_d0_aon_gpio_pins,
+ .npins = ARRAY_SIZE(bcm2712_d0_aon_gpio_pins),
+ .pctlops = &bcm2712_pctl_ops,
+ .pmxops = &bcm2712_pmx_ops,
+ .confops = &bcm2712_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static const struct pinctrl_gpio_range bcm2712_c0_pinctrl_gpio_range = {
+ .name = "pinctrl-bcm2712",
+ .npins = ARRAY_SIZE(bcm2712_c0_gpio_pins),
+};
+
+static const struct pinctrl_gpio_range bcm2712_c0_aon_pinctrl_gpio_range = {
+ .name = "aon-pinctrl-bcm2712",
+ .npins = ARRAY_SIZE(bcm2712_c0_aon_gpio_pins),
+};
+
+static const struct pinctrl_gpio_range bcm2712_d0_pinctrl_gpio_range = {
+ .name = "pinctrl-bcm2712",
+ .npins = ARRAY_SIZE(bcm2712_d0_gpio_pins),
+};
+
+static const struct pinctrl_gpio_range bcm2712_d0_aon_pinctrl_gpio_range = {
+ .name = "aon-pinctrl-bcm2712",
+ .npins = ARRAY_SIZE(bcm2712_d0_aon_gpio_pins),
+};
+
+static const struct bcm_plat_data bcm2712_c0_plat_data = {
+ .pctl_desc = &bcm2712_c0_pinctrl_desc,
+ .gpio_range = &bcm2712_c0_pinctrl_gpio_range,
+ .pin_regs = bcm2712_c0_gpio_pin_regs,
+ .pin_funcs = bcm2712_c0_gpio_pin_funcs,
+};
+
+static const struct bcm_plat_data bcm2712_c0_aon_plat_data = {
+ .pctl_desc = &bcm2712_c0_aon_pinctrl_desc,
+ .gpio_range = &bcm2712_c0_aon_pinctrl_gpio_range,
+ .pin_regs = bcm2712_c0_aon_gpio_pin_regs,
+ .pin_funcs = bcm2712_c0_aon_gpio_pin_funcs,
+};
+
+static const struct bcm_plat_data bcm2712_d0_plat_data = {
+ .pctl_desc = &bcm2712_d0_pinctrl_desc,
+ .gpio_range = &bcm2712_d0_pinctrl_gpio_range,
+ .pin_regs = bcm2712_d0_gpio_pin_regs,
+ .pin_funcs = bcm2712_d0_gpio_pin_funcs,
+};
+
+static const struct bcm_plat_data bcm2712_d0_aon_plat_data = {
+ .pctl_desc = &bcm2712_d0_aon_pinctrl_desc,
+ .gpio_range = &bcm2712_d0_aon_pinctrl_gpio_range,
+ .pin_regs = bcm2712_d0_aon_gpio_pin_regs,
+ .pin_funcs = bcm2712_d0_aon_gpio_pin_funcs,
+};
+
+static const struct of_device_id bcm2712_pinctrl_match[] = {
+ {
+ .compatible = "brcm,bcm2712-pinctrl",
+ .data = &bcm2712_c0_plat_data,
+ },
+ {
+ .compatible = "brcm,bcm2712-aon-pinctrl",
+ .data = &bcm2712_c0_aon_plat_data,
+ },
+
+ {
+ .compatible = "brcm,bcm2712c0-pinctrl",
+ .data = &bcm2712_c0_plat_data,
+ },
+ {
+ .compatible = "brcm,bcm2712c0-aon-pinctrl",
+ .data = &bcm2712_c0_aon_plat_data,
+ },
+
+ {
+ .compatible = "brcm,bcm2712d0-pinctrl",
+ .data = &bcm2712_d0_plat_data,
+ },
+ {
+ .compatible = "brcm,bcm2712d0-aon-pinctrl",
+ .data = &bcm2712_d0_aon_plat_data,
+ },
+ {}
+};
+
+static int bcm2712_pinctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ //struct device_node *np = dev->of_node;
+ const struct bcm_plat_data *pdata;
+ //const struct of_device_id *match;
+ struct bcm2712_pinctrl *pc;
+ const char **names;
+ int num_pins, i;
+
+ pdata = device_get_match_data(&pdev->dev);
+ if (!pdata)
+ return -EINVAL;
+
+ pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
+ if (!pc)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, pc);
+ pc->dev = dev;
+ spin_lock_init(&pc->lock);
+
+ //pc->base = devm_of_iomap(dev, np, 0, NULL);
+ pc->base = devm_platform_ioremap_resource(pdev, 0);
+ if (WARN_ON(IS_ERR(pc->base))) {
+ //dev_err(dev, "could not get IO memory\n");
+ return PTR_ERR(pc->base);
+ }
+
+ pc->pctl_desc = *pdata->pctl_desc;
+ num_pins = pc->pctl_desc.npins;
+ names = devm_kmalloc_array(dev, num_pins, sizeof(const char *),
+ GFP_KERNEL);
+ if (!names)
+ return -ENOMEM;
+ for (i = 0; i < num_pins; i++)
+ names[i] = pc->pctl_desc.pins[i].name;
+ pc->gpio_groups = names;
+ pc->pin_regs = pdata->pin_regs;
+ pc->pin_funcs = pdata->pin_funcs;
+ pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc);
+ if (IS_ERR(pc->pctl_dev))
+ return PTR_ERR(pc->pctl_dev);
+
+ pc->gpio_range = *pdata->gpio_range;
+ pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
+
+ return 0;
+}
+
+static struct platform_driver bcm2712_pinctrl_driver = {
+ .probe = bcm2712_pinctrl_probe,
+ .driver = {
+ .name = MODULE_NAME,
+ .of_match_table = bcm2712_pinctrl_match,
+ .suppress_bind_attrs = true,
+ },
+};
+builtin_platform_driver(bcm2712_pinctrl_driver);
--
2.35.3
On Sun, 14 Apr 2024 00:14:24 +0200, Andrea della Porta wrote:
> Signed-off-by: Andrea della Porta <[email protected]>
> ---
> .../bindings/mmc/brcm,sdhci-brcmstb.yaml | 51 ++++++++++++++++++-
> 1 file changed, 50 insertions(+), 1 deletion(-)
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml:91:10: [warning] wrong indentation: expected 10 but found 9 (indentation)
/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml:91:17: [error] string value is redundantly quoted with any quotes (quoted-strings)
dtschema/dtc warnings/errors:
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/ad96fff723675c2d65a5e3328da9b09f2781cbcd.1713036964.git.andrea.porta@suse.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
On 14/04/2024 00:14, Andrea della Porta wrote:
> Signed-off-by: Andrea della Porta <[email protected]>
? And what is being done here and why?
> ---
> .../bindings/mmc/brcm,sdhci-brcmstb.yaml | 51 ++++++++++++++++++-
> 1 file changed, 50 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
> index cbd3d6c6c77f..6aa137d78e4f 100644
> --- a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
> +++ b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
> @@ -13,6 +13,7 @@ maintainers:
> properties:
> compatible:
> oneOf:
> + - const: brcm,bcm2712-sdhci
> - items:
> - enum:
> - brcm,bcm7216-sdhci
> @@ -26,12 +27,16 @@ properties:
> - const: brcm,sdhci-brcmstb
>
> reg:
> - maxItems: 2
> + minItems: 2
> + maxItems: 4
>
> reg-names:
> + minItems: 2
> items:
> - const: host
> - const: cfg
> + - const: busisol
> + - const: lcpll
>
> interrupts:
> maxItems: 1
> @@ -60,6 +65,7 @@ properties:
> description: Specifies that controller should use auto CMD12
>
> allOf:
> + - $ref: sdhci-common.yaml
> - $ref: mmc-controller.yaml#
Why? Anyway, this replaces mmc-controller, doesn't it?
> - if:
> properties:
> @@ -71,6 +77,28 @@ allOf:
> required:
> - clock-frequency
>
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: brcm,bcm2712-sdhci
> +
> + then:
> + properties:
> + reg:
> + maxItems: 4
> + clock-names:
> + const: "sw_sdio"
Not tested.
> +
> + else:
> + properties:
> + reg:
> + minItems: 2
> + maxItems: 2
> + reg-names:
> + minItems: 2
> + maxItems: 2
> +
> required:
> - compatible
> - reg
> @@ -114,3 +142,24 @@ examples:
> clocks = <&scmi_clk 245>;
> clock-names = "sw_sdio";
> };
> +
> + - |
> + soc {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + mmc@fff000 {
> + compatible = "brcm,bcm2712-sdhci";
> + reg = <0x10 0x00fff000 0x0 0x260>,
> + <0x10 0x00fff400 0x0 0x200>,
> + <0x10 0x015040b0 0x0 0x4>, // Bus isolation control
> + <0x10 0x015200f0 0x0 0x24>; // LCPLL control misc0-8
> + reg-names = "host", "cfg", "busisol", "lcpll";
> + interrupts = <0x0 0x111 0x4>;
Use proper defines.
> + clocks = <&clk_emmc2>;
> + sdhci-caps-mask = <0x0000C000 0x0>;
> + sdhci-caps = <0x0 0x0>;
> + mmc-ddr-3_3v;
> + clock-names = "sw_sdio";
names *always* follow property. In every DTS. Please fix youro DTS.
Best regards,
Krzysztof
On 14/04/2024 00:14, Andrea della Porta wrote:
> Signed-off-by: Andrea della Porta <[email protected]>
> ---
> arch/arm64/boot/dts/broadcom/Makefile | 1 +
> .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 313 +++++++
> arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 81 ++
> arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 841 ++++++++++++++++++
> 4 files changed, 1236 insertions(+)
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712.dtsi
>
> diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile
> index 8b4591ddd27c..92565e9781ad 100644
> --- a/arch/arm64/boot/dts/broadcom/Makefile
> +++ b/arch/arm64/boot/dts/broadcom/Makefile
> @@ -6,6 +6,7 @@ DTC_FLAGS := -@
> dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb \
> bcm2711-rpi-4-b.dtb \
> bcm2711-rpi-cm4-io.dtb \
> + bcm2712-rpi-5-b.dtb \
> bcm2837-rpi-3-a-plus.dtb \
> bcm2837-rpi-3-b.dtb \
> bcm2837-rpi-3-b-plus.dtb \
> diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> new file mode 100644
> index 000000000000..2ce180a54e5b
> --- /dev/null
> +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> @@ -0,0 +1,313 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/dts-v1/;
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/interrupt-controller/irq.h>
> +#include <dt-bindings/pwm/pwm.h>
> +#include <dt-bindings/reset/raspberrypi,firmware-reset.h>
> +
> +#define spi0 _spi0
> +#define uart0 _uart0
> +
> +#include "bcm2712.dtsi"
> +
> +#undef spi0
> +#undef uart0
> +
> +/ {
> + compatible = "raspberrypi,5-model-b", "brcm,bcm2712";
This patch did not pass basic tests. Like checkpatch.
Please run scripts/checkpatch.pl and fix reported warnings. Then please
run `scripts/checkpatch.pl --strict` and (probably) fix more warnings.
Some warnings can be ignored, especially from --strict run, but the code
here looks like it needs a fix. Feel free to get in touch if the warning
is not clear.
It does not look like you tested the DTS against bindings. Please run
`make dtbs_check W=1` (see
Documentation/devicetree/bindings/writing-schema.rst or
https://www.linaro.org/blog/tips-and-tricks-for-validating-devicetree-sources-with-the-devicetree-schema/
for instructions).
> + model = "Raspberry Pi 5";
> +
> + /* Will be filled by the bootloader */
> + memory@0 {
> + device_type = "memory";
> + reg = <0 0 0x28000000>;
> + };
> +
> + leds: leds {
> + compatible = "gpio-leds";
> +
> + led_act: led-act {
> + label = "ACT";
> + gpios = <&gio_aon 9 GPIO_ACTIVE_LOW>;
> + default-state = "off";
> + linux,default-trigger = "mmc0";
> + };
> + };
> +
> + sd_io_1v8_reg: sd_io_1v8_reg {
Don't push to us downstream code. Please fix it first and adjust to
match DTS coding style. Underscores are not allowed in node names.
> + compatible = "regulator-gpio";
> + regulator-name = "vdd-sd-io";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-boot-on;
> + regulator-always-on;
> + regulator-settling-time-us = <5000>;
> + gpios = <&gio_aon 3 GPIO_ACTIVE_HIGH>;
> + states = <1800000 0x1
> + 3300000 0x0>;
Aren't these two tupples?
> + status = "okay";
Why? Where is it disabled?
> + };
> +
> + sd_vcc_reg: sd_vcc_reg {
Underscores...
> + compatible = "regulator-fixed";
> + regulator-name = "vcc-sd";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-boot-on;
> + enable-active-high;
> + gpios = <&gio_aon 4 GPIO_ACTIVE_HIGH>;
> + status = "okay";
Why?
> + };
> +
> + wl_on_reg: wl_on_reg {
> + compatible = "regulator-fixed";
> + regulator-name = "wl-on-regulator";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + pinctrl-0 = <&wl_on_pins>;
> + pinctrl-names = "default";
> +
> + gpio = <&gio 28 GPIO_ACTIVE_HIGH>;
> +
> + startup-delay-us = <150000>;
> + enable-active-high;
> + };
> +
> + clocks: clocks {
> + };
Drop, useless.
> +};
> +
> +// Add some labels to 2712 device
> +
> +// The system UART
> +uart10: &_uart0 { status = "okay"; };
> +
> +// The system SPI for the bootloader EEPROM
> +spi10: &_spi0 { status = "okay"; };
Use standard coding style. Look at other recent platforms how it is done.
&spi {
foo;
};
> +
> +#include "bcm2712-rpi.dtsi"
This goes to the top.
I must say this DTS is terrible to read.
> +
> +/* SDIO1 is used to drive the SD card */
> +&sdio1 {
> + pinctrl-0 = <&emmc_sd_pulls>, <&emmc_aon_cd_pins>;
> + pinctrl-names = "default";
> + vqmmc-supply = <&sd_io_1v8_reg>;
> + vmmc-supply = <&sd_vcc_reg>;
> + bus-width = <4>;
> + sd-uhs-sdr50;
> + sd-uhs-ddr50;
> + sd-uhs-sdr104;
> + cd-gpios = <&gio_aon 5 GPIO_ACTIVE_LOW>;
> + //no-1-8-v;
Do not add dead code to the kernel.
> + status = "okay";
> +};
> +
> +&pinctrl_aon {
> + emmc_aon_cd_pins: emmc_aon_cd_pins {
Again, no underscores.
> + function = "sd_card_g";
> + pins = "aon_gpio5";
> + bias-pull-up;
> + };
> +
> + /* Slight hack - only one PWM pin (status LED) is usable */
> + aon_pwm_1pin: aon_pwm_1pin {
> + function = "aon_pwm";
> + pins = "aon_gpio9";
> + };
> +};
> +
> +&pinctrl {
> + pwr_button_pins: pwr_button_pins {
> + function = "gpio";
> + pins = "gpio20";
> + bias-pull-up;
> + };
> +
> + wl_on_pins: wl_on_pins {
> + function = "gpio";
> + pins = "gpio28";
> + };
> +
> + bt_shutdown_pins: bt_shutdown_pins {
> + function = "gpio";
> + pins = "gpio29";
> + };
> +
> + emmc_sd_pulls: emmc_sd_pulls {
> + pins = "emmc_cmd", "emmc_dat0", "emmc_dat1", "emmc_dat2", "emmc_dat3";
> + bias-pull-up;
> + };
> +};
> +
> +/ {
Why the heck this appears in the middle? This is top level section. I am
sorry, but this DTS looks really poor and not like existing coding
style. Please do not introduce some entirely different coding styles.
> + chosen: chosen {
> + bootargs = "reboot=w coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1";
Not a DTS properties. Drop entire bootargs.
> + stdout-path = "serial10:115200n8";
> + };
> +
> + pwr_button {
Srsly...
> + compatible = "gpio-keys";
> +
> + pinctrl-names = "default";
> + pinctrl-0 = <&pwr_button_pins>;
> + status = "okay";
???
> +
> + pwr_key: pwr {
OK, you definitely did not test it. The code looks worse and worse I
keep looking, so I will stop.
This did not pass basic internal review, checkpatch, basic tests.
..
> +
> + // Pad bank0 out to 32 entries
> + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
> +
> + "HDMI0_SCL", // AON_SGPIO_00
> + "HDMI0_SDA", // AON_SGPIO_01
> + "HDMI1_SCL", // AON_SGPIO_02
> + "HDMI1_SDA", // AON_SGPIO_03
> + "PMIC_SCL", // AON_SGPIO_04
> + "PMIC_SDA"; // AON_SGPIO_05
> +};
> +
> +/ {
> + aliases {
OK, now you are trolling us. It is third top-level node!
Limited review follows.
> + blconfig = &blconfig;
> + blpubkey = &blpubkey;
> + console = &uart10;
> + mailbox = &mailbox;
> + mmc0 = &sdio1;
> + uart10 = &uart10;
> + serial10 = &uart10;
> + gpio1 = &gio;
> + gpio2 = &gio_aon;
> + gpio3 = &pinctrl;
> + gpio4 = &pinctrl_aon;
> + };
> +
> + __overrides__ {
?
Drop
> + button_debounce = <&pwr_key>, "debounce-interval:0";
> + random = <&random>, "status";
> + sd_cqe = <&sdio1>, "supports-cqe?";
> + suspend = <&pwr_key>, "linux,code:0=205";
> + act_led_activelow = <&led_act>,"gpios:8";
> + act_led_trigger = <&led_act>, "linux,default-trigger";
> + };
> +};
> diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
> new file mode 100644
> index 000000000000..d04e39b9c0b6
> --- /dev/null
> +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
What is this file for?
> @@ -0,0 +1,81 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <dt-bindings/power/raspberrypi-power.h>
> +
> +&soc {
> + firmware: firmware {
> + compatible = "raspberrypi,bcm2835-firmware", "simple-mfd";
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + mboxes = <&mailbox>;
> + dma-ranges;
> +
> + firmware_clocks: clocks {
> + compatible = "raspberrypi,firmware-clocks";
> + #clock-cells = <1>;
> + };
> +
> + reset: reset {
> + compatible = "raspberrypi,firmware-reset";
> + #reset-cells = <1>;
> + };
> + };
> +
> + power: power {
> + compatible = "raspberrypi,bcm2835-power";
> + firmware = <&firmware>;
> + #power-domain-cells = <1>;
> + };
> +
> + /* Define these notional regulators for use by overlays, etc. */
> + vdd_3v3_reg: fixedregulator_3v3 {
W=2 warnings.
> + compatible = "regulator-fixed";
> + regulator-always-on;
> + regulator-max-microvolt = <3300000>;
> + regulator-min-microvolt = <3300000>;
> + regulator-name = "3v3";
> + };
> +
> + vdd_5v0_reg: fixedregulator_5v0 {
W=2 warnings.
> + compatible = "regulator-fixed";
> + regulator-always-on;
> + regulator-max-microvolt = <5000000>;
> + regulator-min-microvolt = <5000000>;
> + regulator-name = "5v0";
> + };
> +};
> +
> +/ {
> + __overrides__ {
> + arm_freq;
NAK, drop.
> + };
> +};
> +
> +&rmem {
> + /*
> + * RPi5's co-processor will copy the board's bootloader configuration
> + * into memory for the OS to consume. It'll also update this node with
> + * its placement information.
> + */
> + blconfig: nvram@0 {
> + compatible = "raspberrypi,bootloader-config", "nvmem-rmem";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + reg = <0x0 0x0 0x0>;
> + no-map;
> + status = "disabled";
> + };
> + /*
> + * RPi5 will copy the binary public key blob (if present) from the bootloader
> + * into memory for use by the OS.
> + */
> + blpubkey: nvram@1 {
> + compatible = "raspberrypi,bootloader-public-key", "nvmem-rmem";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + reg = <0x0 0x0 0x0>;
> + no-map;
> + status = "disabled";
> + };
> +};
> diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> new file mode 100644
> index 000000000000..fd5a19f68b49
> --- /dev/null
> +++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> @@ -0,0 +1,841 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/soc/bcm2835-pm.h>
> +#include <dt-bindings/phy/phy.h>
> +
> +/ {
> + compatible = "brcm,bcm2712", "brcm,bcm2711";
Please run scripts/checkpatch.pl and fix reported warnings. Then please
run `scripts/checkpatch.pl --strict` and (probably) fix more warnings.
Some warnings can be ignored, especially from --strict run, but the code
here looks like it needs a fix. Feel free to get in touch if the warning
is not clear.
> + model = "BCM2712";
Drop
> +
> + clk_27MHz: clk-27M {
No upperscore letters.
> + #clock-cells = <0>;
> + compatible = "fixed-clock";
> + clock-frequency = <27000000>;
> + clock-output-names = "27MHz-clock";
> + };
> +
> + clk_108MHz: clk-108M {
> + #clock-cells = <0>;
> + compatible = "fixed-clock";
> + clock-frequency = <108000000>;
> + clock-output-names = "108MHz-clock";
> + };
> +
> + soc: soc {
> + compatible = "simple-bus";
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + ranges = <0x7c000000 0x10 0x7c000000 0x04000000>;
> + /* Emulate a contiguous 30-bit address range for DMA */
> + dma-ranges = <0xc0000000 0x00 0x00000000 0x40000000>,
> + <0x7c000000 0x10 0x7c000000 0x04000000>;
> +
> + system_timer: timer@7c003000 {
> + compatible = "brcm,bcm2835-system-timer";
> + reg = <0x7c003000 0x1000>;
> + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
> + clock-frequency = <1000000>;
> + };
> +
> + mailbox: mailbox@7c013880 {
> + compatible = "brcm,bcm2835-mbox";
> + reg = <0x7c013880 0x40>;
> + interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
> + #mbox-cells = <0>;
> + };
> +
> + disp_intr: interrupt-controller@7c502000 {
> + compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc";
> + reg = <0x7c502000 0x30>;
> + interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + status = "disabled";
> + };
> +
> + dvp: clock@7c700000 {
> + compatible = "brcm,brcm2711-dvp";
> + reg = <0x7c700000 0x10>;
> + clocks = <&clk_108MHz>;
> + #clock-cells = <1>;
> + #reset-cells = <1>;
> + };
> +
> + /*
> + * This node is the provider for the enable-method for
> + * bringing up secondary cores.
> + */
> + local_intc: local_intc@7cd00000 {
You really need to clean this up...
> + compatible = "brcm,bcm2836-l1-intc";
> + reg = <0x7cd00000 0x100>;
> + };
> +
> + uart0: serial@7d001000 {
> + compatible = "arm,pl011", "arm,primecell";
> + reg = <0x7d001000 0x200>;
> + interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&clk_uart>,
> + <&clk_vpu>;
> + clock-names = "uartclk", "apb_pclk";
> + arm,primecell-periphid = <0x00241011>;
> + status = "disabled";
> + };
> +
> + uart2: serial@7d001400 {
> + compatible = "arm,pl011", "arm,primecell";
> + reg = <0x7d001400 0x200>;
> + interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&clk_uart>,
> + <&clk_vpu>;
> + clock-names = "uartclk", "apb_pclk";
> + arm,primecell-periphid = <0x00241011>;
> + status = "disabled";
> + };
> +
> + uart5: serial@7d001a00 {
> + compatible = "arm,pl011", "arm,primecell";
> + reg = <0x7d001a00 0x200>;
> + interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&clk_uart>,
> + <&clk_vpu>;
> + clock-names = "uartclk", "apb_pclk";
> + arm,primecell-periphid = <0x00241011>;
> + status = "disabled";
> + };
> +
> + sdhost: mmc@7d002000 {
> + compatible = "brcm,bcm2835-sdhost";
> + reg = <0x7d002000 0x100>;
> + //interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
No dead code.
..
> +
> + random: rng@7d208000 {
> + compatible = "brcm,bcm2711-rng200";
> + reg = <0x7d208000 0x28>;
> + status = "okay";
Drop.
I just ignored the rest. Quality does not improve. This DTS is in very
poor shape and not suitable for mainline submission.
Please very carefully read DTS coding style and send DTS only after
fixing all automation errors (all! so checkpatch, W=1, dtbs_check W=1)
and after aligning this in 100% to DTS coding style.
Best regards,
Krzysztof
On 14/04/2024 00:14, Andrea della Porta wrote:
> Broadcom BCM2712 SoC has an SDHCI card controller using the SDIO CFG
> register block present on other STB chips. Add support for BCM2712
> SD capabilities of this chipset.
> The silicon is SD Express capable but this driver port does not currently
> include that feature yet.
> Based on downstream driver by raspberry foundation maintained kernel.
DTS and parts of this code look like you just send to us downstream
code. Upstreaming does not work like this. Please consult your folks in
Suse to explain you more how upstreaming process looks like.
>
> Signed-off-by: Andrea della Porta <[email protected]>
> ---
> drivers/mmc/host/sdhci-brcmstb.c | 130 +++++++++++++++++++++++++++++++
> 1 file changed, 130 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
> index 9053526fa212..907a4947abe5 100644
> --- a/drivers/mmc/host/sdhci-brcmstb.c
> +++ b/drivers/mmc/host/sdhci-brcmstb.c
> @@ -12,6 +12,8 @@
> #include <linux/of.h>
> #include <linux/bitops.h>
> #include <linux/delay.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/regulator/consumer.h>
>
> #include "sdhci-cqhci.h"
> #include "sdhci-pltfm.h"
> @@ -30,15 +32,31 @@
>
> #define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
>
> +#define SDIO_CFG_CTRL 0x0
> +#define SDIO_CFG_CTRL_SDCD_N_TEST_EN BIT(31)
> +#define SDIO_CFG_CTRL_SDCD_N_TEST_LEV BIT(30)
> +
> +#define SDIO_CFG_SD_PIN_SEL 0x44
> +#define SDIO_CFG_SD_PIN_SEL_MASK 0x3
> +#define SDIO_CFG_SD_PIN_SEL_SD BIT(1)
> +#define SDIO_CFG_SD_PIN_SEL_MMC BIT(0)
> +
> +#define SDIO_CFG_MAX_50MHZ_MODE 0x1ac
> +#define SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE BIT(31)
> +#define SDIO_CFG_MAX_50MHZ_MODE_ENABLE BIT(0)
> +
> struct sdhci_brcmstb_priv {
> void __iomem *cfg_regs;
> unsigned int flags;
> struct clk *base_clk;
> u32 base_freq_hz;
> + struct pinctrl *pinctrl;
> + struct pinctrl_state *pins_default;
> };
>
> struct brcmstb_match_priv {
> void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
> + void (*cfginit)(struct sdhci_host *host);
> struct sdhci_ops *ops;
> const unsigned int flags;
> };
> @@ -124,6 +142,42 @@ static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios)
> writel(reg, host->ioaddr + SDHCI_VENDOR);
> }
>
> +static void sdhci_bcm2712_set_clock(struct sdhci_host *host, unsigned int clock)
> +{
> + u16 clk;
> + u32 reg;
> + bool is_emmc_rate = false;
> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> + struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
> +
> + host->mmc->actual_clock = 0;
> +
> + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
> +
> + switch (host->mmc->ios.timing) {
> + case MMC_TIMING_MMC_HS400:
> + case MMC_TIMING_MMC_HS200:
> + case MMC_TIMING_MMC_DDR52:
> + case MMC_TIMING_MMC_HS:
> + is_emmc_rate = true;
> + break;
> + }
That's not indented correctly.
> +
> + reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
> + reg &= ~SDIO_CFG_SD_PIN_SEL_MASK;
> + if (is_emmc_rate)
> + reg |= SDIO_CFG_SD_PIN_SEL_MMC;
> + else
> + reg |= SDIO_CFG_SD_PIN_SEL_SD;
> + writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
> +
> + if (clock == 0)
> + return;
> +
> + clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
> + sdhci_enable_clk(host, clk);
> +}
> +
> static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock)
> {
> u16 clk;
> @@ -139,6 +193,17 @@ static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock)
> sdhci_enable_clk(host, clk);
> }
>
> +static void sdhci_brcmstb_set_power(struct sdhci_host *host, unsigned char mode,
> + unsigned short vdd)
> +{
> + if (!IS_ERR(host->mmc->supply.vmmc)) {
> + struct mmc_host *mmc = host->mmc;
> +
> + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
> + }
> + sdhci_set_power_noreg(host, mode, vdd);
> +}
> +
> static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host,
> unsigned int timing)
> {
> @@ -168,6 +233,36 @@ static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host,
> sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
> }
>
> +static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
> +{
> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> + struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
> + u32 uhs_mask = (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104);
> + u32 hsemmc_mask = (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS200_1_2V_SDR |
> + MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V);
> + u32 reg;
> +
> + /*
> + * If we support a speed that requires tuning,
> + * then select the delay line PHY as the clock source.
> + */
> + if ((host->mmc->caps & uhs_mask) || (host->mmc->caps2 & hsemmc_mask)) {
> + reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
> + reg &= ~SDIO_CFG_MAX_50MHZ_MODE_ENABLE;
> + reg |= SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE;
> + writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
> + }
> +
> + if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
> + (host->mmc->caps & MMC_CAP_NEEDS_POLL)) {
> + /* Force presence */
> + reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
> + reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV;
> + reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN;
> + writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
> + }
> +}
> +
> static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc)
> {
> sdhci_dumpregs(mmc_priv(mmc));
> @@ -200,6 +295,14 @@ static struct sdhci_ops sdhci_brcmstb_ops = {
> .set_uhs_signaling = sdhci_set_uhs_signaling,
> };
>
> +static struct sdhci_ops sdhci_brcmstb_ops_2712 = {
> + .set_clock = sdhci_bcm2712_set_clock,
> + .set_power = sdhci_brcmstb_set_power,
> + .set_bus_width = sdhci_set_bus_width,
> + .reset = sdhci_reset,
> + .set_uhs_signaling = sdhci_set_uhs_signaling,
> +};
> +
> static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
> .set_clock = sdhci_brcmstb_set_clock,
> .set_bus_width = sdhci_set_bus_width,
> @@ -237,7 +340,13 @@ static struct brcmstb_match_priv match_priv_74165b0 = {
> .ops = &sdhci_brcmstb_ops_74165b0,
> };
>
> +static const struct brcmstb_match_priv match_priv_2712 = {
> + .cfginit = sdhci_brcmstb_cfginit_2712,
> + .ops = &sdhci_brcmstb_ops_2712,
> +};
> +
> static const struct of_device_id __maybe_unused sdhci_brcm_of_match[] = {
> + { .compatible = "brcm,bcm2712-sdhci", .data = &match_priv_2712 },
> { .compatible = "brcm,bcm7425-sdhci", .data = &match_priv_7425 },
> { .compatible = "brcm,bcm7445-sdhci", .data = &match_priv_7445 },
> { .compatible = "brcm,bcm7216-sdhci", .data = &match_priv_7216 },
> @@ -314,11 +423,16 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
> struct sdhci_brcmstb_priv *priv;
> u32 actual_clock_mhz;
> struct sdhci_host *host;
> + bool no_pinctrl = false;
> struct clk *clk;
> struct clk *base_clk = NULL;
> int res;
>
> match = of_match_node(sdhci_brcm_of_match, pdev->dev.of_node);
> + if (!match) {
Why? This is not explained. Please do not add random pieces of code,
just because downstream code makes mistakes. This should go otherway -
downstream should be fixed, not upstream get downstream mistakes.
> + dev_err(&pdev->dev, "fail to get matching of_match struct\n");
> + return -EINVAL;
> + }
> match_priv = match->data;
>
> dev_dbg(&pdev->dev, "Probe found match for %s\n", match->compatible);
> @@ -354,6 +468,19 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
> if (res)
> goto err;
>
> + priv->pinctrl = devm_pinctrl_get(&pdev->dev);
> + if (IS_ERR(priv->pinctrl)) {
> + no_pinctrl = true;
> + }
> + priv->pins_default = pinctrl_lookup_state(priv->pinctrl, "default");
> + if (IS_ERR(priv->pins_default)) {
> + dev_dbg(&pdev->dev, "No pinctrl default state\n");
> + no_pinctrl = true;
> + }
> +
> + if (no_pinctrl )
> + priv->pinctrl = NULL;
> +
> /*
> * Automatic clock gating does not work for SD cards that may
> * voltage switch so only enable it for non-removable devices.
> @@ -370,6 +497,9 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
> (host->mmc->caps2 & MMC_CAP2_HS400_ES))
> host->mmc_host_ops.hs400_enhanced_strobe = match_priv->hs400es;
>
> + if(match_priv->cfginit)
Not conforming to Linux coding style.
Best regards,
Krzysztof
Hi Andrea,
Am 14.04.24 um 00:14 schrieb Andrea della Porta:
> Hi,
>
> This patchset adds support for the SDHCI controller on Broadcom BCM2712
> SoC in order to make it possible to boot (particularly) Raspberry Pi 5
> from SD card. This work is heavily based on downstream contributions.
since your goal is minimal Raspberry Pi 5 support, i suggest to use this
as the subject for this patch.
> Patch #1 and 2: introduce the dt binding definitions for, respectively,
> the new pin cfg/mux controller and the SD host controller as a preparatory
> step for the upcoming dts.
>
> Patch #3: add a somewhat reasonable (*almost* bare-minimum) dts to be used
> to boot Rpi5 boards. Since till now there was no support at all for any
> 2712 based chipset, both the SoC and board dts plus definitions for the
> new Pin and SD host controller have been added.
The patch still seems to contain a lot unnecessary stuff (Wifi, BT,
SPI), please try to remove as much as possible for the minimal support
(just boot via debug UART & SD card) in order to make review easier. Btw
this patch must be after pinctrl & SDHCI support.
> Patch #4: the driver supporting the pin controller. Based on [1] and
> successive fix commits.
>
> Patch #5: add SDHCI support. Based on [2] and the next 2 fix commits.
> Drop the SD Express implementation for now, that will be added by patch
> #6.
>
> Patch #6: this patch offers SD Express support and can be considered totally
> optional. The callback plumbing is slightly different w.r.t. the downstream
> approach (see [3]), as explained in the patch comment. Not sure what is the best,
> any comment is highly appreciated.
I don't think this should be necessary for minimal Raspberry Pi 5
support. Maybe this should be addressed later.
More important would be an additional patch which enables the necessary
drivers in arm64/defconfig.
>
> Tested succesfully on Raspberry Pi 5 using an SDxC card as the boot device.
>
> Still untested:
> - SD Express due to the lack of an Express capable card.
> Also, it will need PCIe support first.
> - card detection pin, since the sd was the booting and root fs device.
>
> Many thanks,
> Andrea
>
> Links:
> [1] - https://github.com/raspberrypi/linux/commit/d9b655314a826724538867bf9b6c229d04c25d84
> [2] - https://github.com/raspberrypi/linux/commit/e3aa070496e840e72a4dc384718690ea4125fa6a
> [3] - https://github.com/raspberrypi/linux/commit/eb1df34db2a9a5b752eba40ee298c4ae87e26e87
>
> Andrea della Porta (6):
> dt-bindings: pinctrl: Add support for BCM2712 pin controller
> dt-bindings: mmc: Add support for BCM2712 SD host controller
> arm64: dts: broadcom: Add support for BCM2712
> pinctrl: bcm: Add pinconf/pinmux controller driver for BCM2712
> mmc: sdhci-brcmstb: Add BCM2712 support
> mmc: sdhci-brcmstb: Add BCM2712 SD Express support
>
> .../bindings/mmc/brcm,sdhci-brcmstb.yaml | 51 +-
> .../pinctrl/brcm,bcm2712-pinctrl.yaml | 99 ++
> arch/arm64/boot/dts/broadcom/Makefile | 1 +
> .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 313 +++++
> arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 81 ++
> arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 841 +++++++++++
> drivers/mmc/host/Kconfig | 1 +
> drivers/mmc/host/sdhci-brcmstb.c | 275 ++++
> drivers/pinctrl/bcm/Kconfig | 9 +
> drivers/pinctrl/bcm/Makefile | 1 +
> drivers/pinctrl/bcm/pinctrl-bcm2712.c | 1247 +++++++++++++++++
> 11 files changed, 2918 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm2712-pinctrl.yaml
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> create mode 100644 drivers/pinctrl/bcm/pinctrl-bcm2712.c
>
Andrea,
On 4/13/2024 3:14 PM, Andrea della Porta wrote:
> Hi,
>
> This patchset adds support for the SDHCI controller on Broadcom BCM2712
> SoC in order to make it possible to boot (particularly) Raspberry Pi 5
> from SD card. This work is heavily based on downstream contributions.
>
> Patch #1 and 2: introduce the dt binding definitions for, respectively,
> the new pin cfg/mux controller and the SD host controller as a preparatory
> step for the upcoming dts.
>
> Patch #3: add a somewhat reasonable (*almost* bare-minimum) dts to be used
> to boot Rpi5 boards. Since till now there was no support at all for any
> 2712 based chipset, both the SoC and board dts plus definitions for the
> new Pin and SD host controller have been added.
>
> Patch #4: the driver supporting the pin controller. Based on [1] and
> successive fix commits.
>
> Patch #5: add SDHCI support. Based on [2] and the next 2 fix commits.
> Drop the SD Express implementation for now, that will be added by patch
> #6.
>
> Patch #6: this patch offers SD Express support and can be considered totally
> optional. The callback plumbing is slightly different w.r.t. the downstream
> approach (see [3]), as explained in the patch comment. Not sure what is the best,
> any comment is highly appreciated.
>
> Tested succesfully on Raspberry Pi 5 using an SDxC card as the boot device.
You really need to improve upon the quality of the patches you are
submitting, they are not passing checkpatch.pl for coding style and this
is seriously concerning.
It sounds like these patches are sent out just to tick a box that an
effort has been made to upstream them, that is not how upstream works,
so please send some quality time on getting them in tip top shape. Thank
you.
--
Florian
On 4/13/2024 3:14 PM, Andrea della Porta wrote:
> Broadcom BCM2712 SDHCI controller is SD Express capable. Add support
> for sde capability where the implementation is based on downstream driver,
> diverging from it in the way that init_sd_express callback is invoked:
> in downstream the sdhci_ops structure has been augmented with a new
> function ptr 'init_sd_express' that just propagate the call to the
> driver specific callback so that the callstack from a structure
> standpoint is mmc_host_ops -> sdhci_ops. The drawback here is in the
> added level of indirection (the newly added init_sd_express is
> redundant) and the sdhci_ops structure declaration has to be changed.
> To overcome this the presented approach consist in patching the mmc_host_ops
> init_sd_express callback to point directly to the custom function defined in
> this driver (see struct brcmstb_match_priv).
>
> Signed-off-by: Andrea della Porta <[email protected]>
> ---
> drivers/mmc/host/Kconfig | 1 +
> drivers/mmc/host/sdhci-brcmstb.c | 147 ++++++++++++++++++++++++++++++-
> 2 files changed, 147 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index aebc587f77a7..343ccac1a4e4 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -1018,6 +1018,7 @@ config MMC_SDHCI_BRCMSTB
> depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
> depends on MMC_SDHCI_PLTFM
> select MMC_CQHCI
> + select OF_DYNAMIC
> default ARCH_BRCMSTB || BMIPS_GENERIC
> help
> This selects support for the SDIO/SD/MMC Host Controller on
> diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
> index 907a4947abe5..56fb34a75ec2 100644
> --- a/drivers/mmc/host/sdhci-brcmstb.c
> +++ b/drivers/mmc/host/sdhci-brcmstb.c
> @@ -29,6 +29,7 @@
>
> #define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0)
> #define BRCMSTB_PRIV_FLAGS_GATE_CLOCK BIT(1)
> +#define BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS BIT(2)
>
> #define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
>
> @@ -50,13 +51,19 @@ struct sdhci_brcmstb_priv {
> unsigned int flags;
> struct clk *base_clk;
> u32 base_freq_hz;
> + struct regulator *sde_1v8;
> + struct device_node *sde_pcie;
> + void *__iomem sde_ioaddr;
> + void *__iomem sde_ioaddr2;
> struct pinctrl *pinctrl;
> struct pinctrl_state *pins_default;
> + struct pinctrl_state *pins_sdex;
> };
>
> struct brcmstb_match_priv {
> void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
> void (*cfginit)(struct sdhci_host *host);
> + int (*init_sd_express)(struct mmc_host *mmc, struct mmc_ios *ios);
> struct sdhci_ops *ops;
> const unsigned int flags;
> };
> @@ -263,6 +270,105 @@ static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
> }
> }
>
> +static int bcm2712_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> + struct sdhci_host *host = mmc_priv(mmc);
> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> + struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
> + struct device *dev = host->mmc->parent;
> + u32 ctrl_val;
> + u32 present_state;
> + int ret;
> +
> + if (!brcmstb_priv->sde_ioaddr || !brcmstb_priv->sde_ioaddr2)
> + return -EINVAL;
> +
> + if (!brcmstb_priv->pinctrl)
> + return -EINVAL;
> +
> + /* Turn off the SD clock first */
> + sdhci_set_clock(host, 0);
> +
> + /* Disable SD DAT0-3 pulls */
> + pinctrl_select_state(brcmstb_priv->pinctrl, brcmstb_priv->pins_sdex);
> +
> + ctrl_val = readl(brcmstb_priv->sde_ioaddr);
> + dev_dbg(dev, "ctrl_val 1 %08x\n", ctrl_val);
> +
> + /* Tri-state the SD pins */
> + ctrl_val |= 0x1ff8;
No magic values please.
> + writel(ctrl_val, brcmstb_priv->sde_ioaddr);
> + dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr));
> + /* Let voltages settle */
> + udelay(100);
Why not usleep_range()?
> +
> + /* Enable the PCIe sideband pins */
> + ctrl_val &= ~0x6000;
No magic values please.
> + writel(ctrl_val, brcmstb_priv->sde_ioaddr);
> + dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr));
> + /* Let voltages settle */
> + udelay(100);
Likewise.
> +
> + /* Turn on the 1v8 VDD2 regulator */
> + ret = regulator_enable(brcmstb_priv->sde_1v8);
> + if (ret)
> + return ret;
> +
> + /* Wait for Tpvcrl */
> + msleep(1);
> +
> + /* Sample DAT2 (CLKREQ#) - if low, card is in PCIe mode */
> + present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
> + present_state = (present_state & SDHCI_DATA_LVL_MASK) >> SDHCI_DATA_LVL_SHIFT;
> + dev_dbg(dev, "state = 0x%08x\n", present_state);
> +
> + if (present_state & BIT(2)) {
Likewise, replace with constant.
> + dev_err(dev, "DAT2 still high, abandoning SDex switch\n");
> + return -ENODEV;
> + }
> +
> + /* Turn on the LCPLL PTEST mux */
> + ctrl_val = readl(brcmstb_priv->sde_ioaddr2 + 20); // misc5
> + ctrl_val &= ~(0x7 << 7);
> + ctrl_val |= 3 << 7;
> + writel(ctrl_val, brcmstb_priv->sde_ioaddr2 + 20);
> + dev_dbg(dev, "misc 5->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2 + 20));
> +
> + /* PTEST diff driver enable */
> + ctrl_val = readl(brcmstb_priv->sde_ioaddr2);
> + ctrl_val |= BIT(21);
> + writel(ctrl_val, brcmstb_priv->sde_ioaddr2);
> +
> + dev_dbg(dev, "misc 0->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2));
> +
> + /* Wait for more than the minimum Tpvpgl time */
> + msleep(100);
> +
> + if (brcmstb_priv->sde_pcie) {
> + struct of_changeset changeset;
> + static struct property okay_property = {
> + .name = "status",
> + .value = "okay",
> + .length = 5,
> + };
> +
> + /* Enable the pcie controller */
> + of_changeset_init(&changeset);
> + ret = of_changeset_update_property(&changeset,
> + brcmstb_priv->sde_pcie,
> + &okay_property);
> + if (ret) {
> + dev_err(dev, "%s: failed to update property - %d\n", __func__,
> + ret);
> + return -ENODEV;
> + }
> + ret = of_changeset_apply(&changeset);
> + }
Why are you doing this? Cannot the firmware enable/disable the node
according to the boot mode or something else?
This is not going to fly for upstream, sorry.
--
Florian
On 4/13/2024 3:14 PM, Andrea della Porta wrote:
> Add a pincontrol driver for BCM2712. BCM2712 allows muxing GPIOs
> and setting configuration on pads.
>
> Originally-by: Jonathan Bell <[email protected]>
> Originally-by: Phil Elwell <[email protected]>
Is that a new tag in a comment message? Signed-off-by maybe?
> Signed-off-by: Andrea della Porta <[email protected]>
> ---
Was not pinctrl-single usable somehow that we had to go through a
dedicated pinctrl driver?
> drivers/pinctrl/bcm/Kconfig | 9 +
> drivers/pinctrl/bcm/Makefile | 1 +
> drivers/pinctrl/bcm/pinctrl-bcm2712.c | 1247 +++++++++++++++++++++++++
> 3 files changed, 1257 insertions(+)
> create mode 100644 drivers/pinctrl/bcm/pinctrl-bcm2712.c
>
> diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig
> index 35b51ce4298e..62ede44460bc 100644
> --- a/drivers/pinctrl/bcm/Kconfig
> +++ b/drivers/pinctrl/bcm/Kconfig
> @@ -3,6 +3,15 @@
> # Broadcom pinctrl drivers
> #
>
> +config PINCTRL_BCM2712
> + bool "Broadcom BCM2712 PINCONF driver"
> + depends on OF && (ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST)
> + select PINMUX
> + select PINCONF
> + select GENERIC_PINCONF
Rename to PINCTRL_BRCMSTB sicne this is not BCM2712 specific at all.
> + help
> + Say Y here to enable the Broadcom BCM2712 PINCONF driver.
> +
> config PINCTRL_BCM281XX
> bool "Broadcom BCM281xx pinctrl driver"
> depends on OF && (ARCH_BCM_MOBILE || COMPILE_TEST)
> diff --git a/drivers/pinctrl/bcm/Makefile b/drivers/pinctrl/bcm/Makefile
> index 82b868ec1471..d298e4785829 100644
> --- a/drivers/pinctrl/bcm/Makefile
> +++ b/drivers/pinctrl/bcm/Makefile
> @@ -1,6 +1,7 @@
> # SPDX-License-Identifier: GPL-2.0
> # Broadcom pinctrl support
>
> +obj-$(CONFIG_PINCTRL_BCM2712) += pinctrl-bcm2712.o
Likewise.
> obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
> obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
> obj-$(CONFIG_PINCTRL_BCM4908) += pinctrl-bcm4908.o
> diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2712.c b/drivers/pinctrl/bcm/pinctrl-bcm2712.c
> new file mode 100644
> index 000000000000..f9359e9eff14
> --- /dev/null
> +++ b/drivers/pinctrl/bcm/pinctrl-bcm2712.c
> @@ -0,0 +1,1247 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Driver for Broadcom BCM2712 GPIO units (pinctrl only)
> + *
> + * Copyright (C) 2021-3 Raspberry Pi Ltd.
> + * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren
> + *
> + * Based heavily on the BCM2835 GPIO & pinctrl driver, which was inspired by:
> + * pinctrl-nomadik.c, please see original file for copyright information
> + * pinctrl-tegra.c, please see original file for copyright information
> + */
> +
> +#include <linux/bitmap.h>
> +#include <linux/bug.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/of_address.h>
> +#include <linux/of.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/pinctrl/machine.h>
> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>
> +#include <linux/pinctrl/pinconf-generic.h>
> +#include <linux/platform_device.h>
> +#include <linux/seq_file.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/types.h>
> +
> +#define MODULE_NAME "pinctrl-bcm2712"
> +
> +/* Register offsets */
> +
> +#define BCM2712_PULL_NONE 0
> +#define BCM2712_PULL_DOWN 1
> +#define BCM2712_PULL_UP 2
> +#define BCM2712_PULL_MASK 0x3
> +
> +#define BCM2712_FSEL_COUNT 9
> +#define BCM2712_FSEL_MASK 0xf
> +
> +#define FUNC(f) \
> + [func_##f] = #f
> +#define PIN(i, f1, f2, f3, f4, f5, f6, f7, f8) \
> + [i] = { \
> + .funcs = { \
> + func_##f1, \
> + func_##f2, \
> + func_##f3, \
> + func_##f4, \
> + func_##f5, \
> + func_##f6, \
> + func_##f7, \
> + func_##f8, \
> + }, \
> + }
> +
> +#define MUX_BIT_VALID 0x8000
> +#define REG_BIT_INVALID 0xffff
> +
> +#define BIT_TO_REG(b) (((b) >> 5) << 2)
> +#define BIT_TO_SHIFT(b) ((b) & 0x1f)
> +
> +#define MUX_BIT(mr, mb) (MUX_BIT_VALID + ((mr)*4)*8 + (mb)*4)
> +#define GPIO_REGS(n, mr, mb, pr, pb) \
> + [n] = { MUX_BIT(mr, mb), ((pr)*4)*8 + (pb)*2 }
> +
> +#define EMMC_REGS(n, pr, pb) \
> + [n] = { 0, ((pr)*4)*8 + (pb)*2 }
> +
> +#define AGPIO_REGS(n, mr, mb, pr, pb) \
> + [n] = { MUX_BIT(mr, mb), ((pr)*4)*8 + (pb)*2 }
> +
> +#define SGPIO_REGS(n, mr, mb) \
> + [n+32] = { MUX_BIT(mr, mb), REG_BIT_INVALID }
> +
> +#define GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
> +#define AGPIO_PIN(a) PINCTRL_PIN(a, "aon_gpio" #a)
> +#define SGPIO_PIN(a) PINCTRL_PIN(a+32, "aon_sgpio" #a)
> +
> +struct pin_regs {
> + u16 mux_bit;
> + u16 pad_bit;
> +};
> +
> +struct bcm2712_pinctrl {
> + struct device *dev;
> + void __iomem *base;
> + struct pinctrl_dev *pctl_dev;
> + struct pinctrl_desc pctl_desc;
> + const struct pin_regs *pin_regs;
> + const struct bcm2712_pin_funcs *pin_funcs;
> + const char *const *gpio_groups;
> + struct pinctrl_gpio_range gpio_range;
> + spinlock_t lock;
> +};
Please s/bcm2712/brcmstb/ throughout the driver's structures and any
declaration that is not inherently 2712 specific and just make 2712 the
first instance using this driver.
> +
> +struct bcm_plat_data {
> + const struct pinctrl_desc *pctl_desc;
> + const struct pinctrl_gpio_range *gpio_range;
> + const struct pin_regs *pin_regs;
> + const struct bcm2712_pin_funcs *pin_funcs;
> +};
> +
> +struct bcm2712_pin_funcs {
> + u8 funcs[BCM2712_FSEL_COUNT - 1];
> +};
> +
[snip]
> +static int bcm2712_pinctrl_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + //struct device_node *np = dev->of_node;
> + const struct bcm_plat_data *pdata;
> + //const struct of_device_id *match;
> + struct bcm2712_pinctrl *pc;
> + const char **names;
> + int num_pins, i;
> +
> + pdata = device_get_match_data(&pdev->dev);
> + if (!pdata)
> + return -EINVAL;
> +
> + pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
> + if (!pc)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, pc);
> + pc->dev = dev;
> + spin_lock_init(&pc->lock);
> +
> + //pc->base = devm_of_iomap(dev, np, 0, NULL);
Remove stray commented lines.
> + pc->base = devm_platform_ioremap_resource(pdev, 0);
> + if (WARN_ON(IS_ERR(pc->base))) {
> + //dev_err(dev, "could not get IO memory\n");
> + return PTR_ERR(pc->base);
> + }
> +
> + pc->pctl_desc = *pdata->pctl_desc;
> + num_pins = pc->pctl_desc.npins;
> + names = devm_kmalloc_array(dev, num_pins, sizeof(const char *),
> + GFP_KERNEL);
> + if (!names)
> + return -ENOMEM;
> + for (i = 0; i < num_pins; i++)
> + names[i] = pc->pctl_desc.pins[i].name;
> + pc->gpio_groups = names;
> + pc->pin_regs = pdata->pin_regs;
> + pc->pin_funcs = pdata->pin_funcs;
> + pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc);
> + if (IS_ERR(pc->pctl_dev))
> + return PTR_ERR(pc->pctl_dev);
> +
> + pc->gpio_range = *pdata->gpio_range;
> + pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
> +
> + return 0;
> +}
> +
> +static struct platform_driver bcm2712_pinctrl_driver = {
> + .probe = bcm2712_pinctrl_probe,
> + .driver = {
> + .name = MODULE_NAME,
> + .of_match_table = bcm2712_pinctrl_match,
> + .suppress_bind_attrs = true,
> + },
> +};
> +builtin_platform_driver(bcm2712_pinctrl_driver);
There is no MODULE_LICENSE(), MODULE_AUTHOR() or MODULE_DESCRIPTION(),
please provide some.
--
Florian
On 4/13/2024 3:14 PM, Andrea della Porta wrote:
> Broadcom BCM2712 SoC has an SDHCI card controller using the SDIO CFG
> register block present on other STB chips. Add support for BCM2712
> SD capabilities of this chipset.
> The silicon is SD Express capable but this driver port does not currently
> include that feature yet.
> Based on downstream driver by raspberry foundation maintained kernel.
>
> Signed-off-by: Andrea della Porta <[email protected]>
> ---
> drivers/mmc/host/sdhci-brcmstb.c | 130 +++++++++++++++++++++++++++++++
> 1 file changed, 130 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
> index 9053526fa212..907a4947abe5 100644
> --- a/drivers/mmc/host/sdhci-brcmstb.c
> +++ b/drivers/mmc/host/sdhci-brcmstb.c
> @@ -12,6 +12,8 @@
> #include <linux/of.h>
> #include <linux/bitops.h>
> #include <linux/delay.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/regulator/consumer.h>
>
> #include "sdhci-cqhci.h"
> #include "sdhci-pltfm.h"
> @@ -30,15 +32,31 @@
>
> #define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
>
> +#define SDIO_CFG_CTRL 0x0
> +#define SDIO_CFG_CTRL_SDCD_N_TEST_EN BIT(31)
> +#define SDIO_CFG_CTRL_SDCD_N_TEST_LEV BIT(30)
> +
> +#define SDIO_CFG_SD_PIN_SEL 0x44
> +#define SDIO_CFG_SD_PIN_SEL_MASK 0x3
> +#define SDIO_CFG_SD_PIN_SEL_SD BIT(1)
> +#define SDIO_CFG_SD_PIN_SEL_MMC BIT(0)
> +
> +#define SDIO_CFG_MAX_50MHZ_MODE 0x1ac
> +#define SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE BIT(31)
> +#define SDIO_CFG_MAX_50MHZ_MODE_ENABLE BIT(0)
> +
> struct sdhci_brcmstb_priv {
> void __iomem *cfg_regs;
> unsigned int flags;
> struct clk *base_clk;
> u32 base_freq_hz;
> + struct pinctrl *pinctrl;
> + struct pinctrl_state *pins_default;
> };
>
> struct brcmstb_match_priv {
> void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
> + void (*cfginit)(struct sdhci_host *host);
> struct sdhci_ops *ops;
> const unsigned int flags;
> };
> @@ -124,6 +142,42 @@ static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios)
> writel(reg, host->ioaddr + SDHCI_VENDOR);
> }
>
> +static void sdhci_bcm2712_set_clock(struct sdhci_host *host, unsigned int clock)
> +{
> + u16 clk;
> + u32 reg;
> + bool is_emmc_rate = false;
> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> + struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
Reverse christmas tree declaration please, longest lines first and
shortest lines next.
> +
> + host->mmc->actual_clock = 0;
> +
> + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
> +
> + switch (host->mmc->ios.timing) {
> + case MMC_TIMING_MMC_HS400:
> + case MMC_TIMING_MMC_HS200:
> + case MMC_TIMING_MMC_DDR52:
> + case MMC_TIMING_MMC_HS:
> + is_emmc_rate = true;
> + break;
Both lines are mis-aligned and requiren an additional tab.
> + }
> +
> + reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
> + reg &= ~SDIO_CFG_SD_PIN_SEL_MASK;
> + if (is_emmc_rate)
> + reg |= SDIO_CFG_SD_PIN_SEL_MMC;
> + else
> + reg |= SDIO_CFG_SD_PIN_SEL_SD;
> + writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
> +
> + if (clock == 0)
> + return;
> +
> + clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
> + sdhci_enable_clk(host, clk);
> +}
> +
> static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock)
> {
> u16 clk;
> @@ -139,6 +193,17 @@ static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock)
> sdhci_enable_clk(host, clk);
> }
>
> +static void sdhci_brcmstb_set_power(struct sdhci_host *host, unsigned char mode,
> + unsigned short vdd)
> +{
> + if (!IS_ERR(host->mmc->supply.vmmc)) {
> + struct mmc_host *mmc = host->mmc;
> +
> + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
> + }
> + sdhci_set_power_noreg(host, mode, vdd);
> +}
> +
> static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host,
> unsigned int timing)
> {
> @@ -168,6 +233,36 @@ static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host,
> sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
> }
>
> +static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
> +{
> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> + struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
> + u32 uhs_mask = (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104);
> + u32 hsemmc_mask = (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS200_1_2V_SDR |
> + MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V);
> + u32 reg;
> +
> + /*
> + * If we support a speed that requires tuning,
> + * then select the delay line PHY as the clock source.
> + */
> + if ((host->mmc->caps & uhs_mask) || (host->mmc->caps2 & hsemmc_mask)) {
> + reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
> + reg &= ~SDIO_CFG_MAX_50MHZ_MODE_ENABLE;
> + reg |= SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE;
> + writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
> + }
> +
> + if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
> + (host->mmc->caps & MMC_CAP_NEEDS_POLL)) {
> + /* Force presence */
> + reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
> + reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV;
> + reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN;
> + writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
> + }
> +}
> +
> static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc)
> {
> sdhci_dumpregs(mmc_priv(mmc));
> @@ -200,6 +295,14 @@ static struct sdhci_ops sdhci_brcmstb_ops = {
> .set_uhs_signaling = sdhci_set_uhs_signaling,
> };
>
> +static struct sdhci_ops sdhci_brcmstb_ops_2712 = {
> + .set_clock = sdhci_bcm2712_set_clock,
> + .set_power = sdhci_brcmstb_set_power,
> + .set_bus_width = sdhci_set_bus_width,
> + .reset = sdhci_reset,
> + .set_uhs_signaling = sdhci_set_uhs_signaling,
> +};
> +
> static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
> .set_clock = sdhci_brcmstb_set_clock,
> .set_bus_width = sdhci_set_bus_width,
> @@ -237,7 +340,13 @@ static struct brcmstb_match_priv match_priv_74165b0 = {
> .ops = &sdhci_brcmstb_ops_74165b0,
> };
>
> +static const struct brcmstb_match_priv match_priv_2712 = {
> + .cfginit = sdhci_brcmstb_cfginit_2712,
> + .ops = &sdhci_brcmstb_ops_2712,
> +};
> +
> static const struct of_device_id __maybe_unused sdhci_brcm_of_match[] = {
> + { .compatible = "brcm,bcm2712-sdhci", .data = &match_priv_2712 },
> { .compatible = "brcm,bcm7425-sdhci", .data = &match_priv_7425 },
> { .compatible = "brcm,bcm7445-sdhci", .data = &match_priv_7445 },
> { .compatible = "brcm,bcm7216-sdhci", .data = &match_priv_7216 },
> @@ -314,11 +423,16 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
> struct sdhci_brcmstb_priv *priv;
> u32 actual_clock_mhz;
> struct sdhci_host *host;
> + bool no_pinctrl = false;
> struct clk *clk;
> struct clk *base_clk = NULL;
> int res;
>
> match = of_match_node(sdhci_brcm_of_match, pdev->dev.of_node);
> + if (!match) {
> + dev_err(&pdev->dev, "fail to get matching of_match struct\n");
> + return -EINVAL;
> + }
> match_priv = match->data;
>
> dev_dbg(&pdev->dev, "Probe found match for %s\n", match->compatible);
> @@ -354,6 +468,19 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
> if (res)
> goto err;
>
> + priv->pinctrl = devm_pinctrl_get(&pdev->dev);
> + if (IS_ERR(priv->pinctrl)) {
> + no_pinctrl = true;
One too many tabs here.
> + }
> + priv->pins_default = pinctrl_lookup_state(priv->pinctrl, "default");
> + if (IS_ERR(priv->pins_default)) {
> + dev_dbg(&pdev->dev, "No pinctrl default state\n");
> + no_pinctrl = true;
One too many tabs here.
Please just run checkpatch on your patches, thanks.
--
Florian
On 4/13/2024 3:14 PM, Andrea della Porta wrote:
> Signed-off-by: Andrea della Porta <[email protected]>
> ---
> .../bindings/mmc/brcm,sdhci-brcmstb.yaml | 51 ++++++++++++++++++-
> 1 file changed, 50 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
> index cbd3d6c6c77f..6aa137d78e4f 100644
> --- a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
> +++ b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
> @@ -13,6 +13,7 @@ maintainers:
> properties:
> compatible:
> oneOf:
> + - const: brcm,bcm2712-sdhci
> - items:
> - enum:
> - brcm,bcm7216-sdhci
> @@ -26,12 +27,16 @@ properties:
> - const: brcm,sdhci-brcmstb
>
> reg:
> - maxItems: 2
> + minItems: 2
> + maxItems: 4
>
> reg-names:
> + minItems: 2
> items:
> - const: host
> - const: cfg
> + - const: busisol
> + - const: lcpll
>
> interrupts:
> maxItems: 1
> @@ -60,6 +65,7 @@ properties:
> description: Specifies that controller should use auto CMD12
>
> allOf:
> + - $ref: sdhci-common.yaml
> - $ref: mmc-controller.yaml#
> - if:
> properties:
> @@ -71,6 +77,28 @@ allOf:
> required:
> - clock-frequency
>
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: brcm,bcm2712-sdhci
> +
> + then:
> + properties:
> + reg:
> + maxItems: 4
> + clock-names:
> + const: "sw_sdio"
> +
> + else:
> + properties:
> + reg:
> + minItems: 2
> + maxItems: 2
> + reg-names:
> + minItems: 2
> + maxItems: 2
> +
> required:
> - compatible
> - reg
> @@ -114,3 +142,24 @@ examples:
> clocks = <&scmi_clk 245>;
> clock-names = "sw_sdio";
> };
> +
> + - |
> + soc {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + mmc@fff000 {
> + compatible = "brcm,bcm2712-sdhci";
> + reg = <0x10 0x00fff000 0x0 0x260>,
> + <0x10 0x00fff400 0x0 0x200>,
> + <0x10 0x015040b0 0x0 0x4>, // Bus isolation control
That should be a syscon, not under direct management of the driver
because there are other bits in that register that are relevant here.
> + <0x10 0x015200f0 0x0 0x24>; // LCPLL control misc0-8
And likewise, this should be a clock provider, or the firmware could add
support for configuring the LCPLL since there are other things going on
there.
--
Florian
On 4/13/2024 3:14 PM, Andrea della Porta wrote:
> Signed-off-by: Andrea della Porta <[email protected]>
No commit message given the amount of lines changed?
Please split this patch into multiple series that add basic 2712 support
to the mainline kernel.
--
Florian
Hi Phil,
Am 14.04.24 um 00:14 schrieb Andrea della Porta:
> Signed-off-by: Andrea della Porta <[email protected]>
> ---
> arch/arm64/boot/dts/broadcom/Makefile | 1 +
> .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 313 +++++++
> arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 81 ++
> arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 841 ++++++++++++++++++
> 4 files changed, 1236 insertions(+)
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712.dtsi
>
> diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile
> index 8b4591ddd27c..92565e9781ad 100644
> --- a/arch/arm64/boot/dts/broadcom/Makefile
> +++ b/arch/arm64/boot/dts/broadcom/Makefile
> @@ -6,6 +6,7 @@ DTC_FLAGS := -@
> dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb \
> bcm2711-rpi-4-b.dtb \
> bcm2711-rpi-cm4-io.dtb \
> + bcm2712-rpi-5-b.dtb \
> bcm2837-rpi-3-a-plus.dtb \
> bcm2837-rpi-3-b.dtb \
> bcm2837-rpi-3-b-plus.dtb \
> diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> new file mode 100644
> index 000000000000..2ce180a54e5b
> --- /dev/null
> +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> @@ -0,0 +1,313 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/dts-v1/;
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/interrupt-controller/irq.h>
> +#include <dt-bindings/pwm/pwm.h>
> +#include <dt-bindings/reset/raspberrypi,firmware-reset.h>
> +
> +#define spi0 _spi0
> +#define uart0 _uart0
> +
> +#include "bcm2712.dtsi"
> +
> +#undef spi0
> +#undef uart0
> +
> +/ {
> + compatible = "raspberrypi,5-model-b", "brcm,bcm2712";
> + model = "Raspberry Pi 5";
> +
>
according to this downstream commit [1] it's just called "Raspberry Pi
5" without Model B, but the filename and the compatible says something
different. Is there still a chance to get this consistent or is it too
late because the firmware expect the compatible?
[1] -
https://github.com/raspberrypi/linux/commit/99e359d2f2da2c820fd2a30b1ad08b32c9549adb
Stefan,
On Mon, 15 Apr 2024 at 09:20, Stefan Wahren <[email protected]> wrote:
>
> Hi Phil,
>
> Am 14.04.24 um 00:14 schrieb Andrea della Porta:
> > Signed-off-by: Andrea della Porta <[email protected]>
> > ---
> > arch/arm64/boot/dts/broadcom/Makefile | 1 +
> > .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 313 +++++++
> > arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 81 ++
> > arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 841 ++++++++++++++++++
> > 4 files changed, 1236 insertions(+)
> > create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> > create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
> > create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> >
> > diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile
> > index 8b4591ddd27c..92565e9781ad 100644
> > --- a/arch/arm64/boot/dts/broadcom/Makefile
> > +++ b/arch/arm64/boot/dts/broadcom/Makefile
> > @@ -6,6 +6,7 @@ DTC_FLAGS := -@
> > dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb \
> > bcm2711-rpi-4-b.dtb \
> > bcm2711-rpi-cm4-io.dtb \
> > + bcm2712-rpi-5-b.dtb \
> > bcm2837-rpi-3-a-plus.dtb \
> > bcm2837-rpi-3-b.dtb \
> > bcm2837-rpi-3-b-plus.dtb \
> > diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> > new file mode 100644
> > index 000000000000..2ce180a54e5b
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> > @@ -0,0 +1,313 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/dts-v1/;
> > +
> > +#include <dt-bindings/gpio/gpio.h>
> > +#include <dt-bindings/interrupt-controller/irq.h>
> > +#include <dt-bindings/pwm/pwm.h>
> > +#include <dt-bindings/reset/raspberrypi,firmware-reset.h>
> > +
> > +#define spi0 _spi0
> > +#define uart0 _uart0
> > +
> > +#include "bcm2712.dtsi"
> > +
> > +#undef spi0
> > +#undef uart0
> > +
> > +/ {
> > + compatible = "raspberrypi,5-model-b", "brcm,bcm2712";
> > + model = "Raspberry Pi 5";
> > +
> >
> according to this downstream commit [1] it's just called "Raspberry Pi
> 5" without Model B, but the filename and the compatible says something
> different. Is there still a chance to get this consistent or is it too
> late because the firmware expect the compatible?
>
> [1] -
> https://github.com/raspberrypi/linux/commit/99e359d2f2da2c820fd2a30b1ad08b32c9549adb
Nothing cares about the compatible string, but the product name was
changed too late for the firmware, which expects the current DTB file
name. I'm happy with the naming as it stands, since we use Pi 4 to
refer to all the BCM2711-based devices, and Pi 5 can include CM5.
Phil
Hi Phil,
Am 15.04.24 um 10:52 schrieb Phil Elwell:
> Stefan,
>
>
> On Mon, 15 Apr 2024 at 09:20, Stefan Wahren <[email protected]> wrote:
>> Hi Phil,
>>
>> Am 14.04.24 um 00:14 schrieb Andrea della Porta:
>>> Signed-off-by: Andrea della Porta <[email protected]>
>>> ---
>>> arch/arm64/boot/dts/broadcom/Makefile | 1 +
>>> .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 313 +++++++
>>> arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 81 ++
>>> arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 841 ++++++++++++++++++
>>> 4 files changed, 1236 insertions(+)
>>> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
>>> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
>>> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712.dtsi
>>>
>>> diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile
>>> index 8b4591ddd27c..92565e9781ad 100644
>>> --- a/arch/arm64/boot/dts/broadcom/Makefile
>>> +++ b/arch/arm64/boot/dts/broadcom/Makefile
>>> @@ -6,6 +6,7 @@ DTC_FLAGS := -@
>>> dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb \
>>> bcm2711-rpi-4-b.dtb \
>>> bcm2711-rpi-cm4-io.dtb \
>>> + bcm2712-rpi-5-b.dtb \
>>> bcm2837-rpi-3-a-plus.dtb \
>>> bcm2837-rpi-3-b.dtb \
>>> bcm2837-rpi-3-b-plus.dtb \
>>> diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
>>> new file mode 100644
>>> index 000000000000..2ce180a54e5b
>>> --- /dev/null
>>> +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
>>> @@ -0,0 +1,313 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/dts-v1/;
>>> +
>>> +#include <dt-bindings/gpio/gpio.h>
>>> +#include <dt-bindings/interrupt-controller/irq.h>
>>> +#include <dt-bindings/pwm/pwm.h>
>>> +#include <dt-bindings/reset/raspberrypi,firmware-reset.h>
>>> +
>>> +#define spi0 _spi0
>>> +#define uart0 _uart0
>>> +
>>> +#include "bcm2712.dtsi"
>>> +
>>> +#undef spi0
>>> +#undef uart0
>>> +
>>> +/ {
>>> + compatible = "raspberrypi,5-model-b", "brcm,bcm2712";
>>> + model = "Raspberry Pi 5";
>>> +
>>>
>> according to this downstream commit [1] it's just called "Raspberry Pi
>> 5" without Model B, but the filename and the compatible says something
>> different. Is there still a chance to get this consistent or is it too
>> late because the firmware expect the compatible?
>>
>> [1] -
>> https://github.com/raspberrypi/linux/commit/99e359d2f2da2c820fd2a30b1ad08b32c9549adb
> Nothing cares about the compatible string, but the product name was
> changed too late for the firmware, which expects the current DTB file
> name.
should i send a pull request to address the compatible? This would avoid
a little bit confusion in the upstreaming process, because
devicetree/bindings/arm/bcm/bcm2835.yaml needs to be updated as well.
Best regards
> I'm happy with the naming as it stands, since we use Pi 4 to
> refer to all the BCM2711-based devices, and Pi 5 can include CM5.
>
> Phil
Stefan,
On Mon, 15 Apr 2024 at 10:06, Stefan Wahren <[email protected]> wrote:
>
> Hi Phil,
>
> Am 15.04.24 um 10:52 schrieb Phil Elwell:
> > Stefan,
> >
> >
> > On Mon, 15 Apr 2024 at 09:20, Stefan Wahren <[email protected]> wrote:
> >> Hi Phil,
> >>
> >> Am 14.04.24 um 00:14 schrieb Andrea della Porta:
> >>> Signed-off-by: Andrea della Porta <[email protected]>
> >>> ---
> >>> arch/arm64/boot/dts/broadcom/Makefile | 1 +
> >>> .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 313 +++++++
> >>> arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 81 ++
> >>> arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 841 ++++++++++++++++++
> >>> 4 files changed, 1236 insertions(+)
> >>> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> >>> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
> >>> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> >>>
> >>> diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile
> >>> index 8b4591ddd27c..92565e9781ad 100644
> >>> --- a/arch/arm64/boot/dts/broadcom/Makefile
> >>> +++ b/arch/arm64/boot/dts/broadcom/Makefile
> >>> @@ -6,6 +6,7 @@ DTC_FLAGS := -@
> >>> dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-400.dtb \
> >>> bcm2711-rpi-4-b.dtb \
> >>> bcm2711-rpi-cm4-io.dtb \
> >>> + bcm2712-rpi-5-b.dtb \
> >>> bcm2837-rpi-3-a-plus.dtb \
> >>> bcm2837-rpi-3-b.dtb \
> >>> bcm2837-rpi-3-b-plus.dtb \
> >>> diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> >>> new file mode 100644
> >>> index 000000000000..2ce180a54e5b
> >>> --- /dev/null
> >>> +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> >>> @@ -0,0 +1,313 @@
> >>> +// SPDX-License-Identifier: GPL-2.0
> >>> +/dts-v1/;
> >>> +
> >>> +#include <dt-bindings/gpio/gpio.h>
> >>> +#include <dt-bindings/interrupt-controller/irq.h>
> >>> +#include <dt-bindings/pwm/pwm.h>
> >>> +#include <dt-bindings/reset/raspberrypi,firmware-reset.h>
> >>> +
> >>> +#define spi0 _spi0
> >>> +#define uart0 _uart0
> >>> +
> >>> +#include "bcm2712.dtsi"
> >>> +
> >>> +#undef spi0
> >>> +#undef uart0
> >>> +
> >>> +/ {
> >>> + compatible = "raspberrypi,5-model-b", "brcm,bcm2712";
> >>> + model = "Raspberry Pi 5";
> >>> +
> >>>
> >> according to this downstream commit [1] it's just called "Raspberry Pi
> >> 5" without Model B, but the filename and the compatible says something
> >> different. Is there still a chance to get this consistent or is it too
> >> late because the firmware expect the compatible?
> >>
> >> [1] -
> >> https://github.com/raspberrypi/linux/commit/99e359d2f2da2c820fd2a30b1ad08b32c9549adb
> > Nothing cares about the compatible string, but the product name was
> > changed too late for the firmware, which expects the current DTB file
> > name.
> should i send a pull request to address the compatible? This would avoid
> a little bit confusion in the upstreaming process, because
> devicetree/bindings/arm/bcm/bcm2835.yaml needs to be updated as well.
You think it is better to have the compatible string different to the
file name, rather than just the human-readable model string being
different? I don't agree.
Phil
On Sun, 14 Apr 2024 00:14:22 +0200, Andrea della Porta wrote:
> Hi,
>
> This patchset adds support for the SDHCI controller on Broadcom BCM2712
> SoC in order to make it possible to boot (particularly) Raspberry Pi 5
> from SD card. This work is heavily based on downstream contributions.
>
> Patch #1 and 2: introduce the dt binding definitions for, respectively,
> the new pin cfg/mux controller and the SD host controller as a preparatory
> step for the upcoming dts.
>
> Patch #3: add a somewhat reasonable (*almost* bare-minimum) dts to be used
> to boot Rpi5 boards. Since till now there was no support at all for any
> 2712 based chipset, both the SoC and board dts plus definitions for the
> new Pin and SD host controller have been added.
>
> Patch #4: the driver supporting the pin controller. Based on [1] and
> successive fix commits.
>
> Patch #5: add SDHCI support. Based on [2] and the next 2 fix commits.
> Drop the SD Express implementation for now, that will be added by patch
> #6.
>
> Patch #6: this patch offers SD Express support and can be considered totally
> optional. The callback plumbing is slightly different w.r.t. the downstream
> approach (see [3]), as explained in the patch comment. Not sure what is the best,
> any comment is highly appreciated.
>
> Tested succesfully on Raspberry Pi 5 using an SDxC card as the boot device.
>
> Still untested:
> - SD Express due to the lack of an Express capable card.
> Also, it will need PCIe support first.
> - card detection pin, since the sd was the booting and root fs device.
>
> Many thanks,
> Andrea
>
> Links:
> [1] - https://github.com/raspberrypi/linux/commit/d9b655314a826724538867bf9b6c229d04c25d84
> [2] - https://github.com/raspberrypi/linux/commit/e3aa070496e840e72a4dc384718690ea4125fa6a
> [3] - https://github.com/raspberrypi/linux/commit/eb1df34db2a9a5b752eba40ee298c4ae87e26e87
>
> Andrea della Porta (6):
> dt-bindings: pinctrl: Add support for BCM2712 pin controller
> dt-bindings: mmc: Add support for BCM2712 SD host controller
> arm64: dts: broadcom: Add support for BCM2712
> pinctrl: bcm: Add pinconf/pinmux controller driver for BCM2712
> mmc: sdhci-brcmstb: Add BCM2712 support
> mmc: sdhci-brcmstb: Add BCM2712 SD Express support
>
> .../bindings/mmc/brcm,sdhci-brcmstb.yaml | 51 +-
> .../pinctrl/brcm,bcm2712-pinctrl.yaml | 99 ++
> arch/arm64/boot/dts/broadcom/Makefile | 1 +
> .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 313 +++++
> arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 81 ++
> arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 841 +++++++++++
> drivers/mmc/host/Kconfig | 1 +
> drivers/mmc/host/sdhci-brcmstb.c | 275 ++++
> drivers/pinctrl/bcm/Kconfig | 9 +
> drivers/pinctrl/bcm/Makefile | 1 +
> drivers/pinctrl/bcm/pinctrl-bcm2712.c | 1247 +++++++++++++++++
> 11 files changed, 2918 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,bcm2712-pinctrl.yaml
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi
> create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712.dtsi
> create mode 100644 drivers/pinctrl/bcm/pinctrl-bcm2712.c
>
> --
> 2.35.3
>
>
>
My bot found new DTB warnings on the .dts files added or changed in this
series.
Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.
If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:
pip3 install dtschema --upgrade
New warnings running 'make CHECK_DTBS=y broadcom/bcm2712-rpi-5-b.dtb' for [email protected]:
arch/arm64/boot/dts/broadcom/bcm2712.dtsi:554.26-565.5: Warning (interrupt_provider): /soc/gpio@7d517c00: '#interrupt-cells' found, but node is not an interrupt provider
also defined at arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts:201.10-206.3
also defined at arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts:259.10-288.3
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: Warning (interrupt_map): Failed prerequisite 'interrupt_provider'
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /: failed to match any schema with compatible: ['raspberrypi,5-model-b', 'brcm,bcm2712']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /: failed to match any schema with compatible: ['raspberrypi,5-model-b', 'brcm,bcm2712']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: thermal-zones: cpu-thermal:trips:phandle: [[43]] is not of type 'object'
from schema $id: http://devicetree.org/schemas/thermal/thermal-zones.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: soc: firmware: {'compatible': ['raspberrypi,bcm2835-firmware', 'simple-mfd'], '#address-cells': [[1]], '#size-cells': [[1]], 'mboxes': [[15]], 'dma-ranges': True, 'phandle': [[16]], 'clocks': {'compatible': ['raspberrypi,firmware-clocks'], '#clock-cells': [[1]], 'phandle': [[95]]}, 'reset': {'compatible': ['raspberrypi,firmware-reset'], '#reset-cells': [[1]], 'phandle': [[96]]}} should not be valid under {'type': 'object'}
from schema $id: http://devicetree.org/schemas/simple-bus.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: soc: power: {'compatible': ['raspberrypi,bcm2835-power'], 'firmware': [[16]], '#power-domain-cells': [[1]], 'phandle': [[97]]} should not be valid under {'type': 'object'}
from schema $id: http://devicetree.org/schemas/simple-bus.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: soc: fixedregulator_3v3: {'compatible': ['regulator-fixed'], 'regulator-always-on': True, 'regulator-max-microvolt': [[3300000]], 'regulator-min-microvolt': [[3300000]], 'regulator-name': ['3v3'], 'phandle': [[98]]} should not be valid under {'type': 'object'}
from schema $id: http://devicetree.org/schemas/simple-bus.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: soc: fixedregulator_5v0: {'compatible': ['regulator-fixed'], 'regulator-always-on': True, 'regulator-max-microvolt': [[5000000]], 'regulator-min-microvolt': [[5000000]], 'regulator-name': ['5v0'], 'phandle': [[99]]} should not be valid under {'type': 'object'}
from schema $id: http://devicetree.org/schemas/simple-bus.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/timer@7c003000: failed to match any schema with compatible: ['brcm,bcm2835-system-timer']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/local_intc@7cd00000: failed to match any schema with compatible: ['brcm,bcm2836-l1-intc']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/i2s@7d003000: failed to match any schema with compatible: ['brcm,bcm2835-i2s']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/spi@7d004000: failed to match any schema with compatible: ['brcm,bcm2835-spi']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/spi@7d004000/spidev@0: failed to match any schema with compatible: ['spidev']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/spi@7d004600: failed to match any schema with compatible: ['brcm,bcm2835-spi']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/spi@7d004800: failed to match any schema with compatible: ['brcm,bcm2835-spi']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/spi@7d004a00: failed to match any schema with compatible: ['brcm,bcm2835-spi']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/spi@7d004c00: failed to match any schema with compatible: ['brcm,bcm2835-spi']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: pwm@7d00c000: 'assigned-clocks' is a dependency of 'assigned-clock-rates'
from schema $id: http://devicetree.org/schemas/clock/clock.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: pwm@7d00c800: 'assigned-clocks' is a dependency of 'assigned-clock-rates'
from schema $id: http://devicetree.org/schemas/clock/clock.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/cprman@7d202000: failed to match any schema with compatible: ['brcm,bcm2711-cprman']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: intc@7d503000: $nodename:0: 'intc@7d503000' does not match '^interrupt-controller(@[0-9a-f,]+)*$'
from schema $id: http://devicetree.org/schemas/interrupt-controller/brcm,l2-intc.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: intc@7d508380: $nodename:0: 'intc@7d508380' does not match '^interrupt-controller(@[0-9a-f,]+)*$'
from schema $id: http://devicetree.org/schemas/interrupt-controller/brcm,l2-intc.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: intc@7d508400: $nodename:0: 'intc@7d508400' does not match '^interrupt-controller(@[0-9a-f,]+)*$'
from schema $id: http://devicetree.org/schemas/interrupt-controller/brcm,l2-intc.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: gpio@7d508500: compatible:0: 'brcm,brcmstb-gpio' is not one of ['brcm,bcm7445-gpio']
from schema $id: http://devicetree.org/schemas/gpio/brcm,brcmstb-gpio.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: gpio@7d508500: compatible: ['brcm,brcmstb-gpio'] is too short
from schema $id: http://devicetree.org/schemas/gpio/brcm,brcmstb-gpio.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: gpio@7d508500: 'brcm,gpio-direct', 'gpio-line-names' do not match any of the regexes: 'pinctrl-[0-9]+'
from schema $id: http://devicetree.org/schemas/gpio/brcm,brcmstb-gpio.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: intc@7d517000: $nodename:0: 'intc@7d517000' does not match '^interrupt-controller(@[0-9a-f,]+)*$'
from schema $id: http://devicetree.org/schemas/interrupt-controller/brcm,l2-intc.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: pwm@7d517a80: #pwm-cells:0:0: 2 was expected
from schema $id: http://devicetree.org/schemas/pwm/brcm,bcm7038-pwm.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: intc@7d517ac0: $nodename:0: 'intc@7d517ac0' does not match '^interrupt-controller(@[0-9a-f,]+)*$'
from schema $id: http://devicetree.org/schemas/interrupt-controller/brcm,l2-intc.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: intc@7d517b00: $nodename:0: 'intc@7d517b00' does not match '^interrupt-controller(@[0-9a-f,]+)*$'
from schema $id: http://devicetree.org/schemas/interrupt-controller/brcm,l2-intc.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: gpio@7d517c00: compatible:0: 'brcm,brcmstb-gpio' is not one of ['brcm,bcm7445-gpio']
from schema $id: http://devicetree.org/schemas/gpio/brcm,brcmstb-gpio.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: gpio@7d517c00: compatible: ['brcm,brcmstb-gpio'] is too short
from schema $id: http://devicetree.org/schemas/gpio/brcm,brcmstb-gpio.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: gpio@7d517c00: 'brcm,gpio-direct', 'gpio-line-names' do not match any of the regexes: 'pinctrl-[0-9]+'
from schema $id: http://devicetree.org/schemas/gpio/brcm,brcmstb-gpio.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/avs-monitor@7d542000: failed to match any schema with compatible: ['brcm,bcm2711-avs-monitor', 'syscon', 'simple-mfd']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: firmware: '#address-cells', '#size-cells', 'dma-ranges' do not match any of the regexes: 'pinctrl-[0-9]+'
from schema $id: http://devicetree.org/schemas/arm/bcm/raspberrypi,bcm2835-firmware.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: /soc/power: failed to match any schema with compatible: ['raspberrypi,bcm2835-power']
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: l3-cache: 'cache-unified' is a dependency of 'cache-size'
from schema $id: http://devicetree.org/schemas/cache.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: l3-cache: 'cache-unified' is a dependency of 'cache-sets'
from schema $id: http://devicetree.org/schemas/cache.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: l3-cache: 'cache-unified' is a dependency of 'cache-line-size'
from schema $id: http://devicetree.org/schemas/cache.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: l3-cache: 'cache-unified' is a required property
from schema $id: http://devicetree.org/schemas/cache.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: l3-cache: Unevaluated properties are not allowed ('cache-level', 'cache-line-size', 'cache-sets', 'cache-size' were unexpected)
from schema $id: http://devicetree.org/schemas/cache.yaml#
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb: pwr_button: 'pwr' does not match any of the regexes: '^(button|event|key|switch|(button|event|key|switch)-[a-z0-9-]+|[a-z0-9-]+-(button|event|key|switch))$', 'pinctrl-[0-9]+'
from schema $id: http://devicetree.org/schemas/input/gpio-keys.yaml#
Hi Andrea,
thanks for your patch!
Some comments apart from was said already.
On Sun, Apr 14, 2024 at 12:14 AM Andrea della Porta
<[email protected]> wrote:
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/pinctrl/machine.h>
Really? Why?
> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>
> +#include <linux/pinctrl/pinconf-generic.h>
I would just expect these.
> +static int bcm2712_pinctrl_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + //struct device_node *np = dev->of_node;
> + const struct bcm_plat_data *pdata;
> + //const struct of_device_id *match;
I don't know if others commented on it but drop all commented-out code
or make use of it.
Yours,
Linus Walleij
On 09:01 Sun 14 Apr , Florian Fainelli wrote:
>
>
> On 4/13/2024 3:14 PM, Andrea della Porta wrote:
> > Signed-off-by: Andrea della Porta <[email protected]>
>
> No commit message given the amount of lines changed?
Ack. Patchset V2 will have a commit message.
>
> Please split this patch into multiple series that add basic 2712 support to
> the mainline kernel.
Please, can you elaborate a bit further on this?
Many thanks,
Andrea
> --
> Florian
On 09:19 Sun 14 Apr , Christophe JAILLET wrote:
> Le 14/04/2024 ? 00:14, Andrea della Porta a ?crit?:
> > Add a pincontrol driver for BCM2712. BCM2712 allows muxing GPIOs
> > and setting configuration on pads.
> >
> > Originally-by: Jonathan Bell <[email protected]>
> > Originally-by: Phil Elwell <[email protected]>
> > Signed-off-by: Andrea della Porta <[email protected]>
> > ---
> > drivers/pinctrl/bcm/Kconfig | 9 +
> > drivers/pinctrl/bcm/Makefile | 1 +
> > drivers/pinctrl/bcm/pinctrl-bcm2712.c | 1247 +++++++++++++++++++++++++
> > 3 files changed, 1257 insertions(+)
> > create mode 100644 drivers/pinctrl/bcm/pinctrl-bcm2712.c
>
> ...
>
> > +static int bcm2712_pmx_get_function_groups(struct pinctrl_dev *pctldev,
> > + unsigned selector,
> > + const char * const **groups,
> > + unsigned * const num_groups)
> > +{
> > + struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
>
> Missing empty new line.
>
> > + /* every pin can do every function */
> > + *groups = pc->gpio_groups;
> > + *num_groups = pc->pctl_desc.npins;
> > +
> > + return 0;
> > +}
>
> ...
>
> > +static int bcm2712_pinconf_get(struct pinctrl_dev *pctldev,
> > + unsigned pin, unsigned long *config)
> > +{
> > + struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
> > + enum pin_config_param param = pinconf_to_config_param(*config);
> > + u32 arg;
> > +
> > + switch (param) {
> > + case PIN_CONFIG_BIAS_DISABLE:
> > + arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_NONE);
> > + break;
> > + case PIN_CONFIG_BIAS_PULL_DOWN:
> > + arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_DOWN);
> > + break;
> > + case PIN_CONFIG_BIAS_PULL_UP:
> > + arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_UP);
> > + break;
> > + default:
> > + return -ENOTSUPP;
> > + }
> > +
> > + *config = pinconf_to_config_packed(param, arg);
> > +
> > + return -ENOTSUPP;
>
> Strange.
>
> return 0;
> ?
>
> > +}
> > +
> > +static int bcm2712_pinconf_set(struct pinctrl_dev *pctldev,
> > + unsigned int pin, unsigned long *configs,
> > + unsigned int num_configs)
> > +{
> > + struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
> > + u32 param, arg;
> > + int i;
> > +
> > + for (i = 0; i < num_configs; i++) {
> > + param = pinconf_to_config_param(configs[i]);
> > + arg = pinconf_to_config_argument(configs[i]);
> > +
> > + switch (param) {
> > + case PIN_CONFIG_BIAS_DISABLE:
> > + bcm2712_pull_config_set(pc, pin, BCM2712_PULL_NONE);
> > + break;
> > + case PIN_CONFIG_BIAS_PULL_DOWN:
> > + bcm2712_pull_config_set(pc, pin, BCM2712_PULL_DOWN);
> > + break;
> > + case PIN_CONFIG_BIAS_PULL_UP:
> > + bcm2712_pull_config_set(pc, pin, BCM2712_PULL_UP);
> > + break;
> > + default:
> > + return -ENOTSUPP;
> > + }
> > + } /* for each config */
>
> This comment is not really usefull, IMHO.
Agreed. Dropped in V2.
>
> > +
> > + return 0;
> > +}
>
> ...
>
> > +static int bcm2712_pinctrl_probe(struct platform_device *pdev)
> > +{
> > + struct device *dev = &pdev->dev;
> > + //struct device_node *np = dev->of_node;
> > + const struct bcm_plat_data *pdata;
> > + //const struct of_device_id *match;
> > + struct bcm2712_pinctrl *pc;
> > + const char **names;
> > + int num_pins, i;
> > +
> > + pdata = device_get_match_data(&pdev->dev);
> > + if (!pdata)
> > + return -EINVAL;
> > +
> > + pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
> > + if (!pc)
> > + return -ENOMEM;
> > +
> > + platform_set_drvdata(pdev, pc);
> > + pc->dev = dev;
> > + spin_lock_init(&pc->lock);
> > +
> > + //pc->base = devm_of_iomap(dev, np, 0, NULL);
>
> Any use for this commented code? (and variable declarations above)
No, I just forgot to drop the comment. Removed in V2.
Many thanks,
Andrea
>
> CJ
>
> > + pc->base = devm_platform_ioremap_resource(pdev, 0);
> > + if (WARN_ON(IS_ERR(pc->base))) {
> > + //dev_err(dev, "could not get IO memory\n");
> > + return PTR_ERR(pc->base);
> > + }
> > +
> > + pc->pctl_desc = *pdata->pctl_desc;
> > + num_pins = pc->pctl_desc.npins;
> > + names = devm_kmalloc_array(dev, num_pins, sizeof(const char *),
> > + GFP_KERNEL);
> > + if (!names)
> > + return -ENOMEM;
> > + for (i = 0; i < num_pins; i++)
> > + names[i] = pc->pctl_desc.pins[i].name;
> > + pc->gpio_groups = names;
> > + pc->pin_regs = pdata->pin_regs;
> > + pc->pin_funcs = pdata->pin_funcs;
> > + pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc);
> > + if (IS_ERR(pc->pctl_dev))
> > + return PTR_ERR(pc->pctl_dev);
> > +
> > + pc->gpio_range = *pdata->gpio_range;
> > + pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
> > +
> > + return 0;
> > +}
>
> ...
>
On 09:00 Sun 14 Apr , Florian Fainelli wrote:
>
>
> On 4/13/2024 3:14 PM, Andrea della Porta wrote:
> > Add a pincontrol driver for BCM2712. BCM2712 allows muxing GPIOs
> > and setting configuration on pads.
> >
> > Originally-by: Jonathan Bell <[email protected]>
> > Originally-by: Phil Elwell <[email protected]>
>
> Is that a new tag in a comment message? Signed-off-by maybe?
>
> > Signed-off-by: Andrea della Porta <[email protected]>
> > ---
>
> Was not pinctrl-single usable somehow that we had to go through a dedicated
> pinctrl driver?
>
I'm taking a look on this. In V2 though, the pin controller will not be
present since it's not strictly necessary tobe able to boot from sd card.
> > drivers/pinctrl/bcm/Kconfig | 9 +
> > drivers/pinctrl/bcm/Makefile | 1 +
> > drivers/pinctrl/bcm/pinctrl-bcm2712.c | 1247 +++++++++++++++++++++++++
> > 3 files changed, 1257 insertions(+)
> > create mode 100644 drivers/pinctrl/bcm/pinctrl-bcm2712.c
> >
> > diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig
> > index 35b51ce4298e..62ede44460bc 100644
> > --- a/drivers/pinctrl/bcm/Kconfig
> > +++ b/drivers/pinctrl/bcm/Kconfig
> > @@ -3,6 +3,15 @@
> > # Broadcom pinctrl drivers
> > #
> > +config PINCTRL_BCM2712
> > + bool "Broadcom BCM2712 PINCONF driver"
> > + depends on OF && (ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST)
> > + select PINMUX
> > + select PINCONF
> > + select GENERIC_PINCONF
>
> Rename to PINCTRL_BRCMSTB sicne this is not BCM2712 specific at all.
>
> > + help
> > + Say Y here to enable the Broadcom BCM2712 PINCONF driver.
> > +
> > config PINCTRL_BCM281XX
> > bool "Broadcom BCM281xx pinctrl driver"
> > depends on OF && (ARCH_BCM_MOBILE || COMPILE_TEST)
> > diff --git a/drivers/pinctrl/bcm/Makefile b/drivers/pinctrl/bcm/Makefile
> > index 82b868ec1471..d298e4785829 100644
> > --- a/drivers/pinctrl/bcm/Makefile
> > +++ b/drivers/pinctrl/bcm/Makefile
> > @@ -1,6 +1,7 @@
> > # SPDX-License-Identifier: GPL-2.0
> > # Broadcom pinctrl support
> > +obj-$(CONFIG_PINCTRL_BCM2712) += pinctrl-bcm2712.o
>
> Likewise.
>
> > obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
> > obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
> > obj-$(CONFIG_PINCTRL_BCM4908) += pinctrl-bcm4908.o
> > diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2712.c b/drivers/pinctrl/bcm/pinctrl-bcm2712.c
> > new file mode 100644
> > index 000000000000..f9359e9eff14
> > --- /dev/null
> > +++ b/drivers/pinctrl/bcm/pinctrl-bcm2712.c
> > @@ -0,0 +1,1247 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Driver for Broadcom BCM2712 GPIO units (pinctrl only)
> > + *
> > + * Copyright (C) 2021-3 Raspberry Pi Ltd.
> > + * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren
> > + *
> > + * Based heavily on the BCM2835 GPIO & pinctrl driver, which was inspired by:
> > + * pinctrl-nomadik.c, please see original file for copyright information
> > + * pinctrl-tegra.c, please see original file for copyright information
> > + */
> > +
> > +#include <linux/bitmap.h>
> > +#include <linux/bug.h>
> > +#include <linux/delay.h>
> > +#include <linux/device.h>
> > +#include <linux/err.h>
> > +#include <linux/io.h>
> > +#include <linux/init.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of.h>
> > +#include <linux/pinctrl/consumer.h>
> > +#include <linux/pinctrl/machine.h>
> > +#include <linux/pinctrl/pinconf.h>
> > +#include <linux/pinctrl/pinctrl.h>
> > +#include <linux/pinctrl/pinmux.h>
> > +#include <linux/pinctrl/pinconf-generic.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/seq_file.h>
> > +#include <linux/slab.h>
> > +#include <linux/spinlock.h>
> > +#include <linux/types.h>
> > +
> > +#define MODULE_NAME "pinctrl-bcm2712"
> > +
> > +/* Register offsets */
> > +
> > +#define BCM2712_PULL_NONE 0
> > +#define BCM2712_PULL_DOWN 1
> > +#define BCM2712_PULL_UP 2
> > +#define BCM2712_PULL_MASK 0x3
> > +
> > +#define BCM2712_FSEL_COUNT 9
> > +#define BCM2712_FSEL_MASK 0xf
> > +
> > +#define FUNC(f) \
> > + [func_##f] = #f
> > +#define PIN(i, f1, f2, f3, f4, f5, f6, f7, f8) \
> > + [i] = { \
> > + .funcs = { \
> > + func_##f1, \
> > + func_##f2, \
> > + func_##f3, \
> > + func_##f4, \
> > + func_##f5, \
> > + func_##f6, \
> > + func_##f7, \
> > + func_##f8, \
> > + }, \
> > + }
> > +
> > +#define MUX_BIT_VALID 0x8000
> > +#define REG_BIT_INVALID 0xffff
> > +
> > +#define BIT_TO_REG(b) (((b) >> 5) << 2)
> > +#define BIT_TO_SHIFT(b) ((b) & 0x1f)
> > +
> > +#define MUX_BIT(mr, mb) (MUX_BIT_VALID + ((mr)*4)*8 + (mb)*4)
> > +#define GPIO_REGS(n, mr, mb, pr, pb) \
> > + [n] = { MUX_BIT(mr, mb), ((pr)*4)*8 + (pb)*2 }
> > +
> > +#define EMMC_REGS(n, pr, pb) \
> > + [n] = { 0, ((pr)*4)*8 + (pb)*2 }
> > +
> > +#define AGPIO_REGS(n, mr, mb, pr, pb) \
> > + [n] = { MUX_BIT(mr, mb), ((pr)*4)*8 + (pb)*2 }
> > +
> > +#define SGPIO_REGS(n, mr, mb) \
> > + [n+32] = { MUX_BIT(mr, mb), REG_BIT_INVALID }
> > +
> > +#define GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
> > +#define AGPIO_PIN(a) PINCTRL_PIN(a, "aon_gpio" #a)
> > +#define SGPIO_PIN(a) PINCTRL_PIN(a+32, "aon_sgpio" #a)
> > +
> > +struct pin_regs {
> > + u16 mux_bit;
> > + u16 pad_bit;
> > +};
> > +
> > +struct bcm2712_pinctrl {
> > + struct device *dev;
> > + void __iomem *base;
> > + struct pinctrl_dev *pctl_dev;
> > + struct pinctrl_desc pctl_desc;
> > + const struct pin_regs *pin_regs;
> > + const struct bcm2712_pin_funcs *pin_funcs;
> > + const char *const *gpio_groups;
> > + struct pinctrl_gpio_range gpio_range;
> > + spinlock_t lock;
> > +};
>
> Please s/bcm2712/brcmstb/ throughout the driver's structures and any
> declaration that is not inherently 2712 specific and just make 2712 the
> first instance using this driver.
>
> > +
> > +struct bcm_plat_data {
> > + const struct pinctrl_desc *pctl_desc;
> > + const struct pinctrl_gpio_range *gpio_range;
> > + const struct pin_regs *pin_regs;
> > + const struct bcm2712_pin_funcs *pin_funcs;
> > +};
> > +
> > +struct bcm2712_pin_funcs {
> > + u8 funcs[BCM2712_FSEL_COUNT - 1];
> > +};
> > +
>
> [snip]
>
> > +static int bcm2712_pinctrl_probe(struct platform_device *pdev)
> > +{
> > + struct device *dev = &pdev->dev;
> > + //struct device_node *np = dev->of_node;
> > + const struct bcm_plat_data *pdata;
> > + //const struct of_device_id *match;
> > + struct bcm2712_pinctrl *pc;
> > + const char **names;
> > + int num_pins, i;
> > +
> > + pdata = device_get_match_data(&pdev->dev);
> > + if (!pdata)
> > + return -EINVAL;
> > +
> > + pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
> > + if (!pc)
> > + return -ENOMEM;
> > +
> > + platform_set_drvdata(pdev, pc);
> > + pc->dev = dev;
> > + spin_lock_init(&pc->lock);
> > +
> > + //pc->base = devm_of_iomap(dev, np, 0, NULL);
>
> Remove stray commented lines.
>
> > + pc->base = devm_platform_ioremap_resource(pdev, 0);
> > + if (WARN_ON(IS_ERR(pc->base))) {
> > + //dev_err(dev, "could not get IO memory\n");
> > + return PTR_ERR(pc->base);
> > + }
> > +
> > + pc->pctl_desc = *pdata->pctl_desc;
> > + num_pins = pc->pctl_desc.npins;
> > + names = devm_kmalloc_array(dev, num_pins, sizeof(const char *),
> > + GFP_KERNEL);
> > + if (!names)
> > + return -ENOMEM;
> > + for (i = 0; i < num_pins; i++)
> > + names[i] = pc->pctl_desc.pins[i].name;
> > + pc->gpio_groups = names;
> > + pc->pin_regs = pdata->pin_regs;
> > + pc->pin_funcs = pdata->pin_funcs;
> > + pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc);
> > + if (IS_ERR(pc->pctl_dev))
> > + return PTR_ERR(pc->pctl_dev);
> > +
> > + pc->gpio_range = *pdata->gpio_range;
> > + pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
> > +
> > + return 0;
> > +}
> > +
> > +static struct platform_driver bcm2712_pinctrl_driver = {
> > + .probe = bcm2712_pinctrl_probe,
> > + .driver = {
> > + .name = MODULE_NAME,
> > + .of_match_table = bcm2712_pinctrl_match,
> > + .suppress_bind_attrs = true,
> > + },
> > +};
> > +builtin_platform_driver(bcm2712_pinctrl_driver);
>
> There is no MODULE_LICENSE(), MODULE_AUTHOR() or MODULE_DESCRIPTION(),
> please provide some.
> --
> Florian
On 15:07 Tue 16 Apr , Linus Walleij wrote:
> Hi Andrea,
>
> thanks for your patch!
>
> Some comments apart from was said already.
>
> On Sun, Apr 14, 2024 at 12:14 AM Andrea della Porta
> <[email protected]> wrote:
>
> > +#include <linux/pinctrl/consumer.h>
> > +#include <linux/pinctrl/machine.h>
>
> Really? Why?
>
> > +#include <linux/pinctrl/pinconf.h>
> > +#include <linux/pinctrl/pinctrl.h>
> > +#include <linux/pinctrl/pinmux.h>
> > +#include <linux/pinctrl/pinconf-generic.h>
>
> I would just expect these.
>
> > +static int bcm2712_pinctrl_probe(struct platform_device *pdev)
> > +{
> > + struct device *dev = &pdev->dev;
> > + //struct device_node *np = dev->of_node;
> > + const struct bcm_plat_data *pdata;
> > + //const struct of_device_id *match;
>
> I don't know if others commented on it but drop all commented-out code
> or make use of it.
Forgot to remove those lines. Will ve dropped in a future patch since
the pin controller driver will not be included in V2 since it's not
strictly needed to support SD boot.
Many thanks,
Andrea
>
> Yours,
> Linus Walleij
On 09:34 Sun 14 Apr , Christophe JAILLET wrote:
> Le 14/04/2024 ? 00:14, Andrea della Porta a ?crit?:
> > Broadcom BCM2712 SDHCI controller is SD Express capable. Add support
> > for sde capability where the implementation is based on downstream driver,
> > diverging from it in the way that init_sd_express callback is invoked:
> > in downstream the sdhci_ops structure has been augmented with a new
> > function ptr 'init_sd_express' that just propagate the call to the
> > driver specific callback so that the callstack from a structure
> > standpoint is mmc_host_ops -> sdhci_ops. The drawback here is in the
> > added level of indirection (the newly added init_sd_express is
> > redundant) and the sdhci_ops structure declaration has to be changed.
> > To overcome this the presented approach consist in patching the mmc_host_ops
> > init_sd_express callback to point directly to the custom function defined in
> > this driver (see struct brcmstb_match_priv).
> >
> > Signed-off-by: Andrea della Porta <andrea.porta-IBi9RG/[email protected]>
> > ---
> > drivers/mmc/host/Kconfig | 1 +
> > drivers/mmc/host/sdhci-brcmstb.c | 147 ++++++++++++++++++++++++++++++-
> > 2 files changed, 147 insertions(+), 1 deletion(-)
>
> ...
>
> > + if (brcmstb_priv->sde_pcie) {
> > + struct of_changeset changeset;
> > + static struct property okay_property = {
> > + .name = "status",
> > + .value = "okay",
> > + .length = 5,
> > + };
> > +
> > + /* Enable the pcie controller */
> > + of_changeset_init(&changeset);
> > + ret = of_changeset_update_property(&changeset,
> > + brcmstb_priv->sde_pcie,
> > + &okay_property);
> > + if (ret) {
> > + dev_err(dev, "%s: failed to update property - %d\n", __func__,
> > + ret);
> > + return -ENODEV;
> > + }
> > + ret = of_changeset_apply(&changeset);
> > + }
> > +
> > + dev_dbg(dev, "%s -> %d\n", __func__, ret);
>
> Is this really useful?
Not really. Removed.
>
> > + return ret;
> > +}
> > +
>
> ...
>
> > @@ -468,6 +581,24 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
> > if (res)
> > goto err;
> > + priv->sde_1v8 = devm_regulator_get_optional(&pdev->dev, "sde-1v8");
> > + if (IS_ERR(priv->sde_1v8))
> > + priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS;
> > +
> > + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 2);
> > + if (iomem) {
> > + priv->sde_ioaddr = devm_ioremap_resource(&pdev->dev, iomem);
> > + if (IS_ERR(priv->sde_ioaddr))
> > + priv->sde_ioaddr = NULL;
> > + }
> > +
> > + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 3);
> > + if (iomem) {
> > + priv->sde_ioaddr2 = devm_ioremap_resource(&pdev->dev, iomem);
> > + if (IS_ERR(priv->sde_ioaddr2))
> > + priv->sde_ioaddr = NULL;
>
> sde_ioaddr2 ?
>
> > + }
> > +
> > priv->pinctrl = devm_pinctrl_get(&pdev->dev);
> > if (IS_ERR(priv->pinctrl)) {
> > no_pinctrl = true;
> > @@ -478,8 +609,16 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
> > no_pinctrl = true;
> > }
> > - if (no_pinctrl )
> > + priv->pins_sdex = pinctrl_lookup_state(priv->pinctrl, "sd-express");
> > + if (IS_ERR(priv->pins_sdex)) {
> > + dev_dbg(&pdev->dev, "No pinctrl sd-express state\n");
> > + no_pinctrl = true;
>
> Indentation looks too large.
Ack.
>
> > + }
> > +
> > + if (no_pinctrl || !priv->sde_ioaddr || !priv->sde_ioaddr2) {
> > priv->pinctrl = NULL;
> > + priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS;
> > + }
> > /*
> > * Automatic clock gating does not work for SD cards that may
>
> ...
>
In general I'll drop SD express patch for now, it will be re-introduced in a future patch.
Best regards,
Andrea
On 08:55 Sun 14 Apr , Florian Fainelli wrote:
>
>
> On 4/13/2024 3:14 PM, Andrea della Porta wrote:
> > Broadcom BCM2712 SDHCI controller is SD Express capable. Add support
> > for sde capability where the implementation is based on downstream driver,
> > diverging from it in the way that init_sd_express callback is invoked:
> > in downstream the sdhci_ops structure has been augmented with a new
> > function ptr 'init_sd_express' that just propagate the call to the
> > driver specific callback so that the callstack from a structure
> > standpoint is mmc_host_ops -> sdhci_ops. The drawback here is in the
> > added level of indirection (the newly added init_sd_express is
> > redundant) and the sdhci_ops structure declaration has to be changed.
> > To overcome this the presented approach consist in patching the mmc_host_ops
> > init_sd_express callback to point directly to the custom function defined in
> > this driver (see struct brcmstb_match_priv).
> >
> > Signed-off-by: Andrea della Porta <[email protected]>
> > ---
> > drivers/mmc/host/Kconfig | 1 +
> > drivers/mmc/host/sdhci-brcmstb.c | 147 ++++++++++++++++++++++++++++++-
> > 2 files changed, 147 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> > index aebc587f77a7..343ccac1a4e4 100644
> > --- a/drivers/mmc/host/Kconfig
> > +++ b/drivers/mmc/host/Kconfig
> > @@ -1018,6 +1018,7 @@ config MMC_SDHCI_BRCMSTB
> > depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
> > depends on MMC_SDHCI_PLTFM
> > select MMC_CQHCI
> > + select OF_DYNAMIC
> > default ARCH_BRCMSTB || BMIPS_GENERIC
> > help
> > This selects support for the SDIO/SD/MMC Host Controller on
> > diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
> > index 907a4947abe5..56fb34a75ec2 100644
> > --- a/drivers/mmc/host/sdhci-brcmstb.c
> > +++ b/drivers/mmc/host/sdhci-brcmstb.c
> > @@ -29,6 +29,7 @@
> > #define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0)
> > #define BRCMSTB_PRIV_FLAGS_GATE_CLOCK BIT(1)
> > +#define BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS BIT(2)
> > #define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
> > @@ -50,13 +51,19 @@ struct sdhci_brcmstb_priv {
> > unsigned int flags;
> > struct clk *base_clk;
> > u32 base_freq_hz;
> > + struct regulator *sde_1v8;
> > + struct device_node *sde_pcie;
> > + void *__iomem sde_ioaddr;
> > + void *__iomem sde_ioaddr2;
> > struct pinctrl *pinctrl;
> > struct pinctrl_state *pins_default;
> > + struct pinctrl_state *pins_sdex;
> > };
> > struct brcmstb_match_priv {
> > void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
> > void (*cfginit)(struct sdhci_host *host);
> > + int (*init_sd_express)(struct mmc_host *mmc, struct mmc_ios *ios);
> > struct sdhci_ops *ops;
> > const unsigned int flags;
> > };
> > @@ -263,6 +270,105 @@ static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
> > }
> > }
> > +static int bcm2712_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
> > +{
> > + struct sdhci_host *host = mmc_priv(mmc);
> > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > + struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
> > + struct device *dev = host->mmc->parent;
> > + u32 ctrl_val;
> > + u32 present_state;
> > + int ret;
> > +
> > + if (!brcmstb_priv->sde_ioaddr || !brcmstb_priv->sde_ioaddr2)
> > + return -EINVAL;
> > +
> > + if (!brcmstb_priv->pinctrl)
> > + return -EINVAL;
> > +
> > + /* Turn off the SD clock first */
> > + sdhci_set_clock(host, 0);
> > +
> > + /* Disable SD DAT0-3 pulls */
> > + pinctrl_select_state(brcmstb_priv->pinctrl, brcmstb_priv->pins_sdex);
> > +
> > + ctrl_val = readl(brcmstb_priv->sde_ioaddr);
> > + dev_dbg(dev, "ctrl_val 1 %08x\n", ctrl_val);
> > +
> > + /* Tri-state the SD pins */
> > + ctrl_val |= 0x1ff8;
>
> No magic values please.
Ack.
>
> > + writel(ctrl_val, brcmstb_priv->sde_ioaddr);
> > + dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr));
> > + /* Let voltages settle */
> > + udelay(100);
>
> Why not usleep_range()?
No real reason. I assume only the lower boundary is critical so I can use usleep_range instead.
Will be fixed in a future patch, the SD express support will be drpped in V2 since nto strictly
necessary.
>
> > +
> > + /* Enable the PCIe sideband pins */
> > + ctrl_val &= ~0x6000;
>
> No magic values please.
>
> > + writel(ctrl_val, brcmstb_priv->sde_ioaddr);
> > + dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr));
> > + /* Let voltages settle */
> > + udelay(100);
>
> Likewise.
Ditto.
>
> > +
> > + /* Turn on the 1v8 VDD2 regulator */
> > + ret = regulator_enable(brcmstb_priv->sde_1v8);
> > + if (ret)
> > + return ret;
> > +
> > + /* Wait for Tpvcrl */
> > + msleep(1);
> > +
> > + /* Sample DAT2 (CLKREQ#) - if low, card is in PCIe mode */
> > + present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
> > + present_state = (present_state & SDHCI_DATA_LVL_MASK) >> SDHCI_DATA_LVL_SHIFT;
> > + dev_dbg(dev, "state = 0x%08x\n", present_state);
> > +
> > + if (present_state & BIT(2)) {
>
> Likewise, replace with constant.
Ack.
>
> > + dev_err(dev, "DAT2 still high, abandoning SDex switch\n");
> > + return -ENODEV;
> > + }
> > +
> > + /* Turn on the LCPLL PTEST mux */
> > + ctrl_val = readl(brcmstb_priv->sde_ioaddr2 + 20); // misc5
> > + ctrl_val &= ~(0x7 << 7);
> > + ctrl_val |= 3 << 7;
> > + writel(ctrl_val, brcmstb_priv->sde_ioaddr2 + 20);
> > + dev_dbg(dev, "misc 5->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2 + 20));
> > +
> > + /* PTEST diff driver enable */
> > + ctrl_val = readl(brcmstb_priv->sde_ioaddr2);
> > + ctrl_val |= BIT(21);
> > + writel(ctrl_val, brcmstb_priv->sde_ioaddr2);
> > +
> > + dev_dbg(dev, "misc 0->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2));
> > +
> > + /* Wait for more than the minimum Tpvpgl time */
> > + msleep(100);
> > +
> > + if (brcmstb_priv->sde_pcie) {
> > + struct of_changeset changeset;
> > + static struct property okay_property = {
> > + .name = "status",
> > + .value = "okay",
> > + .length = 5,
> > + };
> > +
> > + /* Enable the pcie controller */
> > + of_changeset_init(&changeset);
> > + ret = of_changeset_update_property(&changeset,
> > + brcmstb_priv->sde_pcie,
> > + &okay_property);
> > + if (ret) {
> > + dev_err(dev, "%s: failed to update property - %d\n", __func__,
> > + ret);
> > + return -ENODEV;
> > + }
> > + ret = of_changeset_apply(&changeset);
> > + }
>
> Why are you doing this? Cannot the firmware enable/disable the node
> according to the boot mode or something else?
>
> This is not going to fly for upstream, sorry.
> --
> Florian
On 12:07 Sun 14 Apr , Stefan Wahren wrote:
> Hi Andrea,
>
> Am 14.04.24 um 00:14 schrieb Andrea della Porta:
> > Hi,
> >
> > This patchset adds support for the SDHCI controller on Broadcom BCM2712
> > SoC in order to make it possible to boot (particularly) Raspberry Pi 5
> > from SD card. This work is heavily based on downstream contributions.
> since your goal is minimal Raspberry Pi 5 support, i suggest to use this
> as the subject for this patch.
> > Patch #1 and 2: introduce the dt binding definitions for, respectively,
> > the new pin cfg/mux controller and the SD host controller as a preparatory
> > step for the upcoming dts.
> >
> > Patch #3: add a somewhat reasonable (*almost* bare-minimum) dts to be used
> > to boot Rpi5 boards. Since till now there was no support at all for any
> > 2712 based chipset, both the SoC and board dts plus definitions for the
> > new Pin and SD host controller have been added.
> The patch still seems to contain a lot unnecessary stuff (Wifi, BT,
> SPI), please try to remove as much as possible for the minimal support
> (just boot via debug UART & SD card) in order to make review easier. Btw
> this patch must be after pinctrl & SDHCI support.
> > Patch #4: the driver supporting the pin controller. Based on [1] and
> > successive fix commits.
> >
> > Patch #5: add SDHCI support. Based on [2] and the next 2 fix commits.
> > Drop the SD Express implementation for now, that will be added by patch
> > #6.
> >
> > Patch #6: this patch offers SD Express support and can be considered totally
> > optional. The callback plumbing is slightly different w.r.t. the downstream
> > approach (see [3]), as explained in the patch comment. Not sure what is the best,
> > any comment is highly appreciated.
> I don't think this should be necessary for minimal Raspberry Pi 5
> support. Maybe this should be addressed later.
Thanks for all the feedback. Just a quick note to let you know that
I'm working on V2 patchset that will fix all coding-style and dts/binding
issues. The new patchset will be significantly smaller and I managed
to remove everything that is not strictly needed in order to be able to
boot an rpi5 from sd card.
Best regards,
Andrea