diff --git a/etc/dtb/aarch64/bcm2711-rpi-4-b.dts b/etc/dtb/aarch64/bcm2711-rpi-4-b.dts index 978c7ffb..fe7430bd 100644 --- a/etc/dtb/aarch64/bcm2711-rpi-4-b.dts +++ b/etc/dtb/aarch64/bcm2711-rpi-4-b.dts @@ -134,23 +134,57 @@ pinctrl-names = "default"; bootph-all; + // UART uart0_ctsrts_gpio30: uart0_ctsrts_gpio30 { brcm,pins = <30>, <31>; brcm,pull = <2>, <0>; brcm,function = <7>; }; - uart0_gpio32: uart0_gpio32 { brcm,pins = <32>, <33>; brcm,pull = <0>, <2>; brcm,function = <8>; }; - uart1_gpio14: uart1_gpio14 { brcm,pins = <14>, <15>; brcm,function = <2>; bootph-all; }; + + // I²C + i2c0if_gpio0: i2c0if-gpio0 { + brcm,pins = <0>, <1>; + brcm,function = <4>; + }; + i2c0if_gpio44: i2c0if-gpio44 { + brcm,pins = <44>, <45>; + brcm,function = <5>; + }; + i2c1_gpio: i2c1 { + brcm,pins = <2>, <3>; + brcm,function = <4>; + brcm,pull = <2>; + }; + i2c3_gpio: i2c3 { + brcm,pins = <4>, <5>; + brcm,function = <2>; + brcm,pull = <2>; + }; + i2c4_gpio: i2c4 { + brcm,pins = <8>, <9>; + brcm,function = <2>; + brcm,pull = <2>; + }; + i2c5_gpio: i2c5 { + brcm,pins = <12>, <13>; + brcm,function = <2>; + brcm,pull = <2>; + }; + i2c6_gpio: i2c6 { + brcm,pins = <22>, <23>; + brcm,function = <2>; + brcm,pull = <2>; + }; }; uart0: serial@7e201000 { @@ -163,7 +197,7 @@ "apb_pclk"; arm,primecell-periphid = <0x241011>; pinctrl-names = "default"; - pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32>; + pinctrl-0 = <&uart0_ctsrts_gpio30>, <&uart0_gpio32>; uart-has-rtscts; status = "okay"; skip-init; @@ -189,6 +223,100 @@ bootph-all; }; + i2c0if: i2c@7e205000 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205000 0x200>; + interrupts = ; + clocks = <&cprman 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + clock-frequency = <0x186a0>; + }; + + i2c0mux: i2c0mux { + compatible = "i2c-mux-pinctrl"; + #address-cells = <0x01>; + #size-cells = <0x00>; + i2c-parent = <&i2c0if>; + status = "okay"; + pinctrl-names = "i2c0", "i2c_csi_dsi"; + pinctrl-0 = <&i2c0if_gpio0>; + pinctrl-1 = <&i2c0if_gpio44>; + + i2c0: i2c@0 { + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + }; + + i2c_csi_dsi: i2c@1 { + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + }; + }; + i2c1: i2c@7e804000 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e804000 0x1000>; + interrupts = ; + clocks = <&cprman 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_gpio>; + clock-frequency = <0x186a0>; + }; + // TODO: memory access crashes on qemu (not implemented?) + i2c3: i2c@7e205600 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205600 0x200>; + interrupts = ; + clocks = <&cprman 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <&i2c3_gpio>; + pinctrl-names = "default"; + }; + // TODO: memory access crashes on qemu (not implemented?) + i2c4: i2c@7e205800 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205800 0x200>; + interrupts = ; + clocks = <&cprman 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <&i2c4_gpio>; + pinctrl-names = "default"; + }; + // TODO: memory access crashes on qemu (not implemented?) + i2c5: i2c@7e205a00 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205a00 0x200>; + interrupts = ; + clocks = <&cprman 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <&i2c5_gpio>; + pinctrl-names = "default"; + }; + // TODO: memory access crashes on qemu (not implemented?) + i2c6: i2c@7e205c00 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205c00 0x200>; + interrupts = ; + clocks = <&cprman 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <&i2c6_gpio>; + pinctrl-names = "default"; + }; + l1_intc: local_intc@40000000 { compatible = "brcm,bcm2836-l1-intc"; reg = <0x40000000 0x100>; diff --git a/etc/raw-dtb/bcm2711-rpi-4-b.dtb b/etc/raw-dtb/bcm2711-rpi-4-b.dtb new file mode 100644 index 00000000..4c8a1862 Binary files /dev/null and b/etc/raw-dtb/bcm2711-rpi-4-b.dtb differ diff --git a/etc/raw-dtb/bcm2711-rpi-4-b.dts b/etc/raw-dtb/bcm2711-rpi-4-b.dts new file mode 100644 index 00000000..d05a9ac9 --- /dev/null +++ b/etc/raw-dtb/bcm2711-rpi-4-b.dts @@ -0,0 +1,2730 @@ +/dts-v1/; + +/memreserve/ 0x0000000000000000 0x0000000000001000; +/ { + compatible = "raspberrypi,4-model-b", "brcm,bcm2711"; + model = "Raspberry Pi 4 Model B"; + #address-cells = <0x02>; + #size-cells = <0x01>; + interrupt-parent = <0x01>; + + aliases { + serial0 = "/soc/serial@7e215040"; + serial1 = "/soc/serial@7e201000"; + emmc2bus = "/emmc2bus"; + ethernet0 = "/scb/ethernet@7d580000"; + pcie0 = "/scb/pcie@7d500000"; + blconfig = "/reserved-memory/nvram@0"; + blpubkey = "/reserved-memory/nvram@1"; + bluetooth = "/soc/serial@7e201000/bluetooth"; + aux = "/soc/aux@7e215000"; + sound = "/soc/sound"; + soc = "/soc"; + dma = "/soc/dma-controller@7e007000"; + watchdog = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + uart0 = "/soc/serial@7e201000"; + uart1 = "/soc/serial@7e215040"; + sdhost = "/soc/mmc@7e202000"; + mmc = "/soc/mmc@7e300000"; + mmc1 = "/soc/mmcnr@7e300000"; + mmc0 = "/emmc2bus/mmc@7e340000"; + i2s = "/soc/i2s@7e203000"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c1 = "/soc/i2c@7e804000"; + i2c10 = "/soc/i2c0mux/i2c@1"; + i2c = "/soc/i2c@7e804000"; + spi0 = "/soc/spi@7e204000"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + usb = "/soc/usb@7e980000"; + leds = "/leds"; + fb = "/soc/fb"; + thermal = "/soc/avs-monitor@7d5d2000/thermal"; + axiperf = "/soc/axiperf"; + uart2 = "/soc/serial@7e201400"; + uart3 = "/soc/serial@7e201600"; + uart4 = "/soc/serial@7e201800"; + uart5 = "/soc/serial@7e201a00"; + serial2 = "/soc/serial@7e201400"; + serial3 = "/soc/serial@7e201600"; + serial4 = "/soc/serial@7e201800"; + serial5 = "/soc/serial@7e201a00"; + mmc2 = "/soc/mmc@7e202000"; + i2c3 = "/soc/i2c@7e205600"; + i2c4 = "/soc/i2c@7e205800"; + i2c5 = "/soc/i2c@7e205a00"; + i2c6 = "/soc/i2c@7e205c00"; + i2c20 = "/soc/i2c@7ef04500"; + i2c21 = "/soc/i2c@7ef09500"; + spi3 = "/soc/spi@7e204600"; + spi4 = "/soc/spi@7e204800"; + spi5 = "/soc/spi@7e204a00"; + spi6 = "/soc/spi@7e204c00"; + phandle = <0x4f>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_headphones=0 cgroup_disable=memory numa_policy=interleave nvme.max_host_mem_size_mb=0"; + phandle = <0x54>; + }; + + reserved-memory { + #address-cells = <0x02>; + #size-cells = <0x01>; + ranges; + phandle = <0x5c>; + + linux,cma { + compatible = "shared-dma-pool"; + size = <0x4000000>; + reusable; + linux,cma-default; + alloc-ranges = <0x00 0x00 0x30000000>; + phandle = <0x5d>; + }; + + nvram@0 { + compatible = "raspberrypi,bootloader-config", "nvmem-rmem"; + #address-cells = <0x01>; + #size-cells = <0x01>; + reg = <0x00 0x00 0x00>; + no-map; + status = "disabled"; + phandle = <0x5e>; + }; + + nvram@1 { + compatible = "raspberrypi,bootloader-public-key", "nvmem-rmem"; + #address-cells = <0x01>; + #size-cells = <0x01>; + reg = <0x00 0x00 0x00>; + no-map; + status = "disabled"; + phandle = <0x5f>; + }; + }; + + thermal-zones { + + cpu-thermal { + polling-delay-passive = <0x00>; + polling-delay = <0x3e8>; + coefficients = <0xfffffe19 0x641b8>; + thermal-sensors = <0x02>; + phandle = <0x60>; + + trips { + phandle = <0x61>; + + cpu-crit { + temperature = <0x1adb0>; + hysteresis = <0x00>; + type = "critical"; + }; + }; + + cooling-maps { + phandle = <0x62>; + }; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x7e000000 0x00 0xfe000000 0x1800000 0x7c000000 0x00 0xfc000000 0x2000000 0x40000000 0x00 0xff800000 0x800000>; + dma-ranges = <0xc0000000 0x00 0x00 0x40000000 0x7c000000 0x00 0xfc000000 0x3800000>; + phandle = <0x63>; + + timer@7e003000 { + compatible = "brcm,bcm2835-system-timer"; + reg = <0x7e003000 0x1000>; + interrupts = <0x00 0x40 0x04 0x00 0x41 0x04 0x00 0x42 0x04 0x00 0x43 0x04>; + clock-frequency = <0xf4240>; + status = "disabled"; + phandle = <0x64>; + }; + + txp@7e004000 { + compatible = "brcm,bcm2835-txp"; + reg = <0x7e004000 0x20>; + interrupts = <0x00 0x4b 0x04>; + status = "disabled"; + phandle = <0x65>; + }; + + cprman@7e101000 { + compatible = "brcm,bcm2711-cprman"; + #clock-cells = <0x01>; + reg = <0x7e101000 0x2000>; + clocks = <0x03 0x04 0x00 0x04 0x01 0x04 0x02 0x05 0x00 0x05 0x01 0x05 0x02>; + firmware = <0x06>; + phandle = <0x08>; + }; + + mailbox@7e00b880 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0x00 0x21 0x04>; + #mbox-cells = <0x00>; + phandle = <0x31>; + }; + + gpio@7e200000 { + compatible = "brcm,bcm2711-gpio"; + reg = <0x7e200000 0xb4>; + interrupts = <0x00 0x71 0x04 0x00 0x72 0x04>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x07 0x00 0x00 0x3a>; + gpio-line-names = "ID_SDA", "ID_SCL", "GPIO2", "GPIO3", "GPIO4", "GPIO5", "GPIO6", "GPIO7", "GPIO8", "GPIO9", "GPIO10", "GPIO11", "GPIO12", "GPIO13", "GPIO14", "GPIO15", "GPIO16", "GPIO17", "GPIO18", "GPIO19", "GPIO20", "GPIO21", "GPIO22", "GPIO23", "GPIO24", "GPIO25", "GPIO26", "GPIO27", "RGMII_MDIO", "RGMIO_MDC", "CTS0", "RTS0", "TXD0", "RXD0", "SD1_CLK", "SD1_CMD", "SD1_DATA0", "SD1_DATA1", "SD1_DATA2", "SD1_DATA3", "PWM0_MISO", "PWM1_MOSI", "STATUS_LED_G_CLK", "SPIFLASH_CE_N", "SDA0", "SCL0", "RGMII_RXCLK", "RGMII_RXCTL", "RGMII_RXD0", "RGMII_RXD1", "RGMII_RXD2", "RGMII_RXD3", "RGMII_TXCLK", "RGMII_TXCTL", "RGMII_TXD0", "RGMII_TXD1", "RGMII_TXD2", "RGMII_TXD3"; + phandle = <0x07>; + + dpi-gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x06>; + phandle = <0x66>; + }; + + emmc-gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x07>; + phandle = <0x67>; + }; + + emmc-gpio34 { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x68>; + }; + + emmc-gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x07>; + phandle = <0x13>; + }; + + gpclk0-gpio4 { + brcm,pins = <0x04>; + brcm,function = <0x04>; + phandle = <0x69>; + }; + + gpclk1-gpio5 { + brcm,pins = <0x05>; + brcm,function = <0x04>; + phandle = <0x6a>; + }; + + gpclk1-gpio42 { + brcm,pins = <0x2a>; + brcm,function = <0x04>; + phandle = <0x6b>; + }; + + gpclk1-gpio44 { + brcm,pins = <0x2c>; + brcm,function = <0x04>; + phandle = <0x6c>; + }; + + gpclk2-gpio6 { + brcm,pins = <0x06>; + brcm,function = <0x04>; + phandle = <0x6d>; + }; + + gpclk2-gpio43 { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x6e>; + }; + + i2c0if-gpio0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x35>; + }; + + i2c0if-gpio28 { + brcm,pins = <0x1c 0x1d>; + brcm,function = <0x04>; + phandle = <0x6f>; + }; + + i2c0if-gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x05>; + phandle = <0x36>; + }; + + i2c1-gpio2 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x70>; + }; + + i2c1-gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x06>; + phandle = <0x71>; + }; + + jtag-gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x03>; + phandle = <0x72>; + }; + + pcm-gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x73>; + }; + + pcm-gpio28 { + brcm,pins = <0x1c 0x1d 0x1e 0x1f>; + brcm,function = <0x06>; + phandle = <0x74>; + }; + + sdhost-gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x04>; + phandle = <0x75>; + }; + + spi0-gpio7 { + brcm,pins = <0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x76>; + }; + + spi0-gpio35 { + brcm,pins = <0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x04>; + phandle = <0x77>; + }; + + spi1-gpio16 { + brcm,pins = <0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x03>; + phandle = <0x78>; + }; + + spi2-gpio40 { + brcm,pins = <0x28 0x29 0x2a 0x2b 0x2c 0x2d>; + brcm,function = <0x03>; + phandle = <0x79>; + }; + + uart0-gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x04>; + phandle = <0x7a>; + }; + + uart0-ctsrts-gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x07>; + phandle = <0x7b>; + }; + + uart0-ctsrts-gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x07>; + brcm,pull = <0x02 0x00>; + phandle = <0x7c>; + }; + + uart0-gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x7d>; + }; + + uart0-gpio36 { + brcm,pins = <0x24 0x25>; + brcm,function = <0x06>; + phandle = <0x7e>; + }; + + uart0-ctsrts-gpio38 { + brcm,pins = <0x26 0x27>; + brcm,function = <0x06>; + phandle = <0x7f>; + }; + + uart1-gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x02>; + phandle = <0x80>; + }; + + uart1-ctsrts-gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x02>; + phandle = <0x81>; + }; + + uart1-gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x02>; + phandle = <0x82>; + }; + + uart1-ctsrts-gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x02>; + phandle = <0x83>; + }; + + uart1-gpio40 { + brcm,pins = <0x28 0x29>; + brcm,function = <0x02>; + phandle = <0x84>; + }; + + uart1-ctsrts-gpio42 { + brcm,pins = <0x2a 0x2b>; + brcm,function = <0x02>; + phandle = <0x85>; + }; + + gpclk0-gpio49 { + phandle = <0x86>; + + pin-gpclk { + pins = "gpio49"; + function = "alt1"; + bias-disable; + }; + }; + + gpclk1-gpio50 { + phandle = <0x87>; + + pin-gpclk { + pins = "gpio50"; + function = "alt1"; + bias-disable; + }; + }; + + gpclk2-gpio51 { + phandle = <0x88>; + + pin-gpclk { + pins = "gpio51"; + function = "alt1"; + bias-disable; + }; + }; + + i2c0if-gpio46 { + phandle = <0x89>; + + pin-sda { + function = "alt0"; + pins = "gpio46"; + bias-pull-up; + }; + + pin-scl { + function = "alt0"; + pins = "gpio47"; + bias-disable; + }; + }; + + i2c1-gpio46 { + phandle = <0x8a>; + + pin-sda { + function = "alt1"; + pins = "gpio46"; + bias-pull-up; + }; + + pin-scl { + function = "alt1"; + pins = "gpio47"; + bias-disable; + }; + }; + + i2c3-gpio2 { + phandle = <0x8b>; + + pin-sda { + function = "alt5"; + pins = "gpio2"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio3"; + bias-disable; + }; + }; + + i2c3-gpio4 { + phandle = <0x8c>; + + pin-sda { + function = "alt5"; + pins = "gpio4"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio5"; + bias-disable; + }; + }; + + i2c4-gpio6 { + phandle = <0x8d>; + + pin-sda { + function = "alt5"; + pins = "gpio6"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio7"; + bias-disable; + }; + }; + + i2c4-gpio8 { + phandle = <0x8e>; + + pin-sda { + function = "alt5"; + pins = "gpio8"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio9"; + bias-disable; + }; + }; + + i2c5-gpio10 { + phandle = <0x8f>; + + pin-sda { + function = "alt5"; + pins = "gpio10"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio11"; + bias-disable; + }; + }; + + i2c5-gpio12 { + phandle = <0x90>; + + pin-sda { + function = "alt5"; + pins = "gpio12"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio13"; + bias-disable; + }; + }; + + i2c6-gpio0 { + phandle = <0x91>; + + pin-sda { + function = "alt5"; + pins = "gpio0"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio1"; + bias-disable; + }; + }; + + i2c6-gpio22 { + phandle = <0x92>; + + pin-sda { + function = "alt5"; + pins = "gpio22"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio23"; + bias-disable; + }; + }; + + i2c-slave-gpio8 { + phandle = <0x93>; + + pins-i2c-slave { + pins = "gpio8", "gpio9", "gpio10", "gpio11"; + function = "alt3"; + }; + }; + + jtag-gpio48 { + phandle = <0x94>; + + pins-jtag { + pins = "gpio48", "gpio49", "gpio50", "gpio51", "gpio52", "gpio53"; + function = "alt4"; + }; + }; + + mii-gpio28 { + phandle = <0x95>; + + pins-mii { + pins = "gpio28", "gpio29", "gpio30", "gpio31"; + function = "alt4"; + }; + }; + + mii-gpio36 { + phandle = <0x96>; + + pins-mii { + pins = "gpio36", "gpio37", "gpio38", "gpio39"; + function = "alt5"; + }; + }; + + pcm-gpio50 { + phandle = <0x97>; + + pins-pcm { + pins = "gpio50", "gpio51", "gpio52", "gpio53"; + function = "alt2"; + }; + }; + + pwm0-0-gpio12 { + phandle = <0x98>; + + pin-pwm { + pins = "gpio12"; + function = "alt0"; + bias-disable; + }; + }; + + pwm0-0-gpio18 { + phandle = <0x99>; + + pin-pwm { + pins = "gpio18"; + function = "alt5"; + bias-disable; + }; + }; + + pwm1-0-gpio40 { + phandle = <0x28>; + + pin-pwm { + pins = "gpio40"; + function = "alt0"; + bias-disable; + }; + }; + + pwm0-1-gpio13 { + phandle = <0x9a>; + + pin-pwm { + pins = "gpio13"; + function = "alt0"; + bias-disable; + }; + }; + + pwm0-1-gpio19 { + phandle = <0x9b>; + + pin-pwm { + pins = "gpio19"; + function = "alt5"; + bias-disable; + }; + }; + + pwm1-1-gpio41 { + phandle = <0x29>; + + pin-pwm { + pins = "gpio41"; + function = "alt0"; + bias-disable; + }; + }; + + pwm0-1-gpio45 { + phandle = <0x9c>; + + pin-pwm { + pins = "gpio45"; + function = "alt0"; + bias-disable; + }; + }; + + pwm0-0-gpio52 { + phandle = <0x9d>; + + pin-pwm { + pins = "gpio52"; + function = "alt1"; + bias-disable; + }; + }; + + pwm0-1-gpio53 { + phandle = <0x9e>; + + pin-pwm { + pins = "gpio53"; + function = "alt1"; + bias-disable; + }; + }; + + rgmii-gpio35 { + phandle = <0x9f>; + + pin-start-stop { + pins = "gpio35"; + function = "alt4"; + }; + + pin-rx-ok { + pins = "gpio36"; + function = "alt4"; + }; + }; + + rgmii-irq-gpio34 { + phandle = <0xa0>; + + pin-irq { + pins = "gpio34"; + function = "alt5"; + }; + }; + + rgmii-irq-gpio39 { + phandle = <0xa1>; + + pin-irq { + pins = "gpio39"; + function = "alt4"; + }; + }; + + rgmii-mdio-gpio28 { + phandle = <0xa2>; + + pins-mdio { + pins = "gpio28", "gpio29"; + function = "alt5"; + }; + }; + + rgmii-mdio-gpio37 { + phandle = <0xa3>; + + pins-mdio { + pins = "gpio37", "gpio38"; + function = "alt4"; + }; + }; + + spi0-gpio46 { + phandle = <0xa4>; + + pins-spi { + pins = "gpio46", "gpio47", "gpio48", "gpio49"; + function = "alt2"; + }; + }; + + spi2-gpio46 { + phandle = <0xa5>; + + pins-spi { + pins = "gpio46", "gpio47", "gpio48", "gpio49", "gpio50"; + function = "alt5"; + }; + }; + + spi3-gpio0 { + phandle = <0xa6>; + + pins-spi { + pins = "gpio0", "gpio1", "gpio2", "gpio3"; + function = "alt3"; + }; + }; + + spi4-gpio4 { + phandle = <0xa7>; + + pins-spi { + pins = "gpio4", "gpio5", "gpio6", "gpio7"; + function = "alt3"; + }; + }; + + spi5-gpio12 { + phandle = <0xa8>; + + pins-spi { + pins = "gpio12", "gpio13", "gpio14", "gpio15"; + function = "alt3"; + }; + }; + + spi6-gpio18 { + phandle = <0xa9>; + + pins-spi { + pins = "gpio18", "gpio19", "gpio20", "gpio21"; + function = "alt3"; + }; + }; + + uart2-gpio0 { + phandle = <0xaa>; + + pin-tx { + pins = "gpio0"; + function = "alt4"; + bias-disable; + }; + + pin-rx { + pins = "gpio1"; + function = "alt4"; + bias-pull-up; + }; + }; + + uart2-ctsrts-gpio2 { + phandle = <0xab>; + + pin-cts { + pins = "gpio2"; + function = "alt4"; + bias-pull-up; + }; + + pin-rts { + pins = "gpio3"; + function = "alt4"; + bias-disable; + }; + }; + + uart3-gpio4 { + phandle = <0xac>; + + pin-tx { + pins = "gpio4"; + function = "alt4"; + bias-disable; + }; + + pin-rx { + pins = "gpio5"; + function = "alt4"; + bias-pull-up; + }; + }; + + uart3-ctsrts-gpio6 { + phandle = <0xad>; + + pin-cts { + pins = "gpio6"; + function = "alt4"; + bias-pull-up; + }; + + pin-rts { + pins = "gpio7"; + function = "alt4"; + bias-disable; + }; + }; + + uart4-gpio8 { + phandle = <0xae>; + + pin-tx { + pins = "gpio8"; + function = "alt4"; + bias-disable; + }; + + pin-rx { + pins = "gpio9"; + function = "alt4"; + bias-pull-up; + }; + }; + + uart4-ctsrts-gpio10 { + phandle = <0xaf>; + + pin-cts { + pins = "gpio10"; + function = "alt4"; + bias-pull-up; + }; + + pin-rts { + pins = "gpio11"; + function = "alt4"; + bias-disable; + }; + }; + + uart5-gpio12 { + phandle = <0xb0>; + + pin-tx { + pins = "gpio12"; + function = "alt4"; + bias-disable; + }; + + pin-rx { + pins = "gpio13"; + function = "alt4"; + bias-pull-up; + }; + }; + + uart5-ctsrts-gpio14 { + phandle = <0xb1>; + + pin-cts { + pins = "gpio14"; + function = "alt4"; + bias-pull-up; + }; + + pin-rts { + pins = "gpio15"; + function = "alt4"; + bias-disable; + }; + }; + + gpioout { + brcm,pins = <0x06>; + brcm,function = <0x01>; + phandle = <0xb2>; + }; + + alt0 { + brcm,pins = <0x04 0x05 0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0xb3>; + }; + + dpi_18bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + brcm,pull = <0x00>; + phandle = <0xb4>; + }; + + dpi_18bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + phandle = <0xb5>; + }; + + dpi_18bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0xb6>; + }; + + dpi_18bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0xb7>; + }; + + dpi_16bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0xb8>; + }; + + dpi_16bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0xb9>; + }; + + dpi_16bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0xba>; + }; + + dpi_16bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0xbb>; + }; + + spi0_pins { + brcm,pins = <0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x0e>; + }; + + spi0_cs_pins { + brcm,pins = <0x08 0x07>; + brcm,function = <0x01>; + phandle = <0x0f>; + }; + + spi3_pins { + brcm,pins = <0x01 0x02 0x03>; + brcm,function = <0x07>; + phandle = <0x1c>; + }; + + spi3_cs_pins { + brcm,pins = <0x00 0x18>; + brcm,function = <0x01>; + phandle = <0x1d>; + }; + + spi4_pins { + brcm,pins = <0x05 0x06 0x07>; + brcm,function = <0x07>; + phandle = <0x1e>; + }; + + spi4_cs_pins { + brcm,pins = <0x04 0x19>; + brcm,function = <0x01>; + phandle = <0x1f>; + }; + + spi5_pins { + brcm,pins = <0x0d 0x0e 0x0f>; + brcm,function = <0x07>; + phandle = <0x20>; + }; + + spi5_cs_pins { + brcm,pins = <0x0c 0x1a>; + brcm,function = <0x01>; + phandle = <0x21>; + }; + + spi6_pins { + brcm,pins = <0x13 0x14 0x15>; + brcm,function = <0x07>; + phandle = <0x22>; + }; + + spi6_cs_pins { + brcm,pins = <0x12 0x1b>; + brcm,function = <0x01>; + phandle = <0x23>; + }; + + i2c0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + brcm,pull = <0x02>; + phandle = <0xbc>; + }; + + i2c1 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + brcm,pull = <0x02>; + phandle = <0x15>; + }; + + i2c3 { + brcm,pins = <0x04 0x05>; + brcm,function = <0x02>; + brcm,pull = <0x02>; + phandle = <0x24>; + }; + + i2c4 { + brcm,pins = <0x08 0x09>; + brcm,function = <0x02>; + brcm,pull = <0x02>; + phandle = <0x25>; + }; + + i2c5 { + brcm,pins = <0x0c 0x0d>; + brcm,function = <0x02>; + brcm,pull = <0x02>; + phandle = <0x26>; + }; + + i2c6 { + brcm,pins = <0x16 0x17>; + brcm,function = <0x02>; + brcm,pull = <0x02>; + phandle = <0x27>; + }; + + i2s { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x0d>; + }; + + sdio_pins { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x33>; + }; + + uart2_pins { + brcm,pins = <0x00 0x01>; + brcm,function = <0x03>; + brcm,pull = <0x00 0x02>; + phandle = <0x18>; + }; + + uart3_pins { + brcm,pins = <0x04 0x05>; + brcm,function = <0x03>; + brcm,pull = <0x00 0x02>; + phandle = <0x19>; + }; + + uart4_pins { + brcm,pins = <0x08 0x09>; + brcm,function = <0x03>; + brcm,pull = <0x00 0x02>; + phandle = <0x1a>; + }; + + uart5_pins { + brcm,pins = <0x0c 0x0d>; + brcm,function = <0x03>; + brcm,pull = <0x00 0x02>; + phandle = <0x1b>; + }; + + bt_pins { + brcm,pins = "-"; + brcm,function = <0x00>; + brcm,pull = <0x02>; + phandle = <0x0a>; + }; + + uart0_pins { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x09>; + }; + + uart1_pins { + brcm,pins; + brcm,function; + brcm,pull; + phandle = <0x12>; + }; + + uart1_bt_pins { + brcm,pins = <0x20 0x21 0x1e 0x1f>; + brcm,function = <0x02>; + brcm,pull = <0x00 0x02 0x02 0x00>; + phandle = <0xbd>; + }; + + audio_pins { + brcm,pins = <0x28 0x29>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x32>; + }; + }; + + serial@7e201000 { + compatible = "arm,pl011-axi"; + reg = <0x7e201000 0x200>; + interrupts = <0x00 0x79 0x04>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk", "apb_pclk"; + arm,primecell-periphid = <0x341011>; + status = "okay"; + cts-event-workaround; + pinctrl-names = "default"; + pinctrl-0 = <0x09 0x0a>; + uart-has-rtscts; + skip-init; + phandle = <0x43>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <0x2dc6c0>; + shutdown-gpios = <0x0b 0x00 0x00>; + local-bd-address = [00 00 00 00 00 00]; + fallback-bd-address; + status = "okay"; + phandle = <0x41>; + }; + }; + + mmc@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <0x00 0x78 0x04>; + clocks = <0x08 0x14>; + status = "disabled"; + dmas = <0x0c 0x2000000d>; + dma-names = "rx-tx"; + bus-width = <0x04>; + brcm,overclock-50 = <0x00>; + brcm,pio-limit = <0x01>; + firmware = <0x06>; + phandle = <0x4b>; + }; + + i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; + reg = <0x7e203000 0x24>; + clocks = <0x08 0x1f>; + status = "disabled"; + #sound-dai-cells = <0x00>; + dmas = <0x0c 0x02 0x0c 0x03>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <0x0d>; + phandle = <0x45>; + }; + + spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x200>; + interrupts = <0x00 0x76 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + dmas = <0x0c 0x06 0x0c 0x07>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <0x0e 0x0f>; + cs-gpios = <0x07 0x08 0x01 0x07 0x07 0x01>; + phandle = <0x46>; + + spidev@0 { + compatible = "spidev"; + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0xbe>; + }; + + spidev@1 { + compatible = "spidev"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0xbf>; + }; + }; + + i2c@7e205000 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205000 0x200>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x34>; + }; + + dpi@7e208000 { + compatible = "brcm,bcm2835-dpi"; + reg = <0x7e208000 0x8c>; + clocks = <0x08 0x14 0x08 0x2c>; + clock-names = "core", "pixel"; + status = "disabled"; + phandle = <0xc0>; + }; + + dsi@7e209000 { + compatible = "brcm,bcm2835-dsi0"; + reg = <0x7e209000 0x78>; + interrupts = <0x00 0x64 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x22 0x08 0x2f 0x08 0x31>; + clock-names = "phy", "escape", "pixel"; + clock-output-names = "dsi0_byte", "dsi0_ddr2", "dsi0_ddr"; + status = "disabled"; + power-domains = <0x10 0x11>; + phandle = <0x04>; + }; + + aux@7e215000 { + compatible = "brcm,bcm2835-aux"; + #clock-cells = <0x01>; + reg = <0x7e215000 0x08>; + clocks = <0x08 0x14>; + phandle = <0x11>; + }; + + serial@7e215040 { + compatible = "brcm,bcm2835-aux-uart"; + reg = <0x7e215040 0x40>; + interrupts = <0x00 0x5d 0x04>; + clocks = <0x11 0x00>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x12>; + skip-init; + phandle = <0x44>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <0x38400>; + shutdown-gpios = <0x0b 0x00 0x00>; + local-bd-address = [00 00 00 00 00 00]; + fallback-bd-address; + status = "disabled"; + phandle = <0x42>; + }; + }; + + spi@7e215080 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e215080 0x40>; + interrupts = <0x00 0x5d 0x04>; + clocks = <0x11 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0xc1>; + }; + + spi@7e2150c0 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e2150c0 0x40>; + interrupts = <0x00 0x5d 0x04>; + clocks = <0x11 0x02>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0xc2>; + }; + + pwm@7e20c000 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x7e20c000 0x28>; + clocks = <0x08 0x1e>; + assigned-clocks = <0x08 0x1e>; + assigned-clock-rates = <0x2faf080>; + #pwm-cells = <0x03>; + status = "disabled"; + phandle = <0xc3>; + }; + + mmc@7e300000 { + compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x00 0x7e 0x04>; + clocks = <0x08 0x1c>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x13>; + bus-width = <0x04>; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + phandle = <0x4c>; + }; + + hvs@7e400000 { + compatible = "brcm,bcm2711-hvs"; + reg = <0x7e400000 0x8000>; + interrupts = <0x00 0x61 0x04>; + clocks = <0x14 0x04>; + status = "disabled"; + phandle = <0xc4>; + }; + + dsi@7e700000 { + compatible = "brcm,bcm2711-dsi1"; + reg = <0x7e700000 0x8c>; + interrupts = <0x00 0x6c 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x23 0x08 0x30 0x08 0x32>; + clock-names = "phy", "escape", "pixel"; + clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr"; + status = "disabled"; + power-domains = <0x10 0x12>; + phandle = <0x05>; + }; + + csi@7e800000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e800000 0x800 0x7e802000 0x04>; + reg-names = "unicam", "cmi"; + interrupts = <0x00 0x66 0x04>; + brcm,num-data-lanes = <0x02>; + status = "disabled"; + clocks = <0x08 0x2d 0x14 0x04>; + clock-names = "lp", "vpu"; + power-domains = <0x10 0x0c>; + phandle = <0x51>; + + port { + }; + }; + + csi@7e801000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e801000 0x800 0x7e802004 0x04>; + reg-names = "unicam", "cmi"; + interrupts = <0x00 0x67 0x04>; + brcm,num-data-lanes = <0x02>; + status = "disabled"; + clocks = <0x08 0x2e 0x14 0x04>; + clock-names = "lp", "vpu"; + power-domains = <0x10 0x0d>; + phandle = <0x50>; + + port { + }; + }; + + i2c@7e804000 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e804000 0x1000>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x15>; + clock-frequency = <0x186a0>; + phandle = <0x48>; + }; + + usb@7e980000 { + compatible = "brcm,bcm2708-usb"; + reg = <0x7e980000 0x10000 0x7e00b200 0x200>; + interrupts = <0x00 0x49 0x04 0x00 0x28 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x16>; + clock-names = "otg"; + dr_mode = "host"; + phys = <0x17>; + phy-names = "usb2-phy"; + power-domains = <0x10 0x06>; + interrupt-names = "usb", "soft"; + status = "disabled"; + phandle = <0xc5>; + }; + + interrupt-controller@40000000 { + compatible = "brcm,bcm2836-l1-intc"; + reg = <0x40000000 0x100>; + phandle = <0xc6>; + }; + + interrupt-controller@40041000 { + interrupt-controller; + #interrupt-cells = <0x03>; + compatible = "arm,gic-400"; + reg = <0x40041000 0x1000 0x40042000 0x2000 0x40044000 0x2000 0x40046000 0x2000>; + interrupts = <0x01 0x09 0xf04>; + phandle = <0x01>; + }; + + avs-monitor@7d5d2000 { + compatible = "brcm,bcm2711-avs-monitor", "syscon", "simple-mfd"; + reg = <0x7d5d2000 0xf00>; + phandle = <0xc7>; + + thermal { + compatible = "brcm,bcm2711-thermal"; + #thermal-sensor-cells = <0x00>; + phandle = <0x02>; + }; + }; + + dma-controller@7e007000 { + compatible = "brcm,bcm2835-dma"; + reg = <0x7e007000 0xb00>; + interrupts = <0x00 0x50 0x04 0x00 0x51 0x04 0x00 0x52 0x04 0x00 0x53 0x04 0x00 0x54 0x04 0x00 0x55 0x04 0x00 0x56 0x04 0x00 0x57 0x04 0x00 0x57 0x04 0x00 0x58 0x04 0x00 0x58 0x04>; + interrupt-names = "dma0", "dma1", "dma2", "dma3", "dma4", "dma5", "dma6", "dma7", "dma8", "dma9", "dma10"; + #dma-cells = <0x01>; + brcm,dma-channel-mask = <0x7f5>; + phandle = <0x0c>; + }; + + watchdog@7e100000 { + compatible = "brcm,bcm2711-pm", "brcm,bcm2835-pm-wdt"; + #power-domain-cells = <0x01>; + #reset-cells = <0x01>; + reg = <0x7e100000 0x114 0x7e00a000 0x24 0x7ec11000 0x20>; + reg-names = "pm", "asb", "rpivid_asb"; + clocks = <0x08 0x15 0x08 0x1d 0x08 0x17 0x08 0x16>; + clock-names = "v3d", "peri_image", "h264", "isp"; + system-power-controller; + phandle = <0x49>; + }; + + rng@7e104000 { + compatible = "brcm,bcm2711-rng200"; + reg = <0x7e104000 0x28>; + status = "okay"; + phandle = <0x4a>; + }; + + serial@7e201400 { + compatible = "arm,pl011-axi"; + reg = <0x7e201400 0x200>; + interrupts = <0x00 0x79 0x04>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk", "apb_pclk"; + arm,primecell-periphid = <0x341011>; + status = "disabled"; + pinctrl-0 = <0x18>; + pinctrl-names = "default"; + phandle = <0xc8>; + }; + + serial@7e201600 { + compatible = "arm,pl011-axi"; + reg = <0x7e201600 0x200>; + interrupts = <0x00 0x79 0x04>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk", "apb_pclk"; + arm,primecell-periphid = <0x341011>; + status = "disabled"; + pinctrl-0 = <0x19>; + pinctrl-names = "default"; + phandle = <0xc9>; + }; + + serial@7e201800 { + compatible = "arm,pl011-axi"; + reg = <0x7e201800 0x200>; + interrupts = <0x00 0x79 0x04>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk", "apb_pclk"; + arm,primecell-periphid = <0x341011>; + status = "disabled"; + pinctrl-0 = <0x1a>; + pinctrl-names = "default"; + phandle = <0xca>; + }; + + serial@7e201a00 { + compatible = "arm,pl011-axi"; + reg = <0x7e201a00 0x200>; + interrupts = <0x00 0x79 0x04>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk", "apb_pclk"; + arm,primecell-periphid = <0x341011>; + status = "disabled"; + pinctrl-0 = <0x1b>; + pinctrl-names = "default"; + phandle = <0xcb>; + }; + + spi@7e204600 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204600 0x200>; + interrupts = <0x00 0x76 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x1c 0x1d>; + pinctrl-names = "default"; + phandle = <0xcc>; + }; + + spi@7e204800 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204800 0x200>; + interrupts = <0x00 0x76 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x1e 0x1f>; + pinctrl-names = "default"; + phandle = <0xcd>; + }; + + spi@7e204a00 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204a00 0x200>; + interrupts = <0x00 0x76 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x20 0x21>; + pinctrl-names = "default"; + phandle = <0xce>; + }; + + spi@7e204c00 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204c00 0x200>; + interrupts = <0x00 0x76 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x22 0x23>; + pinctrl-names = "default"; + phandle = <0xcf>; + }; + + i2c@7e205600 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205600 0x200>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x24>; + pinctrl-names = "default"; + phandle = <0xd0>; + }; + + i2c@7e205800 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205800 0x200>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x25>; + pinctrl-names = "default"; + phandle = <0xd1>; + }; + + i2c@7e205a00 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205a00 0x200>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x26>; + pinctrl-names = "default"; + phandle = <0xd2>; + }; + + i2c@7e205c00 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205c00 0x200>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x27>; + pinctrl-names = "default"; + phandle = <0xd3>; + }; + + pixelvalve@7e206000 { + compatible = "brcm,bcm2711-pixelvalve0"; + reg = <0x7e206000 0x100>; + interrupts = <0x00 0x6d 0x04>; + status = "disabled"; + phandle = <0xd4>; + }; + + pixelvalve@7e207000 { + compatible = "brcm,bcm2711-pixelvalve1"; + reg = <0x7e207000 0x100>; + interrupts = <0x00 0x6e 0x04>; + status = "disabled"; + phandle = <0xd5>; + }; + + pixelvalve@7e20a000 { + compatible = "brcm,bcm2711-pixelvalve2"; + reg = <0x7e20a000 0x100>; + interrupts = <0x00 0x65 0x04>; + status = "disabled"; + phandle = <0xd6>; + }; + + pwm@7e20c800 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x7e20c800 0x28>; + clocks = <0x08 0x1e>; + assigned-clocks = <0x08 0x1e>; + assigned-clock-rates = <0x2faf080>; + #pwm-cells = <0x03>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x28 0x29>; + phandle = <0xd7>; + }; + + pixelvalve@7e216000 { + compatible = "brcm,bcm2711-pixelvalve4"; + reg = <0x7e216000 0x100>; + interrupts = <0x00 0x6e 0x04>; + status = "disabled"; + phandle = <0xd8>; + }; + + pixelvalve@7ec12000 { + compatible = "brcm,bcm2711-pixelvalve3"; + reg = <0x7ec12000 0x100>; + interrupts = <0x00 0x6a 0x04>; + status = "disabled"; + phandle = <0xd9>; + }; + + vec@7ec13000 { + compatible = "brcm,bcm2711-vec"; + reg = <0x7ec13000 0x1000>; + clocks = <0x14 0x0f>; + interrupts = <0x00 0x7b 0x04>; + status = "disabled"; + power-domains = <0x10 0x07>; + phandle = <0xda>; + }; + + clock@7ef00000 { + compatible = "brcm,brcm2711-dvp"; + reg = <0x7ef00000 0x10>; + clocks = <0x2a>; + #clock-cells = <0x01>; + #reset-cells = <0x01>; + status = "disabled"; + phandle = <0x2b>; + }; + + interrupt-controller@7ef00100 { + compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; + reg = <0x7ef00100 0x30>; + interrupts = <0x00 0x60 0x01>; + interrupt-controller; + #interrupt-cells = <0x01>; + status = "disabled"; + phandle = <0x2c>; + }; + + hdmi@7ef00700 { + compatible = "brcm,bcm2711-hdmi0"; + reg = <0x7ef00700 0x300 0x7ef00300 0x200 0x7ef00f00 0x80 0x7ef00f80 0x80 0x7ef01b00 0x200 0x7ef01f00 0x400 0x7ef00200 0x80 0x7ef04300 0x100 0x7ef20000 0x100 0x7ef00100 0x30>; + reg-names = "hdmi", "dvp", "phy", "rm", "packet", "metadata", "csc", "cec", "hd", "intr2"; + clock-names = "hdmi", "bvb", "audio", "cec"; + resets = <0x2b 0x00>; + interrupt-parent = <0x2c>; + interrupts = <0x00 0x01 0x02 0x03 0x04 0x05>; + interrupt-names = "cec-tx", "cec-rx", "cec-low", "wakeup", "hpd-connected", "hpd-removed"; + ddc = <0x2d>; + dmas = <0x2e 0x41fa000a>; + dma-names = "audio-rx"; + status = "disabled"; + clocks = <0x14 0x0d 0x14 0x0e 0x2b 0x00 0x2f>; + wifi-2.4ghz-coexistence; + phandle = <0x55>; + }; + + i2c@7ef04500 { + compatible = "brcm,bcm2711-hdmi-i2c"; + reg = <0x7ef04500 0x100 0x7ef00b00 0x300>; + reg-names = "bsc", "auto-i2c"; + clock-frequency = <0x17cdc>; + status = "disabled"; + phandle = <0x2d>; + }; + + hdmi@7ef05700 { + compatible = "brcm,bcm2711-hdmi1"; + reg = <0x7ef05700 0x300 0x7ef05300 0x200 0x7ef05f00 0x80 0x7ef05f80 0x80 0x7ef06b00 0x200 0x7ef06f00 0x400 0x7ef00280 0x80 0x7ef09300 0x100 0x7ef20000 0x100 0x7ef00100 0x30>; + reg-names = "hdmi", "dvp", "phy", "rm", "packet", "metadata", "csc", "cec", "hd", "intr2"; + ddc = <0x30>; + clock-names = "hdmi", "bvb", "audio", "cec"; + resets = <0x2b 0x01>; + interrupt-parent = <0x2c>; + interrupts = <0x08 0x07 0x06 0x09 0x0a 0x0b>; + interrupt-names = "cec-tx", "cec-rx", "cec-low", "wakeup", "hpd-connected", "hpd-removed"; + dmas = <0x2e 0x41fa0011>; + dma-names = "audio-rx"; + status = "disabled"; + clocks = <0x14 0x0d 0x14 0x0e 0x2b 0x01 0x2f>; + wifi-2.4ghz-coexistence; + phandle = <0x56>; + }; + + i2c@7ef09500 { + compatible = "brcm,bcm2711-hdmi-i2c"; + reg = <0x7ef09500 0x100 0x7ef05b00 0x300>; + reg-names = "bsc", "auto-i2c"; + clock-frequency = <0x17cdc>; + status = "disabled"; + phandle = <0x30>; + }; + + firmware { + compatible = "raspberrypi,bcm2835-firmware", "simple-mfd"; + mboxes = <0x31>; + phandle = <0x06>; + + clocks { + compatible = "raspberrypi,firmware-clocks"; + #clock-cells = <0x01>; + phandle = <0x14>; + }; + + gpio { + compatible = "raspberrypi,firmware-gpio"; + gpio-controller; + #gpio-cells = <0x02>; + status = "okay"; + gpio-line-names = "BT_ON", "WL_ON", "PWR_LED_OFF", "GLOBAL_RESET", "VDD_SD_IO_SEL", "CAM_GPIO", "SD_PWR_ON", "SD_OC_N"; + phandle = <0x0b>; + }; + + reset { + compatible = "raspberrypi,firmware-reset"; + #reset-cells = <0x01>; + phandle = <0x3f>; + }; + + vcio { + compatible = "raspberrypi,vcio"; + phandle = <0xdb>; + }; + }; + + power { + compatible = "raspberrypi,bcm2835-power"; + firmware = <0x06>; + #power-domain-cells = <0x01>; + phandle = <0x10>; + }; + + mailbox@7e00b840 { + compatible = "brcm,bcm2711-vchiq"; + reg = <0x7e00b840 0x3c>; + interrupts = <0x00 0x22 0x04>; + pinctrl-names = "default"; + pinctrl-0 = <0x32>; + phandle = <0xdc>; + }; + + mmcnr@7e300000 { + compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x00 0x7e 0x04>; + clocks = <0x08 0x1c>; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + non-removable; + status = "okay"; + #address-cells = <0x01>; + #size-cells = <0x00>; + pinctrl-names = "default"; + pinctrl-0 = <0x33>; + bus-width = <0x04>; + phandle = <0x4d>; + + wifi@1 { + reg = <0x01>; + compatible = "brcm,bcm4329-fmac"; + phandle = <0xdd>; + }; + }; + + firmwarekms@7e600000 { + compatible = "raspberrypi,rpi-firmware-kms-2711"; + reg = <0x7e600000 0x100>; + interrupts = <0x00 0x70 0x04>; + brcm,firmware = <0x06>; + status = "disabled"; + phandle = <0xde>; + }; + + smi@7e600000 { + compatible = "brcm,bcm2835-smi"; + reg = <0x7e600000 0x100>; + interrupts = <0x00 0x70 0x04>; + clocks = <0x08 0x2a>; + assigned-clocks = <0x08 0x2a>; + assigned-clock-rates = <0x7735940>; + dmas = <0x0c 0x04>; + dma-names = "rx-tx"; + status = "disabled"; + phandle = <0xdf>; + }; + + axiperf { + compatible = "brcm,bcm2711-axiperf"; + reg = <0x7e009800 0x100 0x7ee08000 0x100>; + firmware = <0x06>; + status = "disabled"; + phandle = <0x4e>; + }; + + i2c0mux { + compatible = "i2c-mux-pinctrl"; + #address-cells = <0x01>; + #size-cells = <0x00>; + i2c-parent = <0x34>; + status = "disabled"; + pinctrl-names = "i2c0", "i2c_csi_dsi"; + pinctrl-0 = <0x35>; + pinctrl-1 = <0x36>; + phandle = <0x47>; + + i2c@0 { + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0xe0>; + }; + + i2c@1 { + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0xe1>; + }; + }; + + gpiomem { + compatible = "brcm,bcm2835-gpiomem"; + reg = <0x7e200000 0x1000>; + }; + + fb { + compatible = "brcm,bcm2708-fb"; + firmware = <0x06>; + status = "okay"; + phandle = <0xe2>; + }; + + sound { + status = "disabled"; + phandle = <0xe3>; + }; + + nvmem { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + + nvmem_otp { + compatible = "raspberrypi,rpi-otp"; + firmware = <0x06>; + reg = <0x00 0xa6>; + status = "okay"; + phandle = <0xe4>; + }; + + nvmem_cust { + compatible = "raspberrypi,rpi-otp"; + firmware = <0x06>; + reg = <0x01 0x08>; + status = "okay"; + phandle = <0x57>; + }; + + nvmem_priv { + compatible = "raspberrypi,rpi-otp"; + firmware = <0x06>; + reg = <0x03 0x08>; + status = "okay"; + phandle = <0x58>; + }; + }; + }; + + clocks { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x00>; + + clk-osc { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "osc"; + clock-frequency = <0x337f980>; + phandle = <0x03>; + }; + + clk-usb { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "otg"; + clock-frequency = <0x1c9c3800>; + phandle = <0x16>; + }; + }; + + phy { + compatible = "usb-nop-xceiv"; + #phy-cells = <0x00>; + phandle = <0x17>; + }; + + gpu { + compatible = "brcm,bcm2711-vc5"; + status = "disabled"; + raspberrypi,firmware = <0x06>; + phandle = <0xe5>; + }; + + clk-27M { + #clock-cells = <0x00>; + compatible = "fixed-clock"; + clock-frequency = <0x19bfcc0>; + clock-output-names = "27MHz-clock"; + phandle = <0x2f>; + }; + + clk-108M { + #clock-cells = <0x00>; + compatible = "fixed-clock"; + clock-frequency = <0x66ff300>; + clock-output-names = "108MHz-clock"; + phandle = <0x2a>; + }; + + emmc2bus { + compatible = "simple-bus"; + #address-cells = <0x02>; + #size-cells = <0x01>; + ranges = <0x00 0x7e000000 0x00 0xfe000000 0x1800000>; + dma-ranges = <0x00 0xc0000000 0x00 0x00 0x40000000>; + phandle = <0xe6>; + + mmc@7e340000 { + compatible = "brcm,bcm2711-emmc2"; + reg = <0x00 0x7e340000 0x100>; + interrupts = <0x00 0x7e 0x04>; + clocks = <0x08 0x33>; + status = "okay"; + vqmmc-supply = <0x37>; + vmmc-supply = <0x38>; + broken-cd; + mmc-ddr-3_3v; + phandle = <0x59>; + }; + }; + + pmu { + compatible = "arm,cortex-a72-pmu"; + interrupts = <0x00 0x10 0x04 0x00 0x11 0x04 0x00 0x12 0x04 0x00 0x13 0x04>; + interrupt-affinity = <0x39 0x3a 0x3b 0x3c>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <0x01 0x0d 0xf08 0x01 0x0e 0xf08 0x01 0x0b 0xf08 0x01 0x0a 0xf08>; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + enable-method = "brcm,bcm2836-smp"; + phandle = <0xe7>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x00>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xd8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x100>; + i-cache-size = <0xc000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x3d>; + phandle = <0x39>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x01>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x100>; + i-cache-size = <0xc000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x3d>; + phandle = <0x3a>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x02>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x100>; + i-cache-size = <0xc000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x3d>; + phandle = <0x3b>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x03>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xf0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x100>; + i-cache-size = <0xc000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x3d>; + phandle = <0x3c>; + }; + + l2-cache0 { + compatible = "cache"; + cache-unified; + cache-size = <0x100000>; + cache-line-size = <0x40>; + cache-sets = <0x400>; + cache-level = <0x02>; + phandle = <0x3d>; + }; + }; + + scb { + compatible = "simple-bus"; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x7c000000 0x00 0xfc000000 0x00 0x3800000 0x00 0x40000000 0x00 0xff800000 0x00 0x800000 0x06 0x00 0x06 0x00 0x00 0x40000000 0x00 0x00 0x00 0x00 0x00 0xfc000000>; + dma-ranges = <0x04 0x7c000000 0x00 0xfc000000 0x00 0x3800000 0x00 0x00 0x00 0x00 0x04 0x00>; + phandle = <0xe8>; + + pcie@7d500000 { + compatible = "brcm,bcm2711-pcie"; + reg = <0x00 0x7d500000 0x00 0x9310>; + device_type = "pci"; + #address-cells = <0x03>; + #interrupt-cells = <0x01>; + #size-cells = <0x02>; + interrupts = <0x00 0x93 0x04 0x00 0x94 0x04>; + interrupt-names = "pcie", "msi"; + interrupt-map-mask = <0x00 0x00 0x00 0x07>; + interrupt-map = <0x00 0x00 0x00 0x01 0x01 0x00 0x8f 0x04 0x00 0x00 0x00 0x02 0x01 0x00 0x90 0x04 0x00 0x00 0x00 0x03 0x01 0x00 0x91 0x04 0x00 0x00 0x00 0x04 0x01 0x00 0x92 0x04>; + msi-controller; + msi-parent = <0x3e>; + ranges = <0x2000000 0x00 0xc0000000 0x06 0x00 0x00 0x40000000>; + dma-ranges = <0x2000000 0x00 0x00 0x00 0x00 0x00 0xc0000000>; + brcm,enable-ssc; + phandle = <0x3e>; + + pci@0,0 { + device_type = "pci"; + #address-cells = <0x03>; + #size-cells = <0x02>; + ranges; + reg = <0x00 0x00 0x00 0x00 0x00>; + + usb@0,0 { + reg = <0x00 0x00 0x00 0x00 0x00>; + resets = <0x3f 0x00>; + }; + }; + }; + + ethernet@7d580000 { + compatible = "brcm,bcm2711-genet-v5"; + reg = <0x00 0x7d580000 0x00 0x10000>; + #address-cells = <0x01>; + #size-cells = <0x01>; + interrupts = <0x00 0x9d 0x04 0x00 0x9e 0x04>; + status = "okay"; + phy-handle = <0x40>; + phy-mode = "rgmii-rxid"; + phandle = <0xe9>; + + mdio@e14 { + compatible = "brcm,genet-mdio-v5"; + reg = <0xe14 0x08>; + reg-names = "mdio"; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0xea>; + + ethernet-phy@1 { + reg = <0x01>; + led-modes = <0x00 0x08>; + phandle = <0x40>; + }; + }; + }; + + codec@7eb10000 { + compatible = "brcm,bcm2711-hevc-dec", "raspberrypi,hevc-dec"; + reg = <0x00 0x7eb00000 0x00 0x10000 0x00 0x7eb10000 0x00 0x1000>; + reg-names = "hevc", "intc"; + interrupts = <0x00 0x62 0x04>; + clocks = <0x14 0x0b>; + phandle = <0xeb>; + }; + + dma@7e007b00 { + compatible = "brcm,bcm2711-dma"; + reg = <0x00 0x7e007b00 0x00 0x400>; + interrupts = <0x00 0x59 0x04 0x00 0x5a 0x04 0x00 0x5b 0x04 0x00 0x5c 0x04>; + interrupt-names = "dma11", "dma12", "dma13", "dma14"; + #dma-cells = <0x01>; + brcm,dma-channel-mask = <0x7000>; + phandle = <0x2e>; + }; + + xhci@7e9c0000 { + compatible = "generic-xhci"; + status = "disabled"; + reg = <0x00 0x7e9c0000 0x00 0x100000>; + interrupts = <0x00 0xb0 0x04>; + power-domains = <0x10 0x06>; + phandle = <0xec>; + }; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00 0x00 0x00>; + }; + + leds { + compatible = "gpio-leds"; + phandle = <0xed>; + + led-act { + label = "ACT"; + default-state = "off"; + linux,default-trigger = "mmc0"; + gpios = <0x07 0x2a 0x00>; + phandle = <0x5a>; + }; + + led-pwr { + label = "PWR"; + gpios = <0x0b 0x02 0x01>; + default-state = "off"; + linux,default-trigger = "default-on"; + phandle = <0x5b>; + }; + }; + + cam1_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0xee>; + }; + + cam0_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam0-reg"; + enable-active-high; + status = "disabled"; + phandle = <0xef>; + }; + + cam0_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0xf0>; + }; + + cam_dummy_reg { + compatible = "regulator-fixed"; + regulator-name = "cam-dummy-reg"; + status = "okay"; + phandle = <0x52>; + }; + + __overrides__ { + cam0-pwdn-ctrl; + cam0-pwdn; + cam0-led-ctrl; + cam0-led; + bdaddr = "", "", "", "Alocal-bd-address[", "", "", "", "Afallback-bd-address?=0", "", "", "", "Blocal-bd-address[", "", "", "", "Bfallback-bd-address?=0"; + krnbt = "", "", "", "Astatus"; + krnbt_baudrate = "", "", "", "Amax-speed:0", "", "", "", "Bmax-speed:0"; + cache_line_size; + uart0 = "", "", "", "Cstatus"; + uart1 = "", "", "", "Dstatus"; + i2s = "", "", "", "Estatus"; + spi = "", "", "", "Fstatus"; + i2c0 = "", "", "", "4status", "", "", "", "Gstatus"; + i2c1 = "", "", "", "Hstatus"; + i2c = "", "", "", "Hstatus"; + i2c_arm = "", "", "", "Hstatus"; + i2c_vc = "", "", "", "4status", "", "", "", "Gstatus"; + i2c0_baudrate = "", "", "", "4clock-frequency:0"; + i2c1_baudrate = "", "", "", "Hclock-frequency:0"; + i2c_baudrate = "", "", "", "Hclock-frequency:0"; + i2c_arm_baudrate = "", "", "", "Hclock-frequency:0"; + i2c_vc_baudrate = "", "", "", "4clock-frequency:0"; + watchdog = "", "", "", "Iearly-watchdog?"; + random = "", "", "", "Jstatus"; + sd_overclock = "", "", "", "Kbrcm,overclock-50:0"; + sd_force_pio = "", "", "", "Kbrcm,force-pio?"; + sd_pio_limit = "", "", "", "Kbrcm,pio-limit:0"; + sd_debug = "", "", "", "Kbrcm,debug"; + sdio_overclock = "", "", "", "Lbrcm,overclock-50:0", "", "", "", "Mbrcm,overclock-50:0"; + axiperf = "", "", "", "Nstatus"; + drm_fb0_vc4 = "", "", "", "Odrm-fb0=", "/gpu"; + drm_fb1_vc4 = "", "", "", "Odrm-fb1=", "/gpu"; + drm_fb2_vc4 = "", "", "", "Odrm-fb2=", "/gpu"; + cam1_sync = "", "", "", "Psync-gpios:0=", "", "", "", "\a", "", "", "Psync-gpios:4", "", "", "", "Psync-gpios:8=", "", "", "", ""; + cam1_sync_inverted = [00 00 00 50 73 79 6e 63 2d 67 70 69 6f 73 3a 30 3d 00 00 00 00 07 00 00 00 50 73 79 6e 63 2d 67 70 69 6f 73 3a 34 00 00 00 00 50 73 79 6e 63 2d 67 70 69 6f 73 3a 38 3d 00 00 00 00 01]; + cam0_sync = "", "", "", "Qsync-gpios:0=", "", "", "", "\a", "", "", "Qsync-gpios:4", "", "", "", "Qsync-gpios:8=", "", "", "", ""; + cam0_sync_inverted = [00 00 00 51 73 79 6e 63 2d 67 70 69 6f 73 3a 30 3d 00 00 00 00 07 00 00 00 51 73 79 6e 63 2d 67 70 69 6f 73 3a 34 00 00 00 00 51 73 79 6e 63 2d 67 70 69 6f 73 3a 38 3d 00 00 00 00 01]; + cam0_reg = "", "", "", "Rstatus"; + cam0_reg_gpio = [00 00 00 52 67 70 69 6f 3a 34 00 00 00 00 52 67 70 69 6f 3a 30 3d 00 00 00 00 07]; + cam1_reg = "", "", "", "Sstatus"; + cam1_reg_gpio = [00 00 00 53 67 70 69 6f 3a 34 00 00 00 00 53 67 70 69 6f 3a 30 3d 00 00 00 00 07]; + strict_gpiod = "", "", "", "Tbootargs=pinctrl_bcm2835.persist_gpio_outputs=n"; + arm_freq; + eee = "", "", "", "Tbootargs{on='',off='genet.eee=N'}"; + hdmi = "", "", "", "Ustatus", "", "", "", "Vstatus"; + nvmem_cust_rw = "", "", "", "Wrw?"; + nvmem_priv_rw = "", "", "", "Xrw?"; + pcie = "", "", "", ">status"; + sd = "", "", "", "Ystatus"; + sd_poll_once = "", "", "", "Ynon-removable?"; + spi_dma4 = <0x46 0x646d6173 0x3a303d00 0x2e 0x46 0x646d6173 0x3a383d00 0x2e>; + i2s_dma4 = <0x45 0x646d6173 0x3a303d00 0x2e 0x45 0x646d6173 0x3a383d00 0x2e>; + audio = "", "", "", "Tbootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; + act_led_gpio = "", "", "", "Zgpios:4"; + act_led_activelow = "", "", "", "Zgpios:8"; + act_led_trigger = "", "", "", "Zlinux,default-trigger"; + pwr_led_gpio = "", "", "", "[gpios:4"; + pwr_led_activelow = "", "", "", "[gpios:8"; + pwr_led_trigger = "", "", "", "[linux,default-trigger"; + eth_led0 = "", "", "", "@led-modes:0"; + eth_led1 = "", "", "", "@led-modes:4"; + eth_max_speed = "", "", "", "@max-speed:0"; + }; + + regulator-cam1 { + compatible = "regulator-fixed"; + regulator-name = "cam1-reg"; + enable-active-high; + gpio = <0x0b 0x05 0x00>; + phandle = <0x53>; + }; + + regulator-sd-io-1v8 { + compatible = "regulator-gpio"; + regulator-name = "vdd-sd-io"; + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x325aa0>; + regulator-boot-on; + regulator-always-on; + regulator-settling-time-us = <0x1388>; + gpios = <0x0b 0x04 0x00>; + states = <0x1b7740 0x01 0x325aa0 0x00>; + status = "okay"; + phandle = <0x37>; + }; + + regulator-sd-vcc { + compatible = "regulator-fixed"; + regulator-name = "vcc-sd"; + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-boot-on; + enable-active-high; + gpio = <0x0b 0x06 0x00>; + phandle = <0x38>; + }; + + fixedregulator_3v3 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microvolt = <0x325aa0>; + regulator-name = "3v3"; + phandle = <0xf1>; + }; + + fixedregulator_5v0 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x4c4b40>; + regulator-min-microvolt = <0x4c4b40>; + regulator-name = "5v0"; + phandle = <0xf2>; + }; + + zone_dma { + #address-cells = <0x01>; + #size-cells = <0x01>; + dma-ranges = <0x00 0x00 0x00 0x40000000>; + }; + + v3dbus { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x02>; + ranges = <0x7c500000 0x00 0xfc500000 0x00 0x3300000 0x40000000 0x00 0xff800000 0x00 0x800000>; + dma-ranges = <0x00 0x00 0x00 0x04 0x00>; + phandle = <0xf3>; + + v3d@7ec04000 { + compatible = "brcm,2711-v3d"; + reg = <0x7ec00000 0x00 0x4000 0x7ec04000 0x00 0x4000>; + reg-names = "hub", "core0"; + power-domains = <0x49 0x01>; + resets = <0x49 0x00>; + clocks = <0x14 0x05>; + clocks-names = "v3d"; + interrupts = <0x00 0x4a 0x04>; + status = "disabled"; + phandle = <0xf4>; + }; + }; + + __symbols__ { + aliases = "/aliases"; + chosen = "/chosen"; + rmem = "/reserved-memory"; + cma = "/reserved-memory/linux,cma"; + blconfig = "/reserved-memory/nvram@0"; + blpubkey = "/reserved-memory/nvram@1"; + cpu_thermal = "/thermal-zones/cpu-thermal"; + thermal_trips = "/thermal-zones/cpu-thermal/trips"; + cooling_maps = "/thermal-zones/cpu-thermal/cooling-maps"; + soc = "/soc"; + system_timer = "/soc/timer@7e003000"; + txp = "/soc/txp@7e004000"; + clocks = "/soc/cprman@7e101000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + dpi_gpio0 = "/soc/gpio@7e200000/dpi-gpio0"; + emmc_gpio22 = "/soc/gpio@7e200000/emmc-gpio22"; + emmc_gpio34 = "/soc/gpio@7e200000/emmc-gpio34"; + emmc_gpio48 = "/soc/gpio@7e200000/emmc-gpio48"; + gpclk0_gpio4 = "/soc/gpio@7e200000/gpclk0-gpio4"; + gpclk1_gpio5 = "/soc/gpio@7e200000/gpclk1-gpio5"; + gpclk1_gpio42 = "/soc/gpio@7e200000/gpclk1-gpio42"; + gpclk1_gpio44 = "/soc/gpio@7e200000/gpclk1-gpio44"; + gpclk2_gpio6 = "/soc/gpio@7e200000/gpclk2-gpio6"; + gpclk2_gpio43 = "/soc/gpio@7e200000/gpclk2-gpio43"; + i2c0_gpio0 = "/soc/gpio@7e200000/i2c0if-gpio0"; + i2c0_gpio28 = "/soc/gpio@7e200000/i2c0if-gpio28"; + i2c0_gpio44 = "/soc/gpio@7e200000/i2c0if-gpio44"; + i2c1_gpio2 = "/soc/gpio@7e200000/i2c1-gpio2"; + i2c1_gpio44 = "/soc/gpio@7e200000/i2c1-gpio44"; + jtag_gpio22 = "/soc/gpio@7e200000/jtag-gpio22"; + pcm_gpio18 = "/soc/gpio@7e200000/pcm-gpio18"; + pcm_gpio28 = "/soc/gpio@7e200000/pcm-gpio28"; + sdhost_gpio48 = "/soc/gpio@7e200000/sdhost-gpio48"; + spi0_gpio7 = "/soc/gpio@7e200000/spi0-gpio7"; + spi0_gpio35 = "/soc/gpio@7e200000/spi0-gpio35"; + spi1_gpio16 = "/soc/gpio@7e200000/spi1-gpio16"; + spi2_gpio40 = "/soc/gpio@7e200000/spi2-gpio40"; + uart0_gpio14 = "/soc/gpio@7e200000/uart0-gpio14"; + uart0_ctsrts_gpio16 = "/soc/gpio@7e200000/uart0-ctsrts-gpio16"; + uart0_ctsrts_gpio30 = "/soc/gpio@7e200000/uart0-ctsrts-gpio30"; + uart0_gpio32 = "/soc/gpio@7e200000/uart0-gpio32"; + uart0_gpio36 = "/soc/gpio@7e200000/uart0-gpio36"; + uart0_ctsrts_gpio38 = "/soc/gpio@7e200000/uart0-ctsrts-gpio38"; + uart1_gpio14 = "/soc/gpio@7e200000/uart1-gpio14"; + uart1_ctsrts_gpio16 = "/soc/gpio@7e200000/uart1-ctsrts-gpio16"; + uart1_gpio32 = "/soc/gpio@7e200000/uart1-gpio32"; + uart1_ctsrts_gpio30 = "/soc/gpio@7e200000/uart1-ctsrts-gpio30"; + uart1_gpio40 = "/soc/gpio@7e200000/uart1-gpio40"; + uart1_ctsrts_gpio42 = "/soc/gpio@7e200000/uart1-ctsrts-gpio42"; + gpclk0_gpio49 = "/soc/gpio@7e200000/gpclk0-gpio49"; + gpclk1_gpio50 = "/soc/gpio@7e200000/gpclk1-gpio50"; + gpclk2_gpio51 = "/soc/gpio@7e200000/gpclk2-gpio51"; + i2c0_gpio46 = "/soc/gpio@7e200000/i2c0if-gpio46"; + i2c1_gpio46 = "/soc/gpio@7e200000/i2c1-gpio46"; + i2c3_gpio2 = "/soc/gpio@7e200000/i2c3-gpio2"; + i2c3_gpio4 = "/soc/gpio@7e200000/i2c3-gpio4"; + i2c4_gpio6 = "/soc/gpio@7e200000/i2c4-gpio6"; + i2c4_gpio8 = "/soc/gpio@7e200000/i2c4-gpio8"; + i2c5_gpio10 = "/soc/gpio@7e200000/i2c5-gpio10"; + i2c5_gpio12 = "/soc/gpio@7e200000/i2c5-gpio12"; + i2c6_gpio0 = "/soc/gpio@7e200000/i2c6-gpio0"; + i2c6_gpio22 = "/soc/gpio@7e200000/i2c6-gpio22"; + i2c_slave_gpio8 = "/soc/gpio@7e200000/i2c-slave-gpio8"; + jtag_gpio48 = "/soc/gpio@7e200000/jtag-gpio48"; + mii_gpio28 = "/soc/gpio@7e200000/mii-gpio28"; + mii_gpio36 = "/soc/gpio@7e200000/mii-gpio36"; + pcm_gpio50 = "/soc/gpio@7e200000/pcm-gpio50"; + pwm0_0_gpio12 = "/soc/gpio@7e200000/pwm0-0-gpio12"; + pwm0_0_gpio18 = "/soc/gpio@7e200000/pwm0-0-gpio18"; + pwm1_0_gpio40 = "/soc/gpio@7e200000/pwm1-0-gpio40"; + pwm0_1_gpio13 = "/soc/gpio@7e200000/pwm0-1-gpio13"; + pwm0_1_gpio19 = "/soc/gpio@7e200000/pwm0-1-gpio19"; + pwm1_1_gpio41 = "/soc/gpio@7e200000/pwm1-1-gpio41"; + pwm0_1_gpio45 = "/soc/gpio@7e200000/pwm0-1-gpio45"; + pwm0_0_gpio52 = "/soc/gpio@7e200000/pwm0-0-gpio52"; + pwm0_1_gpio53 = "/soc/gpio@7e200000/pwm0-1-gpio53"; + rgmii_gpio35 = "/soc/gpio@7e200000/rgmii-gpio35"; + rgmii_irq_gpio34 = "/soc/gpio@7e200000/rgmii-irq-gpio34"; + rgmii_irq_gpio39 = "/soc/gpio@7e200000/rgmii-irq-gpio39"; + rgmii_mdio_gpio28 = "/soc/gpio@7e200000/rgmii-mdio-gpio28"; + rgmii_mdio_gpio37 = "/soc/gpio@7e200000/rgmii-mdio-gpio37"; + spi0_gpio46 = "/soc/gpio@7e200000/spi0-gpio46"; + spi2_gpio46 = "/soc/gpio@7e200000/spi2-gpio46"; + spi3_gpio0 = "/soc/gpio@7e200000/spi3-gpio0"; + spi4_gpio4 = "/soc/gpio@7e200000/spi4-gpio4"; + spi5_gpio12 = "/soc/gpio@7e200000/spi5-gpio12"; + spi6_gpio18 = "/soc/gpio@7e200000/spi6-gpio18"; + uart2_gpio0 = "/soc/gpio@7e200000/uart2-gpio0"; + uart2_ctsrts_gpio2 = "/soc/gpio@7e200000/uart2-ctsrts-gpio2"; + uart3_gpio4 = "/soc/gpio@7e200000/uart3-gpio4"; + uart3_ctsrts_gpio6 = "/soc/gpio@7e200000/uart3-ctsrts-gpio6"; + uart4_gpio8 = "/soc/gpio@7e200000/uart4-gpio8"; + uart4_ctsrts_gpio10 = "/soc/gpio@7e200000/uart4-ctsrts-gpio10"; + uart5_gpio12 = "/soc/gpio@7e200000/uart5-gpio12"; + uart5_ctsrts_gpio14 = "/soc/gpio@7e200000/uart5-ctsrts-gpio14"; + gpioout = "/soc/gpio@7e200000/gpioout"; + alt0 = "/soc/gpio@7e200000/alt0"; + dpi_18bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio0"; + dpi_18bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio2"; + dpi_18bit_gpio0 = "/soc/gpio@7e200000/dpi_18bit_gpio0"; + dpi_18bit_gpio2 = "/soc/gpio@7e200000/dpi_18bit_gpio2"; + dpi_16bit_gpio0 = "/soc/gpio@7e200000/dpi_16bit_gpio0"; + dpi_16bit_gpio2 = "/soc/gpio@7e200000/dpi_16bit_gpio2"; + dpi_16bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio0"; + dpi_16bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio2"; + spi0_pins = "/soc/gpio@7e200000/spi0_pins"; + spi0_cs_pins = "/soc/gpio@7e200000/spi0_cs_pins"; + spi3_pins = "/soc/gpio@7e200000/spi3_pins"; + spi3_cs_pins = "/soc/gpio@7e200000/spi3_cs_pins"; + spi4_pins = "/soc/gpio@7e200000/spi4_pins"; + spi4_cs_pins = "/soc/gpio@7e200000/spi4_cs_pins"; + spi5_pins = "/soc/gpio@7e200000/spi5_pins"; + spi5_cs_pins = "/soc/gpio@7e200000/spi5_cs_pins"; + spi6_pins = "/soc/gpio@7e200000/spi6_pins"; + spi6_cs_pins = "/soc/gpio@7e200000/spi6_cs_pins"; + i2c0_pins = "/soc/gpio@7e200000/i2c0"; + i2c1_pins = "/soc/gpio@7e200000/i2c1"; + i2c3_pins = "/soc/gpio@7e200000/i2c3"; + i2c4_pins = "/soc/gpio@7e200000/i2c4"; + i2c5_pins = "/soc/gpio@7e200000/i2c5"; + i2c6_pins = "/soc/gpio@7e200000/i2c6"; + i2s_pins = "/soc/gpio@7e200000/i2s"; + sdio_pins = "/soc/gpio@7e200000/sdio_pins"; + uart2_pins = "/soc/gpio@7e200000/uart2_pins"; + uart3_pins = "/soc/gpio@7e200000/uart3_pins"; + uart4_pins = "/soc/gpio@7e200000/uart4_pins"; + uart5_pins = "/soc/gpio@7e200000/uart5_pins"; + bt_pins = "/soc/gpio@7e200000/bt_pins"; + uart0_pins = "/soc/gpio@7e200000/uart0_pins"; + uart1_pins = "/soc/gpio@7e200000/uart1_pins"; + uart1_bt_pins = "/soc/gpio@7e200000/uart1_bt_pins"; + audio_pins = "/soc/gpio@7e200000/audio_pins"; + uart0 = "/soc/serial@7e201000"; + bt = "/soc/serial@7e201000/bluetooth"; + sdhost = "/soc/mmc@7e202000"; + i2s_clk_consumer = "/soc/i2s@7e203000"; + i2s_clk_producer = "/soc/i2s@7e203000"; + i2s = "/soc/i2s@7e203000"; + spi0 = "/soc/spi@7e204000"; + spi = "/soc/spi@7e204000"; + spidev0 = "/soc/spi@7e204000/spidev@0"; + spidev1 = "/soc/spi@7e204000/spidev@1"; + i2c0if = "/soc/i2c@7e205000"; + dpi = "/soc/dpi@7e208000"; + dsi0 = "/soc/dsi@7e209000"; + aux = "/soc/aux@7e215000"; + uart1 = "/soc/serial@7e215040"; + minibt = "/soc/serial@7e215040/bluetooth"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + pwm = "/soc/pwm@7e20c000"; + mmc = "/soc/mmc@7e300000"; + sdhci = "/soc/mmc@7e300000"; + hvs = "/soc/hvs@7e400000"; + dsi1 = "/soc/dsi@7e700000"; + csi0 = "/soc/csi@7e800000"; + csi1 = "/soc/csi@7e801000"; + i2c_arm = "/soc/i2c@7e804000"; + i2c1 = "/soc/i2c@7e804000"; + usb = "/soc/usb@7e980000"; + local_intc = "/soc/interrupt-controller@40000000"; + gicv2 = "/soc/interrupt-controller@40041000"; + avs_monitor = "/soc/avs-monitor@7d5d2000"; + thermal = "/soc/avs-monitor@7d5d2000/thermal"; + dma = "/soc/dma-controller@7e007000"; + watchdog = "/soc/watchdog@7e100000"; + pm = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + uart2 = "/soc/serial@7e201400"; + uart3 = "/soc/serial@7e201600"; + uart4 = "/soc/serial@7e201800"; + uart5 = "/soc/serial@7e201a00"; + spi3 = "/soc/spi@7e204600"; + spi4 = "/soc/spi@7e204800"; + spi5 = "/soc/spi@7e204a00"; + spi6 = "/soc/spi@7e204c00"; + i2c3 = "/soc/i2c@7e205600"; + i2c4 = "/soc/i2c@7e205800"; + i2c5 = "/soc/i2c@7e205a00"; + i2c6 = "/soc/i2c@7e205c00"; + pixelvalve0 = "/soc/pixelvalve@7e206000"; + pixelvalve1 = "/soc/pixelvalve@7e207000"; + pixelvalve2 = "/soc/pixelvalve@7e20a000"; + pwm1 = "/soc/pwm@7e20c800"; + pixelvalve4 = "/soc/pixelvalve@7e216000"; + pixelvalve3 = "/soc/pixelvalve@7ec12000"; + vec = "/soc/vec@7ec13000"; + dvp = "/soc/clock@7ef00000"; + aon_intr = "/soc/interrupt-controller@7ef00100"; + hdmi0 = "/soc/hdmi@7ef00700"; + ddc0 = "/soc/i2c@7ef04500"; + hdmi1 = "/soc/hdmi@7ef05700"; + ddc1 = "/soc/i2c@7ef09500"; + firmware = "/soc/firmware"; + firmware_clocks = "/soc/firmware/clocks"; + expgpio = "/soc/firmware/gpio"; + reset = "/soc/firmware/reset"; + vcio = "/soc/firmware/vcio"; + power = "/soc/power"; + vchiq = "/soc/mailbox@7e00b840"; + mmcnr = "/soc/mmcnr@7e300000"; + brcmf = "/soc/mmcnr@7e300000/wifi@1"; + firmwarekms = "/soc/firmwarekms@7e600000"; + smi = "/soc/smi@7e600000"; + axiperf = "/soc/axiperf"; + i2c0mux = "/soc/i2c0mux"; + i2c_csi_dsi0 = "/soc/i2c0mux/i2c@0"; + i2c_vc = "/soc/i2c0mux/i2c@0"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c_csi_dsi = "/soc/i2c0mux/i2c@1"; + fb = "/soc/fb"; + sound = "/soc/sound"; + nvmem_otp = "/soc/nvmem/nvmem_otp"; + nvmem_cust = "/soc/nvmem/nvmem_cust"; + nvmem_priv = "/soc/nvmem/nvmem_priv"; + clk_osc = "/clocks/clk-osc"; + clk_usb = "/clocks/clk-usb"; + usbphy = "/phy"; + vc4 = "/gpu"; + clk_27MHz = "/clk-27M"; + clk_108MHz = "/clk-108M"; + emmc2bus = "/emmc2bus"; + emmc2 = "/emmc2bus/mmc@7e340000"; + cpus = "/cpus"; + cpu0 = "/cpus/cpu@0"; + cpu1 = "/cpus/cpu@1"; + cpu2 = "/cpus/cpu@2"; + cpu3 = "/cpus/cpu@3"; + l2 = "/cpus/l2-cache0"; + scb = "/scb"; + pcie0 = "/scb/pcie@7d500000"; + genet = "/scb/ethernet@7d580000"; + genet_mdio = "/scb/ethernet@7d580000/mdio@e14"; + phy1 = "/scb/ethernet@7d580000/mdio@e14/ethernet-phy@1"; + hevc_dec = "/scb/codec@7eb10000"; + dma40 = "/scb/dma@7e007b00"; + xhci = "/scb/xhci@7e9c0000"; + leds = "/leds"; + led_act = "/leds/led-act"; + led_pwr = "/leds/led-pwr"; + cam1_clk = "/cam1_clk"; + cam0_regulator = "/cam0_regulator"; + cam0_clk = "/cam0_clk"; + cam0_reg = "/cam_dummy_reg"; + cam_dummy_reg = "/cam_dummy_reg"; + cam1_reg = "/regulator-cam1"; + sd_io_1v8_reg = "/regulator-sd-io-1v8"; + sd_vcc_reg = "/regulator-sd-vcc"; + vdd_3v3_reg = "/fixedregulator_3v3"; + vdd_5v0_reg = "/fixedregulator_5v0"; + v3dbus = "/v3dbus"; + v3d = "/v3dbus/v3d@7ec04000"; + }; +}; diff --git a/kernel/driver/bsp/bcm283x/src/cprman.rs b/kernel/driver/bsp/bcm283x/src/cprman.rs new file mode 100644 index 00000000..dbaf418d --- /dev/null +++ b/kernel/driver/bsp/bcm283x/src/cprman.rs @@ -0,0 +1,78 @@ +use alloc::sync::Arc; +use device_api::{ + clock::{ClockController, ClockHandle, Hertz}, + device::{Device, DeviceInitContext}, +}; +use device_tree::{ + DeviceTreePropertyRead, TProp, + driver::{DeviceTreeClockController, Node, ProbeContext, device_tree_driver}, +}; +use libk::error::Error; + +struct Cprman { + clk_osc: ClockHandle, +} + +impl Device for Cprman { + unsafe fn init(self: Arc, _cx: DeviceInitContext) -> Result<(), Error> { + let _ = &self.clk_osc; + Ok(()) + } + + fn display_name(&self) -> &str { + "bcm2711-cprman" + } +} + +impl ClockController for Cprman { + fn clock_rate(&self, clock: Option) -> Result { + let _ = clock; + todo!() + } + + fn set_clock_rate(&self, clock: Option, rate: Hertz) -> Result { + let _ = clock; + let _ = rate; + todo!() + } + + fn enable_clock(&self, clock: Option) -> Result<(), Error> { + let _ = clock; + todo!() + } + + fn disable_clock(&self, clock: Option) -> Result<(), Error> { + let _ = clock; + todo!() + } +} + +impl DeviceTreeClockController for Cprman { + fn map_clock(self: Arc, property: &TProp, offset: usize) -> Option<(ClockHandle, usize)> { + let clock = property.read_cell(offset, 1)? as u32; + Some(( + ClockHandle { + parent: self.clone(), + clock: Some(clock), + }, + 1, + )) + } +} + +device_tree_driver! { + compatible: ["brcm,bcm2711-cprman"], + driver: { + fn probe(&self, node: &Arc, context: &mut ProbeContext) -> Option> { + let _base = node.map_base(context, 0)?; + let clk_osc = node.clock(0)?; + + let cprman = Arc::new(Cprman { + clk_osc + }); + + node.make_clock_controller(cprman.clone()); + Some(cprman) + } + } +} diff --git a/kernel/driver/bsp/bcm283x/src/i2c.rs b/kernel/driver/bsp/bcm283x/src/i2c.rs new file mode 100644 index 00000000..b3cad8e9 --- /dev/null +++ b/kernel/driver/bsp/bcm283x/src/i2c.rs @@ -0,0 +1,290 @@ +use alloc::sync::Arc; +use device_api::{ + clock::{ClockHandle, Hertz}, + device::{Device, DeviceInitContext}, + i2c::{I2CAddress, I2CController}, + interrupt::{InterruptHandler, IrqHandle, IrqVector}, +}; +use device_tree::driver::{Node, ProbeContext, device_tree_driver}; +use libk::{device::manager::DEVICE_REGISTRY, error::Error}; +use libk_mm::device::DeviceMemoryIo; +use libk_util::{OneTimeInit, sync::spin_rwlock::IrqSafeRwLock}; +use tock_registers::{ + interfaces::{ReadWriteable, Readable, Writeable}, + register_bitfields, register_structs, + registers::ReadWrite, +}; +use yggdrasil_abi::io::device::i2c::I2CMasterInfo; + +register_bitfields! { + u32, + C [ + I2CEN OFFSET(15) NUMBITS(1) [], + INTR OFFSET(10) NUMBITS(1) [], + INTT OFFSET(9) NUMBITS(1) [], + INTD OFFSET(8) NUMBITS(1) [], + ST OFFSET(7) NUMBITS(1) [], + CLEAR OFFSET(4) NUMBITS(2) [], + READ OFFSET(0) NUMBITS(1) [], + ], + S [ + CLKT OFFSET(9) NUMBITS(1) [], + ERR OFFSET(8) NUMBITS(1) [], + RXF OFFSET(7) NUMBITS(1) [], + TXE OFFSET(6) NUMBITS(1) [], + RXD OFFSET(5) NUMBITS(1) [], + TXD OFFSET(4) NUMBITS(1) [], + RXR OFFSET(3) NUMBITS(1) [], + TXW OFFSET(2) NUMBITS(1) [], + DONE OFFSET(1) NUMBITS(1) [], + TA OFFSET(0) NUMBITS(1) [], + ], +} + +register_structs! { + #[allow(non_snake_case)] + Regs { + (0x00 => C: ReadWrite), + (0x04 => S: ReadWrite), + (0x08 => DLEN: ReadWrite), + (0x0C => A: ReadWrite), + (0x10 => FIFO: ReadWrite), + (0x14 => DIV: ReadWrite), + (0x18 => DEL: ReadWrite), + (0x1C => CLKT: ReadWrite), + (0x20 => @END), + } +} + +struct I2C { + name: &'static str, + clock_frequency: Option, + irq: IrqHandle, + clock: Option, + regs: IrqSafeRwLock>, + index: OneTimeInit, +} + +impl Regs { + fn start_transfer(&self, name: &str, buflen: u16, address: I2CAddress, read: bool) { + log::debug!( + "{}: start address={}, read={}, len={}", + name, + address, + read, + buflen + ); + + let address = address.as_8_bit().unwrap(); + let read = if read { C::READ::SET } else { C::READ::CLEAR }; + + self.S.write(S::ERR::SET + S::DONE::SET); + self.DLEN.set(buflen as u32); + self.C.modify(C::ST::CLEAR + C::I2CEN::CLEAR); + self.A.set(address as u32); + self.C.modify(read + C::ST::SET + C::I2CEN::SET); + } + + fn finish_transfer(&self, name: &str) -> Result<(), Error> { + log::debug!("{}: finish transfer", name); + let status = self.S.extract(); + self.C.set(0); + if status.matches_all(S::ERR::SET) { + self.S.write(S::DONE::SET + S::ERR::SET); + return Err(Error::HostUnreachable); + } + if status.matches_all(S::DONE::SET) { + self.S.write(S::DONE::SET); + } + + Ok(()) + } + + fn write_byte(&self, byte: u8) -> Result { + loop { + let status = self.S.extract(); + if status.matches_all(S::ERR::SET) { + self.C.write(C::CLEAR.val(1)); + self.S.write(S::ERR::SET + S::DONE::SET); + // TODO better code + return Err(Error::HostUnreachable); + } + if status.matches_all(S::DONE::SET) { + self.C.set(0); + self.S.write(S::DONE::SET); + return Ok(false); + } + if status.matches_all(S::TXD::SET) { + self.FIFO.set(byte as u32); + return Ok(true); + } + + core::hint::spin_loop(); + } + } + + fn read_byte(&self) -> Result, Error> { + loop { + let status = self.S.extract(); + if status.matches_all(S::ERR::SET) { + self.C.write(C::CLEAR.val(1)); + self.S.write(S::ERR::SET + S::DONE::SET); + // TODO better code + return Err(Error::HostUnreachable); + } + if status.matches_all(S::DONE::SET) { + self.C.set(0); + self.S.write(S::DONE::SET); + return Ok(None); + } + if status.matches_all(S::RXD::SET) { + let val = self.FIFO.get() as u8; + return Ok(Some(val)); + } + + core::hint::spin_loop(); + } + } +} + +impl Device for I2C { + unsafe fn init(self: Arc, _cx: DeviceInitContext) -> Result<(), Error> { + // TODO + let _ = &self.clock; + + log::info!("{}: initialize", self.name); + let regs = self.regs.write(); + regs.C.set(0); + + let index = DEVICE_REGISTRY.i2c.register_bus(self.clone())?; + self.index.init(index); + Ok(()) + } + + unsafe fn init_irq(self: Arc) -> Result<(), Error> { + // TODO + let _ = &self.irq; + // self.irq.register(self.clone())?; + // self.irq.enable()?; + // let regs = self.regs.write(); + // regs.C.modify(C::INTD::SET); + Ok(()) + } + + fn display_name(&self) -> &str { + self.name + } +} + +impl InterruptHandler for I2C { + fn handle_irq(self: Arc, _vector: IrqVector) -> bool { + todo!() + } +} + +impl I2CController for I2C { + fn bus_number(&self) -> u32 { + *self.index.get() + } + + fn child_number(&self) -> Option { + None + } + + fn set_speed(&self, speed: Hertz) -> Result { + if let Some(frequency) = self.clock_frequency { + // Fixed frequency + if speed == frequency { + Ok(speed) + } else { + Err(Error::InvalidArgument) + } + } else { + todo!("Set i2c speed = {speed}") + } + } + + fn capabilities(&self) -> I2CMasterInfo { + let max_speed_hz = if let Some(frequency) = self.clock_frequency { + frequency + } else { + todo!() + } + .0 as u32; + I2CMasterInfo { + max_speed_hz, + supports_10bit_addresses: true, + } + } + + fn i2c_write(&self, address: I2CAddress, buffer: &[u8]) -> Result { + let buflen: u16 = buffer + .len() + .try_into() + .map_err(|_| Error::InvalidArgument)?; + let regs = self.regs.write(); + // TODO DMA/interrupts + regs.start_transfer(self.name, buflen, address, false); + let mut bytes_written = 0; + // let mut done = false; + for &byte in buffer { + if regs.write_byte(byte)? { + bytes_written += 1; + } else { + break; + } + } + regs.finish_transfer(self.name)?; + Ok(bytes_written) + } + + fn i2c_read(&self, address: I2CAddress, buffer: &mut [u8]) -> Result { + let buflen: u16 = buffer + .len() + .try_into() + .map_err(|_| Error::InvalidArgument)?; + let regs = self.regs.write(); + // TODO DMA/interrupts + regs.start_transfer(self.name, buflen, address, true); + let mut bytes_read = 0; + // let mut done = false; + for byte in buffer { + if let Some(val) = regs.read_byte()? { + *byte = val; + bytes_read += 1; + } else { + break; + } + } + regs.finish_transfer(self.name)?; + Ok(bytes_read) + } +} + +device_tree_driver! { + compatible: ["brcm,bcm2711-i2c", "brcm,bcm2835-i2c"], + driver: { + fn probe(&self, node: &Arc, context: &mut ProbeContext) -> Option> { + let clock_frequency = node.prop_usize("clock-frequency").map(|p| Hertz(p as u64)); + let base = node.map_base(context, 0)?; + let name = node.name().unwrap_or("bcm2835-i2c"); + let irq = node.interrupt(0)?; + let clock = node.clock(0); + + let regs = unsafe { DeviceMemoryIo::map(base, Default::default()) }.ok()?; + + let i2c = Arc::new(I2C { + name, + clock_frequency, + irq, + clock, + index: OneTimeInit::new(), + regs: IrqSafeRwLock::new(regs) + }); + + node.make_i2c_controller(i2c.clone()); + + Some(i2c) + } + } +} diff --git a/kernel/driver/bsp/bcm283x/src/lib.rs b/kernel/driver/bsp/bcm283x/src/lib.rs index 2169ad47..1712c336 100644 --- a/kernel/driver/bsp/bcm283x/src/lib.rs +++ b/kernel/driver/bsp/bcm283x/src/lib.rs @@ -4,5 +4,7 @@ extern crate alloc; mod aux; // mod aux_uart; +mod cprman; mod gpio; +mod i2c; mod mbox; diff --git a/kernel/lib/device-api/src/clock/freq.rs b/kernel/lib/device-api/src/clock/freq.rs index 0dfa1e00..d666c711 100644 --- a/kernel/lib/device-api/src/clock/freq.rs +++ b/kernel/lib/device-api/src/clock/freq.rs @@ -26,6 +26,18 @@ pub trait IntoHertz { } } +impl From for Hertz { + fn from(value: u32) -> Self { + Self(value as u64) + } +} + +impl From for Hertz { + fn from(value: u64) -> Self { + Self(value) + } +} + impl Mul for Hertz { type Output = Hertz; diff --git a/kernel/lib/device-api/src/i2c.rs b/kernel/lib/device-api/src/i2c.rs new file mode 100644 index 00000000..9310ff00 --- /dev/null +++ b/kernel/lib/device-api/src/i2c.rs @@ -0,0 +1,147 @@ +use core::{ + fmt, + ops::Deref, + sync::atomic::{AtomicU16, AtomicU32, Ordering}, +}; + +use alloc::sync::Arc; +use yggdrasil_abi::{error::Error, io::device::i2c::I2CMasterInfo, process::ProcessId}; + +use crate::{ + clock::Hertz, + device::{Device, DeviceInitContext}, +}; + +pub struct I2CAddress(u16); + +pub struct I2CDevice { + device: Arc, + address: AtomicU16, + user: AtomicU32, +} + +pub trait I2CController: Device { + fn bus_number(&self) -> u32; + fn child_number(&self) -> Option; + + fn set_speed(&self, speed: Hertz) -> Result; + fn capabilities(&self) -> I2CMasterInfo; + + fn i2c_write(&self, address: I2CAddress, buffer: &[u8]) -> Result; + fn i2c_read(&self, address: I2CAddress, buffer: &mut [u8]) -> Result; +} + +impl I2CAddress { + pub fn as_8_bit(&self) -> Option { + self.0.try_into().ok() + } + + pub fn as_10_bit(&self) -> u16 { + self.0 + } + + pub fn is_8_bit(&self) -> bool { + self.0 <= 0xFF + } +} + +impl fmt::Display for I2CAddress { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + +impl From for I2CAddress { + fn from(value: u8) -> Self { + Self(value as u16) + } +} + +impl TryFrom for I2CAddress { + type Error = Error; + + fn try_from(value: u16) -> Result { + if value >= (1 << 10) { + return Err(Error::InvalidArgument); + } + Ok(Self(value)) + } +} + +impl Deref for I2CDevice { + type Target = dyn I2CController; + + fn deref(&self) -> &Self::Target { + &*self.device + } +} + +impl From> for I2CDevice { + fn from(value: Arc) -> Self { + Self { + device: value, + address: AtomicU16::new(0), + user: AtomicU32::new(0), + } + } +} + +impl I2CDevice { + pub fn set_slave_address(&self, address: I2CAddress) { + self.address.store(address.0, Ordering::Release); + } + + pub fn set_speed(&self, speed: Hertz) -> Result { + self.device.set_speed(speed) + } + + pub fn slave_address(&self) -> I2CAddress { + I2CAddress(self.address.load(Ordering::Acquire)) + } + + pub fn check_lock(&self, id: ProcessId) -> Result<(), Error> { + if self.user.load(Ordering::Acquire) == id.bits() { + Ok(()) + } else { + Err(Error::PermissionDenied) + } + } + + pub fn lock(&self, process: ProcessId) -> Result<(), Error> { + if self + .user + .compare_exchange(0, process.bits(), Ordering::Acquire, Ordering::Relaxed) + .is_ok() + { + Ok(()) + } else { + Err(Error::WouldBlock) + } + } + + pub fn release(&self, process: ProcessId) -> Result<(), Error> { + if self + .user + .compare_exchange(process.bits(), 0, Ordering::Release, Ordering::Relaxed) + .is_ok() + { + Ok(()) + } else { + Err(Error::InvalidOperation) + } + } +} + +impl Device for I2CDevice { + unsafe fn init(self: Arc, cx: DeviceInitContext) -> Result<(), Error> { + self.device.clone().init(cx) + } + + unsafe fn init_irq(self: Arc) -> Result<(), Error> { + self.device.clone().init_irq() + } + + fn display_name(&self) -> &str { + self.device.display_name() + } +} diff --git a/kernel/lib/device-api/src/lib.rs b/kernel/lib/device-api/src/lib.rs index 0d38f71a..af3d34d2 100644 --- a/kernel/lib/device-api/src/lib.rs +++ b/kernel/lib/device-api/src/lib.rs @@ -8,6 +8,7 @@ pub mod bus; pub mod clock; pub mod device; pub mod gpio; +pub mod i2c; pub mod interrupt; pub mod serial; pub mod timer; diff --git a/kernel/lib/device-tree/src/driver/macros.rs b/kernel/lib/device-tree/src/driver/macros.rs index 49f4eaee..df7cd59d 100644 --- a/kernel/lib/device-tree/src/driver/macros.rs +++ b/kernel/lib/device-tree/src/driver/macros.rs @@ -9,6 +9,10 @@ /// `.init_array`-based mechanism. pub macro device_tree_driver( compatible: [$($compatible:literal),+ $(,)?], + $(config: { + $($config_field:ident : $config_value:expr),+ + $(,)? + },)? driver: $driver:tt ) { struct __DtDriver; @@ -21,8 +25,15 @@ pub macro device_tree_driver( static __REGISTER_FN: extern "C" fn() = __register_fn; extern "C" fn __register_fn() { + let config = $crate::driver::DriverConfig { + $( + $($config_field: $config_value,)+ + )? + ..Default::default() + }; $crate::driver::register_driver( &[$($compatible),+], + config, &__DT_DRIVER ) } diff --git a/kernel/lib/device-tree/src/driver/mod.rs b/kernel/lib/device-tree/src/driver/mod.rs index 862aa545..95d5e699 100644 --- a/kernel/lib/device-tree/src/driver/mod.rs +++ b/kernel/lib/device-tree/src/driver/mod.rs @@ -15,7 +15,7 @@ pub mod util; pub use controller::{map_interrupt, map_interrupt_at}; pub use macros::device_tree_driver; -pub use registry::{lookup_phandle, register_driver}; +pub use registry::{DriverConfig, lookup_phandle, register_driver}; pub use syscon::DeviceTreeSyscon; pub use traits::{ DeviceTreeClockController, DeviceTreeInterruptController, DeviceTreePinController, diff --git a/kernel/lib/device-tree/src/driver/registry.rs b/kernel/lib/device-tree/src/driver/registry.rs index 25efd0b2..5ef42bc4 100644 --- a/kernel/lib/device-tree/src/driver/registry.rs +++ b/kernel/lib/device-tree/src/driver/registry.rs @@ -7,8 +7,22 @@ use crate::DeviceTree; use super::{Driver, Node}; +/// Device tree driver configuration +#[derive(Debug)] +pub struct DriverConfig { + /// If `false`, pinctrl setup for the node needs to be performed manually + pub auto_pinctrl: bool, +} + +impl Default for DriverConfig { + fn default() -> Self { + Self { auto_pinctrl: true } + } +} + pub(crate) struct DriverRegistration { pub(crate) compatible: &'static [&'static str], + pub(crate) config: DriverConfig, pub(crate) imp: &'static dyn Driver, } @@ -25,9 +39,14 @@ impl DriverRegistration { } #[doc(hidden)] -pub fn register_driver(compatible: &'static [&'static str], driver: &'static dyn Driver) { +pub fn register_driver( + compatible: &'static [&'static str], + config: DriverConfig, + driver: &'static dyn Driver, +) { DRIVERS.write().push(DriverRegistration { compatible, + config, imp: driver, }); } diff --git a/kernel/lib/device-tree/src/driver/tree.rs b/kernel/lib/device-tree/src/driver/tree.rs index 511e8e87..132bd903 100644 --- a/kernel/lib/device-tree/src/driver/tree.rs +++ b/kernel/lib/device-tree/src/driver/tree.rs @@ -10,6 +10,7 @@ use device_api::{ clock::{ClockController, ClockHandle, ResetHandle}, device::{Device, DeviceInitContext}, gpio::PinHandle, + i2c::I2CController, interrupt::{ExternalInterruptController, IrqHandle, MessageInterruptController}, }; use fdt_rs::spec::Phandle; @@ -61,6 +62,7 @@ pub struct Node { pub(crate) reset_controller: OneTimeInit>, pub(crate) system_controller: OneTimeInit>, pub(crate) pin_controller: OneTimeInit>, + pub(crate) i2c_controller: OneTimeInit>, } pub(crate) struct ProbedDevice { @@ -105,24 +107,26 @@ impl Node { .as_str_list() .find_map(|c| drivers.iter().find(|d| d.matches(c))); - // if libk::config::get().device_tree.log_missing && driver.is_none() { - // // FIXME don't spam virtio missing stuff - // if !name.is_some_and(|n| n.starts_with("virtio_mmio")) { - // for (i, compatible) in compatible.as_str_list().enumerate() { - // if i == 0 { - // log::warn!("No driver for {name:?} ({compatible:?})"); - // } else { - // log::warn!(" also {compatible:?}"); - // } - // } - // } - // } + if libk::config::get().device_tree.log_missing && driver.is_none() { + // FIXME don't spam virtio missing stuff + if !name.is_some_and(|n| n.starts_with("virtio_mmio")) { + for (i, compatible) in compatible.as_str_list().enumerate() { + if i == 0 { + log::warn!("No driver for {name:?} ({compatible:?})"); + } else { + log::warn!(" also {compatible:?}"); + } + } + } + } let driver = driver?; // Initialize default pinctrl before probing - node.setup_pins() - .inspect_err(|e| log::error!("{name:?}: pinctrl init error {e:?}")) - .ok()?; + if driver.config.auto_pinctrl { + node.setup_pins(0) + .inspect_err(|e| log::error!("{name:?}: pinctrl init error {e:?}")) + .ok()?; + } let device = driver.imp.probe(node, cx); @@ -198,6 +202,11 @@ impl Node { self.interrupt_controller.init(intc); } + /// Makes node an I²C controller node + pub fn make_i2c_controller(&self, i2c: Arc) { + self.i2c_controller.init(i2c); + } + /// When called from an msi-controller driver, informs the node of its capability as an MSI /// controller. pub fn make_msi_controller(&self, intc: Arc) { @@ -451,6 +460,11 @@ impl Node { self.pin_controller.try_get().cloned() } + /// Attempts to get an I2C controller represented by this node, if any + pub fn as_i2c_controller(&self) -> Option> { + self.i2c_controller.try_get().cloned() + } + /// Returns the `#address-cells` value of the node's parent bus pub fn bus_address_cells(&self) -> usize { self.bus_address_cells @@ -527,9 +541,11 @@ impl Node { tree::dump(self.dt_node.clone(), 0); } - fn setup_pins(&self) -> Result<(), Error> { + /// Configure the `index`th pinctrl mode for the peripheral node + pub fn setup_pins(&self, index: usize) -> Result<(), Error> { // TODO lookup pin state by name - let Some(pinctrl0) = self.prop_usize("pinctrl-0") else { + let field_name = alloc::format!("pinctrl-{index}"); + let Some(pinctrl0) = self.prop_usize(&field_name) else { return Ok(()); }; let pinctrl0 = lookup_phandle(pinctrl0 as Phandle, false).ok_or(Error::DoesNotExist)?; @@ -596,6 +612,7 @@ fn unflatten_node( reset_controller: OneTimeInit::new(), system_controller: OneTimeInit::new(), pin_controller: OneTimeInit::new(), + i2c_controller: OneTimeInit::new(), }); if let Some(phandle) = phandle { diff --git a/kernel/libk/src/device/char.rs b/kernel/libk/src/device/char.rs index 92cad3fe..ad84bf53 100644 --- a/kernel/libk/src/device/char.rs +++ b/kernel/libk/src/device/char.rs @@ -1,11 +1,27 @@ -use core::{any::Any, ops::Deref}; +use core::{ + any::Any, + ops::Deref, + task::{Context, Poll}, +}; use alloc::{boxed::Box, sync::Arc}; use async_trait::async_trait; -use device_api::device::Device; -use yggdrasil_abi::error::Error; +use device_api::{ + clock::Hertz, + device::Device, + i2c::{I2CAddress, I2CDevice}, +}; +use yggdrasil_abi::{ + error::Error, + io::device::i2c::{self, I2CRequestVariant}, + option::RequestValue, + process::ProcessId, +}; -use crate::vfs::{CommonImpl, FileReadiness, NodeRef}; +use crate::{ + task::thread::Thread, + vfs::{CommonImpl, FileReadiness, NodeRef}, +}; #[async_trait] pub trait CharDevice: Device + FileReadiness { @@ -25,6 +41,15 @@ pub trait CharDevice: Device + FileReadiness { Err(Error::NotImplemented) } + fn lock(&self, process: ProcessId) -> Result<(), Error> { + let _ = process; + Ok(()) + } + fn release(&self, process: ProcessId) -> Result<(), Error> { + let _ = process; + Ok(()) + } + fn is_readable(&self) -> bool { true } @@ -65,3 +90,63 @@ impl Deref for CharDeviceFile { self.0.as_ref() } } + +// TODO timeouts and better access +#[async_trait] +impl CharDevice for I2CDevice { + async fn read(&self, buffer: &mut [u8]) -> Result { + self.read_nonblocking(buffer) + } + async fn write(&self, buffer: &[u8]) -> Result { + self.write_nonblocking(buffer) + } + fn read_nonblocking(&self, buffer: &mut [u8]) -> Result { + let pid = Thread::current().process_id(); + self.check_lock(pid)?; + self.i2c_read(self.slave_address(), buffer) + } + fn write_nonblocking(&self, buffer: &[u8]) -> Result { + let pid = Thread::current().process_id(); + self.check_lock(pid)?; + self.i2c_write(self.slave_address(), buffer) + } + fn device_request(&self, option: u32, buffer: &mut [u8], len: usize) -> Result { + if let Ok(req) = I2CRequestVariant::try_from(option) { + match req { + I2CRequestVariant::SetAddress => { + let address = i2c::SetAddress::load_request(&buffer[..len])?; + let address = I2CAddress::try_from(address)?; + self.set_slave_address(address); + Ok(0) + } + I2CRequestVariant::SetSpeed => { + let speed = i2c::SetSpeed::load_request(&buffer[..len])?; + let speed = Hertz::from(speed); + let actual = self.set_speed(speed)?.0 as u32; + let len = i2c::SetSpeed::store_response(&actual, buffer)?; + Ok(len) + } + I2CRequestVariant::GetMasterInfo => { + let info = self.capabilities(); + let len = i2c::GetMasterInfo::store_response(&info, buffer)?; + Ok(len) + } + } + } else { + Err(Error::InvalidArgument) + } + } + + fn lock(&self, process: ProcessId) -> Result<(), Error> { + I2CDevice::lock(self, process) + } + fn release(&self, process: ProcessId) -> Result<(), Error> { + I2CDevice::release(self, process) + } +} +impl FileReadiness for I2CDevice { + fn poll_read(&self, cx: &mut Context<'_>) -> Poll> { + let _ = cx; + todo!() + } +} diff --git a/kernel/libk/src/device/manager.rs b/kernel/libk/src/device/manager.rs index 0db9f705..e13a4a12 100644 --- a/kernel/libk/src/device/manager.rs +++ b/kernel/libk/src/device/manager.rs @@ -4,6 +4,7 @@ use core::{ }; use alloc::{collections::BTreeMap, format, sync::Arc, vec::Vec}; +use device_api::i2c::{I2CController, I2CDevice}; use libk_util::{OneTimeInit, sync::spin_rwlock::IrqSafeRwLock}; use yggdrasil_abi::{error::Error, io::FileMode}; @@ -46,16 +47,23 @@ pub struct SerialTerminalRegistry { registry: GenericRegistry>, } +// Manages devices: i2c, i2c- +pub struct I2CDeviceRegistry { + registry: GenericRegistry>, +} + pub struct DeviceRegistry { pub display: DisplayDeviceRegistry, pub terminal: TerminalRegistry, pub serial_terminal: SerialTerminalRegistry, + pub i2c: I2CDeviceRegistry, } pub static DEVICE_REGISTRY: DeviceRegistry = DeviceRegistry { display: DisplayDeviceRegistry::new(), terminal: TerminalRegistry::new(), serial_terminal: SerialTerminalRegistry::new(), + i2c: I2CDeviceRegistry::new(), }; impl TerminalRegistry { @@ -117,6 +125,22 @@ impl DisplayDeviceRegistry { } } +impl I2CDeviceRegistry { + pub const fn new() -> Self { + Self { + registry: GenericRegistry::new(), + } + } + + pub fn register_bus(&self, device: Arc) -> Result { + let wrapper = Arc::new(I2CDevice::from(device)); + let id = self.registry.register(wrapper.clone())?; + let name = format!("i2c{id}"); + devfs::add_named_char_device(wrapper.clone(), &name, FileMode::new(0o600))?; + Ok(id) + } +} + impl GenericRegistry { pub const fn new() -> Self { Self { diff --git a/kernel/libk/src/vfs/file/device.rs b/kernel/libk/src/vfs/file/device.rs index 97c9a95e..c509b594 100644 --- a/kernel/libk/src/vfs/file/device.rs +++ b/kernel/libk/src/vfs/file/device.rs @@ -1,5 +1,5 @@ use libk_util::sync::IrqSafeSpinlock; -use yggdrasil_abi::{error::Error, io::SeekFrom}; +use yggdrasil_abi::{error::Error, io::SeekFrom, process::ProcessId}; use crate::{ device::{block::BlockDeviceFile, char::CharDeviceFile}, @@ -20,6 +20,7 @@ pub struct CharFile { pub(super) node: NodeRef, pub(super) read: bool, pub(super) write: bool, + pub(super) pid: ProcessId, } impl BlockFile { @@ -103,3 +104,10 @@ impl CharFile { self.device.0.is_terminal() } } + +impl Drop for CharFile { + fn drop(&mut self) { + // TODO doesn't work with fork + self.device.release(self.pid).ok(); + } +} diff --git a/kernel/libk/src/vfs/file/mod.rs b/kernel/libk/src/vfs/file/mod.rs index 4016a5ad..1d0813f1 100644 --- a/kernel/libk/src/vfs/file/mod.rs +++ b/kernel/libk/src/vfs/file/mod.rs @@ -33,7 +33,7 @@ use yggdrasil_abi::{ use crate::{ device::{block::BlockDeviceFile, char::CharDeviceFile}, - task::process::Process, + task::{process::Process, thread::Thread}, vfs::{ FdPoll, FileReadiness, Node, SharedMemory, TimerFile, node::NodeRef, @@ -254,6 +254,10 @@ impl File { node: NodeRef, opts: OpenOptions, ) -> Result, Error> { + let pid = Thread::current().process_id(); + + device.lock(pid)?; + let read = opts.contains(OpenOptions::READ); let write = opts.contains(OpenOptions::WRITE); @@ -269,6 +273,7 @@ impl File { node, read, write, + pid, }))) } diff --git a/kernel/src/device/i2c/mod.rs b/kernel/src/device/i2c/mod.rs new file mode 100644 index 00000000..817198de --- /dev/null +++ b/kernel/src/device/i2c/mod.rs @@ -0,0 +1,112 @@ +#![allow(missing_docs)] + +use abi::{ + error::Error, + io::{FileMode, device::i2c::I2CMasterInfo}, +}; +use alloc::{string::String, sync::Arc}; +use device_api::{ + clock::Hertz, + device::{Device, DeviceInitContext}, + i2c::{I2CAddress, I2CController, I2CDevice}, +}; +use device_tree::driver::{Node, ProbeContext, device_tree_driver, lookup_phandle}; +use libk::fs::devfs; + +pub struct I2CMuxChild { + name: String, + channel: u32, + parent: Arc, +} + +pub struct I2CMux { + name: &'static str, +} + +impl I2CMux { + pub fn from_fdt(node: &Arc, _context: &mut ProbeContext) -> Option> { + let i2c_parent = node.prop_usize("i2c-parent")? as u32; + let i2c_parent = lookup_phandle(i2c_parent, true)?; + let i2c_parent = i2c_parent.as_i2c_controller()?; + let name = node.name().unwrap_or("i2c-mux-pinctrl"); + + let bus_index = i2c_parent.bus_number(); + + for (index, child) in node.children().enumerate() { + node.setup_pins(index).unwrap(); + let channel_index = child.prop_usize("reg")? as u32; + let name = alloc::format!("{name}@{channel_index}"); + let channel: Arc = Arc::new(I2CMuxChild { + name, + channel: channel_index, + parent: i2c_parent.clone(), + }); + + let device = Arc::new(I2CDevice::from(channel)); + let fs_name = alloc::format!("i2c{bus_index}-{channel_index}"); + devfs::add_named_char_device(device, fs_name, FileMode::new(0o600)).ok(); + } + + Some(Arc::new(I2CMux { name })) + } +} + +impl Device for I2CMux { + unsafe fn init(self: Arc, _cx: DeviceInitContext) -> Result<(), Error> { + Ok(()) + } + + fn display_name(&self) -> &str { + &self.name + } +} + +impl Device for I2CMuxChild { + unsafe fn init(self: Arc, _cx: DeviceInitContext) -> Result<(), Error> { + unreachable!() + } + + fn display_name(&self) -> &str { + &self.name + } +} + +impl I2CController for I2CMuxChild { + fn bus_number(&self) -> u32 { + self.parent.bus_number() + } + + fn child_number(&self) -> Option { + Some(self.channel) + } + + fn set_speed(&self, speed: Hertz) -> Result { + self.parent.set_speed(speed) + } + + fn capabilities(&self) -> I2CMasterInfo { + self.parent.capabilities() + } + + fn i2c_write(&self, address: I2CAddress, buffer: &[u8]) -> Result { + // TODO channel select? + self.parent.i2c_write(address, buffer) + } + + fn i2c_read(&self, address: I2CAddress, buffer: &mut [u8]) -> Result { + // TODO channel select? + self.parent.i2c_read(address, buffer) + } +} + +device_tree_driver! { + compatible: ["i2c-mux-pinctrl"], + config: { + auto_pinctrl: false, + }, + driver: { + fn probe(&self, node: &Arc, context: &mut ProbeContext) -> Option> { + I2CMux::from_fdt(node, context) + } + } +} diff --git a/kernel/src/device/mod.rs b/kernel/src/device/mod.rs index 4cdc61f0..f8774626 100644 --- a/kernel/src/device/mod.rs +++ b/kernel/src/device/mod.rs @@ -6,6 +6,7 @@ use libk_util::OneTimeInit; pub mod bus; pub mod clock; pub mod display; +pub mod i2c; pub mod power; // pub mod timer; diff --git a/lib/abi-serde/src/impls/base.rs b/lib/abi-serde/src/impls/base.rs index 06e8c256..0a44ee7d 100644 --- a/lib/abi-serde/src/impls/base.rs +++ b/lib/abi-serde/src/impls/base.rs @@ -39,6 +39,34 @@ impl_primitive_serde!( usize: [read_usize, write_usize] ); +impl Serialize for *const T { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> { + serializer.write_usize(self.addr()) + } +} + +impl Serialize for *mut T { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> { + serializer.write_usize(self.addr()) + } +} + +impl<'de, T: 'de> Deserialize<'de> for *const T { + fn deserialize>(deserializer: &mut D) -> Result { + deserializer + .read_usize() + .map(core::ptr::with_exposed_provenance) + } +} + +impl<'de, T: 'de> Deserialize<'de> for *mut T { + fn deserialize>(deserializer: &mut D) -> Result { + deserializer + .read_usize() + .map(core::ptr::with_exposed_provenance_mut) + } +} + impl Serialize for () { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> { let _ = serializer; diff --git a/lib/abi/src/io/device.rs b/lib/abi/src/io/device.rs index d1f3ed25..5bf4858c 100644 --- a/lib/abi/src/io/device.rs +++ b/lib/abi/src/io/device.rs @@ -55,6 +55,90 @@ request_group!( } ); +/// I²C device requests +pub mod i2c { + /// I²C master device information + #[derive(Debug, Clone, Copy)] + #[repr(C)] + pub struct I2CMasterInfo { + /// Maximum clock rate supported by the controller + pub max_speed_hz: u32, + /// `true` if the controller supports 10-bit addressing mode + pub supports_10bit_addresses: bool, + } + + request_group!( + #[doc = "I²C device requests"] + pub enum I2CRequestVariant<'de> { + #[doc = "Selects the address on the I²C bus"] + 0x2000: SetAddress(u16, ()), + #[doc = "Configures device speed (in Hertz)"] + 0x2001: SetSpeed(u32, u32), + #[doc = "Queries I²C master capabilities"] + 0x2010: GetMasterInfo((), I2CMasterInfo), + } + ); + + abi_serde::impl_struct_serde!(I2CMasterInfo: [ + max_speed_hz, supports_10bit_addresses + ]); +} + +/// SPI device requests +pub mod spi { + #![allow(missing_docs)] + + use crate::bitflags; + + /// Represents a single SPI transfer + #[derive(Clone, Copy, Debug)] + #[repr(C)] + pub struct SpiTransfer { + /// Tx buffer base pointer + pub tx_buffer: *const u8, + /// Rx buffer base pointer + pub rx_buffer: *mut u8, + /// Transfer size + pub len: usize, + /// SPI clock rate + pub speed_hz: Option, + /// Bits per SPI word + pub bits_per_word: u8, + } + + bitflags! { + #[doc = "SPI supported bits-per-word settings"] + pub struct SpiSupportedBitsPerWord: u32 { + #[doc = "8-bit words support"] + const BITS_8: bit 0; + } + } + + /// SPI controller capabilities + pub struct SpiCapabilities { + /// Maximum clock rate supported + pub max_speed_hz: u32, + /// Supports SPI master mode + pub supports_master_mode: bool, + /// Supports SPI slave mode + pub supports_slave_mode: bool, + /// Mask + pub supported_bits_per_word: u32, + } + + request_group!( + #[doc = "SPI device requests"] + pub enum SpiRequestVariant<'de> { + #[doc = "Perform a SPI transfer"] + 0x2000: Transfer(SpiTransfer, usize) + } + ); + + abi_serde::impl_struct_serde!(SpiTransfer: [ + tx_buffer, rx_buffer, len, speed_hz, bits_per_word + ]); +} + abi_serde::impl_struct_serde!(Framebuffer: [ width, height, stride, size ]); diff --git a/userspace/lib/cross/src/i2c.rs b/userspace/lib/cross/src/i2c.rs new file mode 100644 index 00000000..76585339 --- /dev/null +++ b/userspace/lib/cross/src/i2c.rs @@ -0,0 +1,48 @@ +use std::{ + io::{self, Read, Write}, + path::Path, +}; + +use crate::sys::{I2CMaster as SysI2CMaster, i2c::I2CMasterImpl}; + +pub use crate::sys::I2CMasterConfig; + +pub struct I2CMaster(I2CMasterImpl); + +impl Read for I2CMaster { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } +} + +impl Write for I2CMaster { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.0.flush() + } +} + +impl I2CMaster { + pub fn open>(device: P, config: &I2CMasterConfig) -> io::Result { + I2CMasterImpl::open(device, config).map(Self) + } + + pub fn set_slave_address(&mut self, address: u16) -> io::Result<()> { + self.0.set_slave_address(address) + } + + pub fn set_speed_hz(&mut self, speed_hz: u32) -> io::Result<()> { + self.0.set_speed_hz(speed_hz) + } + + pub fn smbus_read(&mut self, reg: u8, data: &mut [u8]) -> io::Result { + self.0.smbus_read(reg, data) + } + + pub fn smbus_write(&mut self, reg: u8, data: &[u8]) -> io::Result { + self.0.smbus_write(reg, data) + } +} diff --git a/userspace/lib/cross/src/lib.rs b/userspace/lib/cross/src/lib.rs index 275ccc02..4423ff13 100644 --- a/userspace/lib/cross/src/lib.rs +++ b/userspace/lib/cross/src/lib.rs @@ -5,6 +5,7 @@ pub(crate) mod sys; pub mod fs; +pub mod i2c; pub mod io; pub mod mem; pub mod net; diff --git a/userspace/lib/cross/src/sys/mod.rs b/userspace/lib/cross/src/sys/mod.rs index 4f17da87..7df346a8 100644 --- a/userspace/lib/cross/src/sys/mod.rs +++ b/userspace/lib/cross/src/sys/mod.rs @@ -64,6 +64,20 @@ pub(crate) trait SerialPort: Read + Write + AsRawFd + IntoRawFd + Sized { fn open>(device: P, options: &SerialPortSettings) -> io::Result; } +#[derive(Debug, Default)] +pub struct I2CMasterConfig { + pub slave_address: Option, + pub speed_hz: Option, +} + +pub(crate) trait I2CMaster: Read + Write + AsRawFd + Sized { + fn open>(device: P, config: &I2CMasterConfig) -> io::Result; + fn set_slave_address(&mut self, address: u16) -> io::Result<()>; + fn set_speed_hz(&mut self, speed_hz: u32) -> io::Result<()>; + fn smbus_read(&mut self, reg: u8, data: &mut [u8]) -> io::Result; + fn smbus_write(&mut self, reg: u8, data: &[u8]) -> io::Result; +} + pub trait TerminalOptions: Copy { fn normal() -> Self; fn raw() -> Self; diff --git a/userspace/lib/cross/src/sys/yggdrasil/i2c.rs b/userspace/lib/cross/src/sys/yggdrasil/i2c.rs new file mode 100644 index 00000000..45e2ae61 --- /dev/null +++ b/userspace/lib/cross/src/sys/yggdrasil/i2c.rs @@ -0,0 +1,72 @@ +use std::{ + fs::{File, OpenOptions}, + io::{self, Read, Write}, + os::fd::{AsRawFd, RawFd}, + path::Path, +}; + +use runtime::{abi::io::device::i2c, rt::io::device::device_request}; + +use crate::sys::{I2CMaster, I2CMasterConfig}; + +pub struct I2CMasterImpl { + file: File, +} + +impl Read for I2CMasterImpl { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.file.read(buf) + } +} + +impl Write for I2CMasterImpl { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.file.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.file.flush() + } +} + +impl I2CMaster for I2CMasterImpl { + fn open>(device: P, config: &I2CMasterConfig) -> io::Result { + let file = OpenOptions::new().read(true).write(true).open(device)?; + let mut this = Self { file }; + if let Some(address) = config.slave_address { + this.set_slave_address(address)?; + } + if let Some(speed_hz) = config.speed_hz { + this.set_speed_hz(speed_hz)?; + } + Ok(this) + } + + fn set_slave_address(&mut self, address: u16) -> io::Result<()> { + let mut buffer = [0; 4]; + device_request::(self.file.as_raw_fd(), &mut buffer, &address)?; + Ok(()) + } + + fn set_speed_hz(&mut self, speed_hz: u32) -> io::Result<()> { + let mut buffer = [0; 4]; + device_request::(self.file.as_raw_fd(), &mut buffer, &speed_hz)?; + Ok(()) + } + + fn smbus_read(&mut self, reg: u8, data: &mut [u8]) -> io::Result { + self.write_all(&[reg])?; + self.read(data) + } + + fn smbus_write(&mut self, reg: u8, data: &[u8]) -> io::Result { + self.write_all(&[reg])?; + self.write(data) + } +} + +impl AsRawFd for I2CMasterImpl { + fn as_raw_fd(&self) -> RawFd { + self.file.as_raw_fd() + } +} diff --git a/userspace/lib/cross/src/sys/yggdrasil/mod.rs b/userspace/lib/cross/src/sys/yggdrasil/mod.rs index a7d0eb82..c85b4156 100644 --- a/userspace/lib/cross/src/sys/yggdrasil/mod.rs +++ b/userspace/lib/cross/src/sys/yggdrasil/mod.rs @@ -1,4 +1,5 @@ pub mod fs; +pub mod i2c; pub mod mem; pub mod path; pub mod pid; diff --git a/userspace/sysutils/src/tst.rs b/userspace/sysutils/src/tst.rs index be85c50f..622260df 100644 --- a/userspace/sysutils/src/tst.rs +++ b/userspace/sysutils/src/tst.rs @@ -1,62 +1,97 @@ -#![feature(let_chains)] - -use std::collections::{HashSet, VecDeque}; - -use stuff::{ - autocomplete, - readline::{Buffer, NonEmptyVec, Readline, ReadlineProvider}, +use std::{ + io::{self, Write, stdout}, + path::{Path, PathBuf}, + process::ExitCode, + thread, + time::Duration, }; -#[derive(Default)] -struct P { - history: VecDeque, +use clap::Parser; +use cross::i2c::{I2CMaster, I2CMasterConfig}; + +#[derive(Debug, Parser)] +struct Args { + #[clap(short, long, default_value_t = 0x40, help = "I²C device address")] + address: u8, + #[clap(help = "I²C controller path")] + device: PathBuf, } -impl ReadlineProvider for P { - fn completions(&mut self, buffer: &Buffer) -> Option> { - let word_before_cursor = buffer.word_before_cursor(); - let is_first = buffer.is_first_word(); +struct M41T80 { + master: I2CMaster, +} - let mut entries = HashSet::new(); - if let Some(word) = word_before_cursor - && !is_first - { - autocomplete::complete_from_cwd(&mut entries, word, &Default::default()); - } else { - let prefix = word_before_cursor.unwrap_or(""); - autocomplete::complete_binary_from_env(&mut entries, prefix); - } +#[derive(Debug, PartialEq)] +struct Time { + year: u16, + mon: u8, + day: u8, - let mut entries = NonEmptyVec::try_from_iter(entries.drain()).ok()?; - entries.sort(); + hour: u8, + min: u8, + sec: u8, + millis: u16, +} - Some(entries) +impl M41T80 { + fn open>(path: P, config: &I2CMasterConfig) -> io::Result { + let master = I2CMaster::open(path, config)?; + Ok(Self { master }) } - fn push_history(&mut self, entry: &str) { - self.history.push_back(entry.into()); - } + fn read_time(&mut self) -> io::Result