From 692205305db14deeff1a2dc4a6d7f87e19fc418b Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Fri, 27 Dec 2024 17:14:40 +0100 Subject: [PATCH] bcm27xx: pull 6.6 patches from RPi repo MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Adds latest 6.6 patches from the Raspberry Pi repository. These patches were generated from: https://github.com/raspberrypi/linux/commits/rpi-6.6.y/ With the following command: git format-patch -N v6.6.67..HEAD (HEAD -> 811ff707533bcd67cdcd368bbd46223082009b12) Signed-off-by: Álvaro Fernández Rojas --- target/linux/bcm27xx/bcm2708/config-6.6 | 2 + target/linux/bcm27xx/bcm2709/config-6.6 | 2 + target/linux/bcm27xx/bcm2710/config-6.6 | 2 + target/linux/bcm27xx/bcm2711/config-6.6 | 2 + target/linux/bcm27xx/bcm2712/config-6.6 | 2 + target/linux/bcm27xx/config-6.6 | 2 + ...-dts-rp1-Disable-DMA-usage-for-UART0.patch | 34 - ...ia-bcm2835_isp-Cache-LS-table-dmabuf.patch | 141 + .../950-1353-pwm-Add-GPIO-PWM-driver.patch | 330 ++ ...overlay-Add-a-dtoverlay-for-pwm-gpio.patch | 79 + ...Drop-some-numa-options-from-bootargs.patch | 29 + ...ore-broken-Kingston-Canvas-Go-SD-car.patch | 42 + ...snps-dwc3-add-FS-HS-periodic-NAK-pol.patch | 35 + ...d-support-for-setting-NAK-enhancemen.patch | 77 + ...nced-FS-NAK-quirk-for-usb3-controlle.patch | 30 + ...-prevent-a-theoretical-race-on-non-c.patch | 50 + ...midity-dht11-Allow-non-zero-decimals.patch | 32 + ...condition-for-ignoring-a-plane-to-sr.patch | 41 + ...TPZ-scaling-filter-for-1x1-source-im.patch | 59 + ...top-property-to-true-for-writeback-a.patch | 30 + ...366-drm-Increase-plane_mask-to-64bit.patch | 101 + ...-number-of-overlay-planes-from-16-to.patch | 42 + ...-32-overlay-planes-to-writeback-only.patch | 71 + ...DE_TRANSPOSE-option-to-the-DRM-rotat.patch | 47 + ...d-a-rotation-parameter-to-connectors.patch | 164 + ...a-rotation-property-to-the-writeback.patch | 65 + ...w-axi-dmac-Allow-client-chosen-width.patch | 40 + ...Let-the-DMAC-set-the-transfer-widths.patch | 31 + ...011-Request-a-memory-width-of-1-byte.patch | 25 + ...-set-HID-bit-in-streaming-endpoint-c.patch | 56 + ...-Add-options-for-slightly-modifying-.patch | 199 + ...ink-frequency-override-to-imx477-378.patch | 43 + ...dw-axi-dmac-Only-start-idle-channels.patch | 29 + ...382-mailbox-Add-RP1-mailbox-support.patch} | 0 ...an-RP1-firmware-interface-over-mbox.patch} | 0 ...=> 950-1384-misc-Add-RP1-PIO-driver.patch} | 0 ...2-rpi-Add-RP1-firmware-and-mailboxes.patch | 118 + ...s-bcm2712-rpi-Add-the-RP1-PIO-device.patch | 55 + ...8-misc-rp1-pio-Add-an-in-kernel-API.patch} | 0 ...950-1389-pwm-Add-pwm-pio-rp1-driver.patch} | 4 +- ...50-1391-overlays-Add-pwm-pio-overlay.patch | 99 + ...-1392-fixup-misc-Add-RP1-PIO-driver.patch} | 0 ...misc-rp1-pio-Add-compat_ioctl-method.patch | 4 +- ...e-Add-support-for-bus-clear-feature.patch} | 12 +- ...i-Update-Hailo-accelerator-device-dr.patch | 3592 +++++++++++++++++ ...dtoverlays-enable-SPI-CS-active-high.patch | 108 + ...r-updating-the-enable_bg_fill-until-.patch | 64 + ...sc-rp1-pio-Add-FIFO-related-methods.patch} | 4 +- ...Raspberry-Touch-2-rotation-with-over.patch | 31 + ...rp1-pio-Add-missing-static-inline-s.patch} | 6 +- ...pio-Back-port-some-6.11-build-fixes.patch} | 0 ...950-1404-Adding-Pimidi-kernel-module.patch | 1167 ++++++ .../950-1406-Adding-pimidi-overlay.dts.patch | 100 + ...chiq_arm-Add-36-bit-address-support.patch} | 4 +- ...hiq_arm-children-inherit-DMA-config.patch} | 4 +- ..._arm-Usa-a-DMA-pool-for-small-bulks.patch} | 4 +- ...hiq_arm-Add-log_level-module-params.patch} | 4 +- ...a-i2c-imx477-Fix-link-frequency-menu.patch | 25 + ...o-Fix-copy-paste-error-in-pio_rp1.h.patch} | 2 +- ...-Fix-parameter-checks-wihout-client.patch} | 0 ...le-the-different-command-FIFO-widths.patch | 147 + ...For-CM5IO-i2c_csi_dsi-needs-to-be-CA.patch | 30 + ...rpi-cm5-Remove-inaccessible-USB_OC_N.patch | 25 + ...ca7000-replace-URL-with-textual-hint.patch | 33 + ...cdns-macb-Add-compatible-for-Raspber.patch | 24 + ...port-for-Raspberry-Pi-RP1-ethernet-c.patch | 4 +- ...t-PLL_SEC_RST-in-rp1_pll_divider_off.patch | 3 +- ...ise-the-use-of-the-CLK_IS_CRITICAL-f.patch | 3 +- ...-Fixup-RP1-ethernet-DT-configuration.patch | 8 +- .../950-1427-clk-rp1-Add-RP1_CLK_DMA.patch | 2 +- ...1-clk-Remove-CLK_IGNORE_UNUSED-flags.patch | 2 +- ...e-clk_sys-for-ethernet-hclk-and-pclk.patch | 6 +- ...Link-RP1-DMA-to-the-associated-clock.patch | 4 +- ...mware-Add-the-RPI-firmware-UART-APIs.patch | 23 + ...dd-the-Raspberry-Pi-firmware-UART-id.patch | 22 + ...d-a-driver-for-the-RPi-firmware-UART.patch | 630 +++ ...-overlay-for-the-Raspberry-Pi-firmwa.patch | 95 + ...0-1436-ARM-dts-Remove-duplicate-tags.patch | 142 + ...C-clock-frequency-via-i2c_arm_baudra.patch | 25 + ...pci-Disable-Host-Memory-Buffer-usage.patch | 48 + ...-Add-a-driver-for-the-RPi-firmware-U.patch | 23 + ...pi-fw-uart-Demote-debug-log-messages.patch | 28 + ...lays-Add-Arducam-override-for-ov9281.patch | 55 + ...uchscreen-Add-support-for-no-irq-to-.patch | 118 + ...panel-Added-waveshare-13.3inch-panel.patch | 309 ++ ...s-overlays-Added-waveshare-13.3inch-.patch | 46 + ...-kernel-command-line-to-disable-memo.patch | 37 + ...c-ov9282-Correct-the-exposure-offset.patch | 31 + ...4-hvs-Don-t-write-gamma-luts-on-2711.patch | 22 + ...arn-if-no-host-bridge-NUMA-node-info.patch | 29 + ...-Connector-to-allow-interlaced-modes.patch | 25 + ...-kms-dpi-generic-overlay-Add-interla.patch | 34 + ...Add-interlaced-modes-and-PIO-program.patch | 4 +- ...pwm-Improve-PWM_PIO_RP1-dependencies.patch | 22 - ...pwm-Improve-PWM_PIO_RP1-dependencies.patch | 20 - ...no-dac-plus-Fix-volume-limit-locking.patch | 79 + ...ot-allow-24bpp-formats-when-transpos.patch | 30 + ...nector-rotation-has-one-bit-set-in-t.patch | 29 + ...o-piano-dac-plus-Suppress-517-errors.patch | 73 + ...i-Fix-optional-dependency-on-RP1_PIO.patch | 3 +- ...-announce-support-for-SER_RS485_RTS_.patch | 42 + ...verride-for-target-path-on-I2C-overl.patch | 550 +++ ...p1-pio-Support-larger-data-transfers.patch | 2 +- ...Use-continuous-clock-mode-for-ov9281.patch | 34 + ...ys-goodix-Allow-override-i2c-address.patch | 36 + ...0-1471-fixup-misc-Add-RP1-PIO-driver.patch | 2 +- ...-rp1-pio-More-logical-probe-sequence.patch | 2 +- ...o-Convert-floats-to-24.8-fixed-point.patch | 2 +- ...5-misc-rp1-pio-Minor-cosmetic-tweaks.patch | 2 +- ...sc-rp1-pio-Add-in-kernel-DMA-support.patch | 2 +- ...-1477-misc-Add-ws2812-pio-rp1-driver.patch | 2 +- ...1478-overlays-Add-ws2812-pio-overlay.patch | 6 +- ...and-document-i2c_csi_dsi0-parameters.patch | 342 ++ ...d-noanthogs-parameter-to-CM4-and-CM5.patch | 56 + 114 files changed, 10583 insertions(+), 131 deletions(-) delete mode 100644 target/linux/bcm27xx/patches-6.6/950-1267-dts-rp1-Disable-DMA-usage-for-UART0.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1351-drivers-media-bcm2835_isp-Cache-LS-table-dmabuf.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1353-pwm-Add-GPIO-PWM-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1355-dtoverlay-Add-a-dtoverlay-for-pwm-gpio.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1356-dts-2712-Drop-some-numa-options-from-bootargs.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1357-mmc-quirks-add-more-broken-Kingston-Canvas-Go-SD-car.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1358-dt-bindings-usb-snps-dwc3-add-FS-HS-periodic-NAK-pol.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1359-usb-dwc3-core-add-support-for-setting-NAK-enhancemen.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1360-DTS-rp1-set-enhanced-FS-NAK-quirk-for-usb3-controlle.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1361-drivers-usb-xhci-prevent-a-theoretical-race-on-non-c.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1362-iio-humidity-dht11-Allow-non-zero-decimals.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1363-drm-vc4-Correct-condition-for-ignoring-a-plane-to-sr.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1364-drm-vc4-Use-the-TPZ-scaling-filter-for-1x1-source-im.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1365-drm-Set-non-desktop-property-to-true-for-writeback-a.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1366-drm-Increase-plane_mask-to-64bit.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1367-drm-vc4-Increase-number-of-overlay-planes-from-16-to.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1368-drm-vc4-Assign-32-overlay-planes-to-writeback-only.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1369-drm-Add-a-DRM_MODE_TRANSPOSE-option-to-the-DRM-rotat.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1370-drm-Add-a-rotation-parameter-to-connectors.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1371-drm-vc4-txp-Add-a-rotation-property-to-the-writeback.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1372-dmaengine-dw-axi-dmac-Allow-client-chosen-width.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1373-spi-dw-Let-the-DMAC-set-the-transfer-widths.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1374-serial-pl011-Request-a-memory-width-of-1-byte.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1377-drivers-usb-xhci-set-HID-bit-in-streaming-endpoint-c.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1379-media-i2c-imx477-Add-options-for-slightly-modifying-.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1380-dtoverlays-Add-link-frequency-override-to-imx477-378.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1381-dmaengine-dw-axi-dmac-Only-start-idle-channels.patch rename target/linux/bcm27xx/patches-6.6/{950-1351-mailbox-Add-RP1-mailbox-support.patch => 950-1382-mailbox-Add-RP1-mailbox-support.patch} (100%) rename target/linux/bcm27xx/patches-6.6/{950-1352-firmware-Add-an-RP1-firmware-interface.patch => 950-1383-firmware-Add-an-RP1-firmware-interface-over-mbox.patch} (100%) rename target/linux/bcm27xx/patches-6.6/{950-1353-misc-Add-RP1-PIO-driver.patch => 950-1384-misc-Add-RP1-PIO-driver.patch} (100%) create mode 100644 target/linux/bcm27xx/patches-6.6/950-1386-dts-bcm2712-rpi-Add-RP1-firmware-and-mailboxes.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1387-dts-bcm2712-rpi-Add-the-RP1-PIO-device.patch rename target/linux/bcm27xx/patches-6.6/{950-1355-misc-rp1-pio-Add-an-in-kernel.patch => 950-1388-misc-rp1-pio-Add-an-in-kernel-API.patch} (100%) rename target/linux/bcm27xx/patches-6.6/{950-1356-pwm-Add-pwm-pio-rp1-driver.patch => 950-1389-pwm-Add-pwm-pio-rp1-driver.patch} (98%) create mode 100644 target/linux/bcm27xx/patches-6.6/950-1391-overlays-Add-pwm-pio-overlay.patch rename target/linux/bcm27xx/patches-6.6/{950-1354-fixup-musc-add-RP1-PIO-driver.patch => 950-1392-fixup-misc-Add-RP1-PIO-driver.patch} (100%) rename target/linux/bcm27xx/patches-6.6/{950-0998-i2c-designware-Add-support-for-bus-clear-feature.patch => 950-1396-i2c-designware-Add-support-for-bus-clear-feature.patch} (93%) create mode 100644 target/linux/bcm27xx/patches-6.6/950-1397-drivers-media-pci-Update-Hailo-accelerator-device-dr.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1398-dtoverlays-enable-SPI-CS-active-high.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1399-drm-vc4-hvs-Defer-updating-the-enable_bg_fill-until-.patch rename target/linux/bcm27xx/patches-6.6/{950-1359-misc-rp1-pio-Add-FIFO.patch => 950-1400-misc-rp1-pio-Add-FIFO-related-methods.patch} (98%) create mode 100644 target/linux/bcm27xx/patches-6.6/950-1401-overlays-Enable-Raspberry-Touch-2-rotation-with-over.patch rename target/linux/bcm27xx/patches-6.6/{950-1357-rpi-pio-add-missing.patch => 950-1402-rp1-pio-Add-missing-static-inline-s.patch} (88%) rename target/linux/bcm27xx/patches-6.6/{950-1358-misc-rpi-pio-back-port-some.patch => 950-1403-misc-rp1-pio-Back-port-some-6.11-build-fixes.patch} (100%) create mode 100644 target/linux/bcm27xx/patches-6.6/950-1404-Adding-Pimidi-kernel-module.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1406-Adding-pimidi-overlay.dts.patch rename target/linux/bcm27xx/patches-6.6/{950-0297-staging-vchiq_arm-Add-36-bit-address-support.patch => 950-1411-staging-vchiq_arm-Add-36-bit-address-support.patch} (98%) rename target/linux/bcm27xx/patches-6.6/{950-0298-staging-vchiq_arm-children-inherit-DMA-config.patch => 950-1412-staging-vchiq_arm-children-inherit-DMA-config.patch} (87%) rename target/linux/bcm27xx/patches-6.6/{950-0299-staging-vchiq_arm-Usa-a-DMA-pool-for-small-bulks.patch => 950-1413-staging-vchiq_arm-Usa-a-DMA-pool-for-small-bulks.patch} (96%) rename target/linux/bcm27xx/patches-6.6/{950-0365-staging-vchiq_arm-Add-log_level-module-params.patch => 950-1414-staging-vchiq_arm-Add-log_level-module-params.patch} (88%) create mode 100644 target/linux/bcm27xx/patches-6.6/950-1415-media-i2c-imx477-Fix-link-frequency-menu.patch rename target/linux/bcm27xx/patches-6.6/{950-1357-misc-rp1-pio-Fix-copy-paste-error-in-pio_rp1.h.patch => 950-1416-misc-rp1-pio-Fix-copy-paste-error-in-pio_rp1.h.patch} (93%) rename target/linux/bcm27xx/patches-6.6/{950-1360-misc-rp1-pio-Fix-parameter-checks-wihout-client.patch => 950-1417-misc-rp1-pio-Fix-parameter-checks-wihout-client.patch} (100%) create mode 100644 target/linux/bcm27xx/patches-6.6/950-1418-drm-vc4-dsi-Handle-the-different-command-FIFO-widths.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1419-dts-bcm2712-rpi-For-CM5IO-i2c_csi_dsi-needs-to-be-CA.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1420-dts-bcm2712-rpi-cm5-Remove-inaccessible-USB_OC_N.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1421-overlays-qca7000-replace-URL-with-textual-hint.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1422-dt-bindings-net-cdns-macb-Add-compatible-for-Raspber.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1431-raspberrypi-firmware-Add-the-RPI-firmware-UART-APIs.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1432-serial-core-Add-the-Raspberry-Pi-firmware-UART-id.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1433-serial-tty-Add-a-driver-for-the-RPi-firmware-UART.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1435-dtoverlay-Add-an-overlay-for-the-Raspberry-Pi-firmwa.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1436-ARM-dts-Remove-duplicate-tags.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1437-Allow-setting-I-C-clock-frequency-via-i2c_arm_baudra.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1438-nvme-pci-Disable-Host-Memory-Buffer-usage.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1439-fixup-serial-tty-Add-a-driver-for-the-RPi-firmware-U.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1440-serial-rpi-fw-uart-Demote-debug-log-messages.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1441-dtoverlays-Add-Arducam-override-for-ov9281.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1442-drivers-input-touchscreen-Add-support-for-no-irq-to-.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1443-drivers-gpu-drm-panel-Added-waveshare-13.3inch-panel.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1444-arch-arm-boot-dts-overlays-Added-waveshare-13.3inch-.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1445-fixup-cgroup-Use-kernel-command-line-to-disable-memo.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1446-media-i2c-ov9282-Correct-the-exposure-offset.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1451-Revert-drm-vc4-hvs-Don-t-write-gamma-luts-on-2711.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1452-Revert-PCI-Warn-if-no-host-bridge-NUMA-node-info.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1454-drm-bridge-panel-Connector-to-allow-interlaced-modes.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1455-dts-overlays-vc4-kms-dpi-generic-overlay-Add-interla.patch delete mode 100644 target/linux/bcm27xx/patches-6.6/950-1457-pwm-Improve-PWM_PIO_RP1-dependencies.patch delete mode 100644 target/linux/bcm27xx/patches-6.6/950-1458-Revert-pwm-Improve-PWM_PIO_RP1-dependencies.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1459-ASoC-allo-piano-dac-plus-Fix-volume-limit-locking.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1460-drm-vc4-txp-Do-not-allow-24bpp-formats-when-transpos.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1461-drm-Validate-connector-rotation-has-one-bit-set-in-t.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1462-ASoC-allo-piano-dac-plus-Suppress-517-errors.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1464-serial-sc16is7xx-announce-support-for-SER_RS485_RTS_.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1467-dtoverlays-Add-override-for-target-path-on-I2C-overl.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1469-dtoverlays-Use-continuous-clock-mode-for-ov9281.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1470-overlays-goodix-Allow-override-i2c-address.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1480-overlays-Add-and-document-i2c_csi_dsi0-parameters.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1481-dts-Add-noanthogs-parameter-to-CM4-and-CM5.patch diff --git a/target/linux/bcm27xx/bcm2708/config-6.6 b/target/linux/bcm27xx/bcm2708/config-6.6 index b587b5d719..a8a3cc9af7 100644 --- a/target/linux/bcm27xx/bcm2708/config-6.6 +++ b/target/linux/bcm27xx/bcm2708/config-6.6 @@ -314,6 +314,7 @@ CONFIG_PRINTK_TIME=y CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_PWM=y CONFIG_PWM_BCM2835=y +CONFIG_PWM_GPIO=y CONFIG_PWM_SYSFS=y CONFIG_RANDSTRUCT_NONE=y CONFIG_RASPBERRYPI_FIRMWARE=y @@ -346,6 +347,7 @@ CONFIG_SERIAL_DEV_BUS=y # CONFIG_SERIAL_DEV_CTRL_TTYPORT is not set CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_RPI_FW=y CONFIG_SG_POOL=y CONFIG_SMSC_PHY=y CONFIG_SOFTIRQ_ON_OWN_STACK=y diff --git a/target/linux/bcm27xx/bcm2709/config-6.6 b/target/linux/bcm27xx/bcm2709/config-6.6 index 4a295d52c8..edcc8f58cc 100644 --- a/target/linux/bcm27xx/bcm2709/config-6.6 +++ b/target/linux/bcm27xx/bcm2709/config-6.6 @@ -398,6 +398,7 @@ CONFIG_PTP_1588_CLOCK=y CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_PWM=y CONFIG_PWM_BCM2835=y +CONFIG_PWM_GPIO=y CONFIG_PWM_SYSFS=y CONFIG_RANDSTRUCT_NONE=y CONFIG_RAS=y @@ -435,6 +436,7 @@ CONFIG_SERIAL_DEV_BUS=y # CONFIG_SERIAL_DEV_CTRL_TTYPORT is not set CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_RPI_FW=y CONFIG_SG_POOL=y CONFIG_SMP=y CONFIG_SMP_ON_UP=y diff --git a/target/linux/bcm27xx/bcm2710/config-6.6 b/target/linux/bcm27xx/bcm2710/config-6.6 index 97f2f110b0..18a9c26b01 100644 --- a/target/linux/bcm27xx/bcm2710/config-6.6 +++ b/target/linux/bcm27xx/bcm2710/config-6.6 @@ -389,6 +389,7 @@ CONFIG_PRINTK_TIME=y CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_PWM=y CONFIG_PWM_BCM2835=y +CONFIG_PWM_GPIO=y CONFIG_PWM_SYSFS=y CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y @@ -428,6 +429,7 @@ CONFIG_SERIAL_DEV_BUS=y # CONFIG_SERIAL_DEV_CTRL_TTYPORT is not set CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_RPI_FW=y CONFIG_SG_POOL=y CONFIG_SMP=y CONFIG_SMSC_PHY=y diff --git a/target/linux/bcm27xx/bcm2711/config-6.6 b/target/linux/bcm27xx/bcm2711/config-6.6 index f9b7469607..a48771b8e7 100644 --- a/target/linux/bcm27xx/bcm2711/config-6.6 +++ b/target/linux/bcm27xx/bcm2711/config-6.6 @@ -405,6 +405,7 @@ CONFIG_PTP_1588_CLOCK=y CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_PWM=y CONFIG_PWM_BCM2835=y +CONFIG_PWM_GPIO=y CONFIG_PWM_SYSFS=y CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y @@ -445,6 +446,7 @@ CONFIG_SERIAL_DEV_BUS=y # CONFIG_SERIAL_DEV_CTRL_TTYPORT is not set CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_RPI_FW=y CONFIG_SG_POOL=y CONFIG_SMP=y CONFIG_SOCK_RX_QUEUE_MAPPING=y diff --git a/target/linux/bcm27xx/bcm2712/config-6.6 b/target/linux/bcm27xx/bcm2712/config-6.6 index 5ed564f5ab..9dac0688df 100644 --- a/target/linux/bcm27xx/bcm2712/config-6.6 +++ b/target/linux/bcm27xx/bcm2712/config-6.6 @@ -513,6 +513,7 @@ CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_PWM=y CONFIG_PWM_BCM2835=y CONFIG_PWM_BRCMSTB=y +CONFIG_PWM_GPIO=y CONFIG_PWM_RP1=y CONFIG_PWM_SYSFS=y CONFIG_QUEUED_RWLOCKS=y @@ -577,6 +578,7 @@ CONFIG_SPARSEMEM_VMEMMAP=y CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y CONFIG_SPARSE_IRQ=y CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SRAM=y # CONFIG_STRIP_ASM_SYMS is not set CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y diff --git a/target/linux/bcm27xx/config-6.6 b/target/linux/bcm27xx/config-6.6 index 50ca86f585..e69dbf5d74 100644 --- a/target/linux/bcm27xx/config-6.6 +++ b/target/linux/bcm27xx/config-6.6 @@ -28,6 +28,8 @@ # CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2 is not set # CONFIG_RP1_PIO is not set # CONFIG_SENSORS_RP1_ADC is not set +# CONFIG_SERIAL_RPI_FW is not set +# CONFIG_SND_PIMIDI is not set # CONFIG_SPI_RP2040_GPIO_BRIDGE is not set # CONFIG_VIDEO_AD5398 is not set # CONFIG_VIDEO_ARDUCAM_64MP is not set diff --git a/target/linux/bcm27xx/patches-6.6/950-1267-dts-rp1-Disable-DMA-usage-for-UART0.patch b/target/linux/bcm27xx/patches-6.6/950-1267-dts-rp1-Disable-DMA-usage-for-UART0.patch deleted file mode 100644 index c809c4f10b..0000000000 --- a/target/linux/bcm27xx/patches-6.6/950-1267-dts-rp1-Disable-DMA-usage-for-UART0.patch +++ /dev/null @@ -1,34 +0,0 @@ -From cc63d552b9aab92fb581dfb08267d5af697f477b Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 18 Sep 2024 16:45:24 +0100 -Subject: [PATCH 1267/1350] dts: rp1: Disable DMA usage for UART0 - -Some recent DMA changes have led to data loss in UART0 on Pi 5. It also -seems that even prior to these changes there was a problem with aborted -transfers. - -As this is the only RP1 UART configured for DMA, it is better to remove -the DMA usage until it is shown to be reliable. - -Link: https://github.com/raspberrypi/linux/issues/6365 - -Signed-off-by: Phil Elwell ---- - arch/arm64/boot/dts/broadcom/rp1.dtsi | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/arch/arm64/boot/dts/broadcom/rp1.dtsi -+++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi -@@ -55,9 +55,9 @@ - interrupts = ; - clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; - clock-names = "uartclk", "apb_pclk"; -- dmas = <&rp1_dma RP1_DMA_UART0_TX>, -- <&rp1_dma RP1_DMA_UART0_RX>; -- dma-names = "tx", "rx"; -+ // dmas = <&rp1_dma RP1_DMA_UART0_TX>, -+ // <&rp1_dma RP1_DMA_UART0_RX>; -+ // dma-names = "tx", "rx"; - pinctrl-names = "default"; - arm,primecell-periphid = <0x00541011>; - uart-has-rtscts; diff --git a/target/linux/bcm27xx/patches-6.6/950-1351-drivers-media-bcm2835_isp-Cache-LS-table-dmabuf.patch b/target/linux/bcm27xx/patches-6.6/950-1351-drivers-media-bcm2835_isp-Cache-LS-table-dmabuf.patch new file mode 100644 index 0000000000..1f5ed7545b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1351-drivers-media-bcm2835_isp-Cache-LS-table-dmabuf.patch @@ -0,0 +1,141 @@ +From 25e6acfe00f589a5989ebd2c8d21a130fb3bf106 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Fri, 18 Oct 2024 09:18:10 +0100 +Subject: [PATCH] drivers: media: bcm2835_isp: Cache LS table dmabuf + +Clients such as libcamera do not change the LS table dmabuf on every +frame. In such cases instead of mapping/remapping the same dmabuf on +every frame to send to the firmware, cache the dmabuf once and only +update and remap if the dmabuf has been changed by the userland client. + +Signed-off-by: Naushir Patuck +--- + .../bcm2835-isp/bcm2835-v4l2-isp.c | 77 +++++++++++-------- + 1 file changed, 46 insertions(+), 31 deletions(-) + +--- a/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c ++++ b/drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c +@@ -139,6 +139,8 @@ struct bcm2835_isp_dev { + /* Image pipeline controls. */ + int r_gain; + int b_gain; ++ struct dma_buf *last_ls_dmabuf; ++ struct mmal_parameter_lens_shading_v2 ls; + }; + + struct bcm2835_isp_buffer { +@@ -657,18 +659,18 @@ static void bcm2835_isp_node_stop_stream + atomic_dec(&dev->num_streaming); + /* If all ports disabled, then disable the component */ + if (atomic_read(&dev->num_streaming) == 0) { +- struct bcm2835_isp_lens_shading ls; + /* + * The ISP component on the firmware has a reference to the + * dmabuf handle for the lens shading table. Pass a null handle + * to remove that reference now. + */ +- memset(&ls, 0, sizeof(ls)); ++ memset(&dev->ls, 0, sizeof(dev->ls)); + /* Must set a valid grid size for the FW */ +- ls.grid_cell_size = 16; ++ dev->ls.grid_cell_size = 16; + set_isp_param(&dev->node[0], + MMAL_PARAMETER_LENS_SHADING_OVERRIDE, +- &ls, sizeof(ls)); ++ &dev->ls, sizeof(dev->ls)); ++ dev->last_ls_dmabuf = NULL; + + ret = vchiq_mmal_component_disable(dev->mmal_instance, + dev->component); +@@ -719,6 +721,36 @@ static inline unsigned int get_sizeimage + return (bpl * height * fmt->size_multiplier_x2) >> 1; + } + ++static int map_ls_table(struct bcm2835_isp_dev *dev, struct dma_buf *dmabuf, ++ const struct bcm2835_isp_lens_shading *v4l2_ls) ++{ ++ void *vcsm_handle; ++ int ret; ++ ++ if (IS_ERR_OR_NULL(dmabuf)) ++ return -EINVAL; ++ ++ /* ++ * struct bcm2835_isp_lens_shading and struct ++ * mmal_parameter_lens_shading_v2 match so that we can do a ++ * simple memcpy here. ++ * Only the dmabuf to the actual table needs any manipulation. ++ */ ++ memcpy(&dev->ls, v4l2_ls, sizeof(dev->ls)); ++ ret = vc_sm_cma_import_dmabuf(dmabuf, &vcsm_handle); ++ if (ret) { ++ dma_buf_put(dmabuf); ++ return ret; ++ } ++ ++ dev->ls.mem_handle_table = vc_sm_cma_int_handle(vcsm_handle); ++ dev->last_ls_dmabuf = dmabuf; ++ ++ vc_sm_cma_free(vcsm_handle); ++ ++ return 0; ++} ++ + static int bcm2835_isp_s_ctrl(struct v4l2_ctrl *ctrl) + { + struct bcm2835_isp_dev *dev = +@@ -754,44 +786,27 @@ static int bcm2835_isp_s_ctrl(struct v4l + case V4L2_CID_USER_BCM2835_ISP_LENS_SHADING: + { + struct bcm2835_isp_lens_shading *v4l2_ls; +- struct mmal_parameter_lens_shading_v2 ls; +- struct dma_buf *dmabuf; +- void *vcsm_handle; + + v4l2_ls = (struct bcm2835_isp_lens_shading *)ctrl->p_new.p_u8; +- /* +- * struct bcm2835_isp_lens_shading and struct +- * mmal_parameter_lens_shading_v2 match so that we can do a +- * simple memcpy here. +- * Only the dmabuf to the actual table needs any manipulation. +- */ +- memcpy(&ls, v4l2_ls, sizeof(ls)); ++ struct dma_buf *dmabuf = dma_buf_get(v4l2_ls->dmabuf); + +- dmabuf = dma_buf_get(v4l2_ls->dmabuf); +- if (IS_ERR_OR_NULL(dmabuf)) +- return -EINVAL; +- +- ret = vc_sm_cma_import_dmabuf(dmabuf, &vcsm_handle); +- if (ret) { +- dma_buf_put(dmabuf); +- return -EINVAL; +- } ++ if (dmabuf != dev->last_ls_dmabuf) ++ ret = map_ls_table(dev, dmabuf, v4l2_ls); + +- ls.mem_handle_table = vc_sm_cma_int_handle(vcsm_handle); +- if (ls.mem_handle_table) +- /* The VPU will take a reference on the vcsm handle, ++ if (!ret && dev->ls.mem_handle_table) ++ /* ++ * The VPU will take a reference on the vcsm handle, + * which in turn will retain a reference on the dmabuf. + * This code can therefore safely release all + * references to the buffer. + */ +- ret = set_isp_param(node, +- MMAL_PARAMETER_LENS_SHADING_OVERRIDE, +- &ls, +- sizeof(ls)); ++ ret = ++ set_isp_param(node, ++ MMAL_PARAMETER_LENS_SHADING_OVERRIDE, ++ &dev->ls, sizeof(dev->ls)); + else + ret = -EINVAL; + +- vc_sm_cma_free(vcsm_handle); + dma_buf_put(dmabuf); + break; + } diff --git a/target/linux/bcm27xx/patches-6.6/950-1353-pwm-Add-GPIO-PWM-driver.patch b/target/linux/bcm27xx/patches-6.6/950-1353-pwm-Add-GPIO-PWM-driver.patch new file mode 100644 index 0000000000..5b89f60bca --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1353-pwm-Add-GPIO-PWM-driver.patch @@ -0,0 +1,330 @@ +From 3ab72fc21ea8576e59f6aad10bd6b1a0eae6e5eb Mon Sep 17 00:00:00 2001 +From: Vincent Whitchurch +Date: Tue, 4 Jun 2024 23:00:41 +0200 +Subject: [PATCH] pwm: Add GPIO PWM driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 7f61257cd6e1ad4769b4b819668cab00f68f2556 upstream. + +Add a software PWM which toggles a GPIO from a high-resolution timer. + +This will naturally not be as accurate or as efficient as a hardware +PWM, but it is useful in some cases. I have for example used it for +evaluating LED brightness handling (via leds-pwm) on a board where the +LED was just hooked up to a GPIO, and for a simple verification of the +timer frequency on another platform. + +Since high-resolution timers are used, sleeping GPIO chips are not +supported and are rejected in the probe function. + +Signed-off-by: Vincent Whitchurch +Co-developed-by: Stefan Wahren +Signed-off-by: Stefan Wahren +Co-developed-by: Linus Walleij +Reviewed-by: Andy Shevchenko +Signed-off-by: Linus Walleij +Reviewed-by: Dhruva Gole +Link: https://lore.kernel.org/r/20240604-pwm-gpio-v7-2-6b67cf60db92@linaro.org +Signed-off-by: Uwe Kleine-König +Signed-off-by: Tim Gover + +pwm: Backport pwm-gpio.c to rpi-6.6.y +--- + .../driver-api/gpio/drivers-on-gpio.rst | 7 +- + drivers/pwm/Kconfig | 11 + + drivers/pwm/Makefile | 1 + + drivers/pwm/pwm-gpio.c | 240 ++++++++++++++++++ + 4 files changed, 258 insertions(+), 1 deletion(-) + create mode 100644 drivers/pwm/pwm-gpio.c + +--- a/Documentation/driver-api/gpio/drivers-on-gpio.rst ++++ b/Documentation/driver-api/gpio/drivers-on-gpio.rst +@@ -27,7 +27,12 @@ hardware descriptions such as device tre + to the lines for a more permanent solution of this type. + + - gpio-beeper: drivers/input/misc/gpio-beeper.c is used to provide a beep from +- an external speaker connected to a GPIO line. ++ an external speaker connected to a GPIO line. (If the beep is controlled by ++ off/on, for an actual PWM waveform, see pwm-gpio below.) ++ ++- pwm-gpio: drivers/pwm/pwm-gpio.c is used to toggle a GPIO with a high ++ resolution timer producing a PWM waveform on the GPIO line, as well as ++ Linux high resolution timers can do. + + - extcon-gpio: drivers/extcon/extcon-gpio.c is used when you need to read an + external connector status, such as a headset line for an audio driver or an +--- a/drivers/pwm/Kconfig ++++ b/drivers/pwm/Kconfig +@@ -217,6 +217,17 @@ config PWM_FSL_FTM + To compile this driver as a module, choose M here: the module + will be called pwm-fsl-ftm. + ++config PWM_GPIO ++ tristate "GPIO PWM support" ++ depends on GPIOLIB ++ depends on HIGH_RES_TIMERS ++ help ++ Generic PWM framework driver for software PWM toggling a GPIO pin ++ from kernel high-resolution timers. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called pwm-gpio. ++ + config PWM_HIBVT + tristate "HiSilicon BVT PWM support" + depends on ARCH_HISI || COMPILE_TEST +--- a/drivers/pwm/Makefile ++++ b/drivers/pwm/Makefile +@@ -18,6 +18,7 @@ obj-$(CONFIG_PWM_CROS_EC) += pwm-cros-ec + obj-$(CONFIG_PWM_DWC) += pwm-dwc.o + obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o + obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o ++obj-$(CONFIG_PWM_GPIO) += pwm-gpio.o + obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o + obj-$(CONFIG_PWM_IMG) += pwm-img.o + obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o +--- /dev/null ++++ b/drivers/pwm/pwm-gpio.c +@@ -0,0 +1,240 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Generic software PWM for modulating GPIOs ++ * ++ * Copyright (C) 2020 Axis Communications AB ++ * Copyright (C) 2020 Nicola Di Lieto ++ * Copyright (C) 2024 Stefan Wahren ++ * Copyright (C) 2024 Linus Walleij ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct pwm_gpio { ++ struct hrtimer gpio_timer; ++ struct gpio_desc *gpio; ++ struct pwm_state state; ++ struct pwm_state next_state; ++ ++ /* Protect internal state between pwm_ops and hrtimer */ ++ spinlock_t lock; ++ ++ bool changing; ++ bool running; ++ bool level; ++ struct pwm_chip chip; ++}; ++ ++static void pwm_gpio_round(struct pwm_state *dest, const struct pwm_state *src) ++{ ++ u64 dividend; ++ u32 remainder; ++ ++ *dest = *src; ++ ++ /* Round down to hrtimer resolution */ ++ dividend = dest->period; ++ remainder = do_div(dividend, hrtimer_resolution); ++ dest->period -= remainder; ++ ++ dividend = dest->duty_cycle; ++ remainder = do_div(dividend, hrtimer_resolution); ++ dest->duty_cycle -= remainder; ++} ++ ++static u64 pwm_gpio_toggle(struct pwm_gpio *gpwm, bool level) ++{ ++ const struct pwm_state *state = &gpwm->state; ++ bool invert = state->polarity == PWM_POLARITY_INVERSED; ++ ++ gpwm->level = level; ++ gpiod_set_value(gpwm->gpio, gpwm->level ^ invert); ++ ++ if (!state->duty_cycle || state->duty_cycle == state->period) { ++ gpwm->running = false; ++ return 0; ++ } ++ ++ gpwm->running = true; ++ return level ? state->duty_cycle : state->period - state->duty_cycle; ++} ++ ++static enum hrtimer_restart pwm_gpio_timer(struct hrtimer *gpio_timer) ++{ ++ struct pwm_gpio *gpwm = container_of(gpio_timer, struct pwm_gpio, ++ gpio_timer); ++ u64 next_toggle; ++ bool new_level; ++ ++ guard(spinlock_irqsave)(&gpwm->lock); ++ ++ /* Apply new state at end of current period */ ++ if (!gpwm->level && gpwm->changing) { ++ gpwm->changing = false; ++ gpwm->state = gpwm->next_state; ++ new_level = !!gpwm->state.duty_cycle; ++ } else { ++ new_level = !gpwm->level; ++ } ++ ++ next_toggle = pwm_gpio_toggle(gpwm, new_level); ++ if (next_toggle) ++ hrtimer_forward(gpio_timer, hrtimer_get_expires(gpio_timer), ++ ns_to_ktime(next_toggle)); ++ ++ return next_toggle ? HRTIMER_RESTART : HRTIMER_NORESTART; ++} ++ ++static int pwm_gpio_apply(struct pwm_chip *chip, struct pwm_device *pwm, ++ const struct pwm_state *state) ++{ ++ struct pwm_gpio *gpwm = container_of(chip, struct pwm_gpio, chip); ++ bool invert = state->polarity == PWM_POLARITY_INVERSED; ++ ++ if (state->duty_cycle && state->duty_cycle < hrtimer_resolution) ++ return -EINVAL; ++ ++ if (state->duty_cycle != state->period && ++ (state->period - state->duty_cycle < hrtimer_resolution)) ++ return -EINVAL; ++ ++ if (!state->enabled) { ++ hrtimer_cancel(&gpwm->gpio_timer); ++ } else if (!gpwm->running) { ++ int ret; ++ ++ /* ++ * This just enables the output, but pwm_gpio_toggle() ++ * really starts the duty cycle. ++ */ ++ ret = gpiod_direction_output(gpwm->gpio, invert); ++ if (ret) ++ return ret; ++ } ++ ++ guard(spinlock_irqsave)(&gpwm->lock); ++ ++ if (!state->enabled) { ++ pwm_gpio_round(&gpwm->state, state); ++ gpwm->running = false; ++ gpwm->changing = false; ++ ++ gpiod_set_value(gpwm->gpio, invert); ++ } else if (gpwm->running) { ++ pwm_gpio_round(&gpwm->next_state, state); ++ gpwm->changing = true; ++ } else { ++ unsigned long next_toggle; ++ ++ pwm_gpio_round(&gpwm->state, state); ++ gpwm->changing = false; ++ ++ next_toggle = pwm_gpio_toggle(gpwm, !!state->duty_cycle); ++ if (next_toggle) ++ hrtimer_start(&gpwm->gpio_timer, next_toggle, ++ HRTIMER_MODE_REL); ++ } ++ ++ return 0; ++} ++ ++static int pwm_gpio_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) ++{ ++ struct pwm_gpio *gpwm = container_of(chip, struct pwm_gpio, chip); ++ ++ guard(spinlock_irqsave)(&gpwm->lock); ++ ++ if (gpwm->changing) ++ *state = gpwm->next_state; ++ else ++ *state = gpwm->state; ++ ++ return 0; ++} ++ ++static const struct pwm_ops pwm_gpio_ops = { ++ .apply = pwm_gpio_apply, ++ .get_state = pwm_gpio_get_state, ++}; ++ ++static void pwm_gpio_disable_hrtimer(void *data) ++{ ++ struct pwm_gpio *gpwm = data; ++ ++ hrtimer_cancel(&gpwm->gpio_timer); ++} ++ ++static int pwm_gpio_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct pwm_chip *chip; ++ struct pwm_gpio *gpwm; ++ int ret; ++ ++ gpwm = devm_kzalloc(&pdev->dev, sizeof(*gpwm), GFP_KERNEL); ++ if (IS_ERR(gpwm)) ++ return PTR_ERR(gpwm); ++ ++ chip = &gpwm->chip; ++ ++ spin_lock_init(&gpwm->lock); ++ ++ gpwm->gpio = devm_gpiod_get(dev, NULL, GPIOD_ASIS); ++ if (IS_ERR(gpwm->gpio)) ++ return dev_err_probe(dev, PTR_ERR(gpwm->gpio), ++ "%pfw: could not get gpio\n", ++ dev_fwnode(dev)); ++ ++ if (gpiod_cansleep(gpwm->gpio)) ++ return dev_err_probe(dev, -EINVAL, ++ "%pfw: sleeping GPIO not supported\n", ++ dev_fwnode(dev)); ++ ++ chip->dev = dev; ++ chip->ops = &pwm_gpio_ops; ++ chip->atomic = true; ++ chip->npwm = 1; ++ ++ hrtimer_init(&gpwm->gpio_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ ret = devm_add_action_or_reset(dev, pwm_gpio_disable_hrtimer, gpwm); ++ if (ret) ++ return ret; ++ ++ gpwm->gpio_timer.function = pwm_gpio_timer; ++ ++ return devm_pwmchip_add(dev, chip); ++} ++ ++static const struct of_device_id pwm_gpio_dt_ids[] = { ++ { .compatible = "pwm-gpio" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, pwm_gpio_dt_ids); ++ ++static struct platform_driver pwm_gpio_driver = { ++ .driver = { ++ .name = "pwm-gpio", ++ .of_match_table = pwm_gpio_dt_ids, ++ }, ++ .probe = pwm_gpio_probe, ++}; ++module_platform_driver(pwm_gpio_driver); ++ ++MODULE_DESCRIPTION("PWM GPIO driver"); ++MODULE_AUTHOR("Vincent Whitchurch"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/bcm27xx/patches-6.6/950-1355-dtoverlay-Add-a-dtoverlay-for-pwm-gpio.patch b/target/linux/bcm27xx/patches-6.6/950-1355-dtoverlay-Add-a-dtoverlay-for-pwm-gpio.patch new file mode 100644 index 0000000000..65c6be6f3f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1355-dtoverlay-Add-a-dtoverlay-for-pwm-gpio.patch @@ -0,0 +1,79 @@ +From ff0fe12ab875d587348b6f2b9e73ae928049ebee Mon Sep 17 00:00:00 2001 +From: Tim Gover +Date: Thu, 31 Oct 2024 16:12:54 +0000 +Subject: [PATCH] dtoverlay: Add a dtoverlay for pwm-gpio + +Signed-off-by: Tim Gover +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 6 +++ + .../boot/dts/overlays/pwm-gpio-overlay.dts | 38 +++++++++++++++++++ + 3 files changed, 45 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/pwm-gpio-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -217,6 +217,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + proto-codec.dtbo \ + pwm.dtbo \ + pwm-2chan.dtbo \ ++ pwm-gpio.dtbo \ + pwm-ir-tx.dtbo \ + pwm1.dtbo \ + qca7000.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -3903,6 +3903,12 @@ Params: pin Output p + clock PWM clock frequency (informational) + + ++Name: pwm-gpio ++Info: Configures the software PWM GPIO driver ++Load: dtoverlay=pwm-gpio,= ++Params: gpio Output pin (default 4) ++ ++ + Name: pwm-ir-tx + Info: Use GPIO pin as pwm-assisted infrared transmitter output. + This is an alternative to "gpio-ir-tx". pwm-ir-tx makes use +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pwm-gpio-overlay.dts +@@ -0,0 +1,38 @@ ++// Device tree overlay for software GPIO PWM. ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835"; ++ ++ fragment@0 { ++ target = <&gpio>; ++ __overlay__ { ++ pwm_gpio_pins: pwm_gpio_pins@4 { ++ brcm,pins = <4>; /* gpio 4 */ ++ brcm,function = <1>; /* output */ ++ brcm,pull = <0>; /* pull-none */ ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "/"; ++ __overlay__ { ++ pwm_gpio: pwm_gpio@4 { ++ compatible = "pwm-gpio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_gpio_pins>; ++ gpios = <&gpio 4 0>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpio = <&pwm_gpio>,"gpios:4", ++ <&pwm_gpio_pins>,"brcm,pins:0", ++ /* modify reg values to allow multiple instantiation */ ++ <&pwm_gpio>,"reg:0", ++ <&pwm_gpio_pins>,"reg:0"; ++ }; ++}; diff --git a/target/linux/bcm27xx/patches-6.6/950-1356-dts-2712-Drop-some-numa-options-from-bootargs.patch b/target/linux/bcm27xx/patches-6.6/950-1356-dts-2712-Drop-some-numa-options-from-bootargs.patch new file mode 100644 index 0000000000..245c575e2d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1356-dts-2712-Drop-some-numa-options-from-bootargs.patch @@ -0,0 +1,29 @@ +From 624eb357e1a16385b3d6171e9194e4c5f8d4fd5f Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Wed, 23 Oct 2024 19:09:18 +0100 +Subject: [PATCH] dts: 2712: Drop some numa options from bootargs + +iommu_dma_numa_policy=interleave is not valid in the current tree +It generates an unknown setting will be passed to usespace warning + +system_heap.max_order=0 is wanted when numa is enabled, but may not +be when it is disabled. + +Add it on firmware side when we know if numa=fake= is used. + +Signed-off-by: Dom Cobley +--- + arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi +@@ -99,7 +99,7 @@ + + / { + chosen: chosen { +- bootargs = "reboot=w coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe cgroup_disable=memory numa_policy=interleave iommu_dma_numa_policy=interleave system_heap.max_order=0"; ++ bootargs = "reboot=w coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe cgroup_disable=memory numa_policy=interleave"; + stdout-path = "serial10:115200n8"; + }; + diff --git a/target/linux/bcm27xx/patches-6.6/950-1357-mmc-quirks-add-more-broken-Kingston-Canvas-Go-SD-car.patch b/target/linux/bcm27xx/patches-6.6/950-1357-mmc-quirks-add-more-broken-Kingston-Canvas-Go-SD-car.patch new file mode 100644 index 0000000000..ef5a5a5dcb --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1357-mmc-quirks-add-more-broken-Kingston-Canvas-Go-SD-car.patch @@ -0,0 +1,42 @@ +From 74f3ca5e39586ea26201fe6eaf1b9e6793b101b7 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Tue, 29 Oct 2024 13:33:21 +0000 +Subject: [PATCH] mmc: quirks: add more broken Kingston Canvas Go! SD card date + ranges + +A user has reported that a card of this model from late 2021 doesn't +work, so extend the date range and make it match on all card sizes. + +Signed-off-by: Jonathan Bell +--- + drivers/mmc/core/quirks.h | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/drivers/mmc/core/quirks.h ++++ b/drivers/mmc/core/quirks.h +@@ -18,10 +18,22 @@ + static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = { + /* + * Kingston Canvas Go! Plus microSD cards never finish SD cache flush. +- * This has so far only been observed on cards from 11/2019, while new +- * cards from 2023/05 do not exhibit this behavior. ++ * This has been observed on cards from 2019/11 and 2021/11, while new ++ * cards from 2023/05 and 2024/08 do not exhibit this behavior. + */ +- _FIXUP_EXT("SD64G", CID_MANFID_KINGSTON_SD, 0x5449, 2019, 11, ++ _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_KINGSTON_SD, 0x5449, 2019, CID_MONTH_ANY, ++ 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, ++ MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), ++ ++ _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_KINGSTON_SD, 0x5449, 2020, CID_MONTH_ANY, ++ 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, ++ MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), ++ ++ _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_KINGSTON_SD, 0x5449, 2021, CID_MONTH_ANY, ++ 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, ++ MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), ++ ++ _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_KINGSTON_SD, 0x5449, 2022, CID_MONTH_ANY, + 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + diff --git a/target/linux/bcm27xx/patches-6.6/950-1358-dt-bindings-usb-snps-dwc3-add-FS-HS-periodic-NAK-pol.patch b/target/linux/bcm27xx/patches-6.6/950-1358-dt-bindings-usb-snps-dwc3-add-FS-HS-periodic-NAK-pol.patch new file mode 100644 index 0000000000..eaa340f249 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1358-dt-bindings-usb-snps-dwc3-add-FS-HS-periodic-NAK-pol.patch @@ -0,0 +1,35 @@ +From 6c0f34fb0f83741f7f03f6bfd3fcbc89cb2c7cde Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 6 Nov 2024 10:26:55 +0000 +Subject: [PATCH] dt-bindings: usb: snps,dwc3: add FS/HS periodic NAK polling + quirk + +Add two quirk properties that control whether or not the controller +issues many more handshakes to FS/HS Async endpoints in a single +(micro)frame. Enabling these can significantly increase throughput for +endpoints that frequently respond with NAKs. + +Signed-off-by: Jonathan Bell +--- + Documentation/devicetree/bindings/usb/snps,dwc3.yaml | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml ++++ b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml +@@ -231,6 +231,16 @@ properties: + description: When set, disable u2mac linestate check during HS transmit + type: boolean + ++ snps,enhanced-nak-fs-quirk: ++ description: ++ When set, the controller schedules many more handshakes to Async FS ++ endpoints, improving throughput when they frequently respond with NAKs. ++ ++ snps,enhanced-nak-hs-quirk: ++ description: ++ When set, the controller schedules many more handshakes to Async HS ++ endpoints, improving throughput when they frequently respond with NAKs. ++ + snps,parkmode-disable-ss-quirk: + description: + When set, disable park mode for all Superspeed bus instances. diff --git a/target/linux/bcm27xx/patches-6.6/950-1359-usb-dwc3-core-add-support-for-setting-NAK-enhancemen.patch b/target/linux/bcm27xx/patches-6.6/950-1359-usb-dwc3-core-add-support-for-setting-NAK-enhancemen.patch new file mode 100644 index 0000000000..ed7dbb0e6c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1359-usb-dwc3-core-add-support-for-setting-NAK-enhancemen.patch @@ -0,0 +1,77 @@ +From bb53ca75f9e3631e753f397ccab704a8f975658b Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 6 Nov 2024 10:45:24 +0000 +Subject: [PATCH] usb: dwc3: core: add support for setting NAK enhancement bits + for FS/HS + +If a device frequently NAKs, it can exhaust the scheduled handshakes in +a frame. It will then not get polled by the controller until the next +frame interval. This is most noticeable on FS devices as the controller +schedules a small set of transactions only once per full-speed frame. + +Setting the ENH_PER_NAK_FS/LS bits in the GUCTL1 register increases the +number of transactions that can be scheduled to Async (Control/Bulk) +endpoints in the respective frame time. In the FS case, this only +applies to FS devices directly connected to root ports. + +Signed-off-by: Jonathan Bell +--- + drivers/usb/dwc3/core.c | 10 ++++++++++ + drivers/usb/dwc3/core.h | 6 ++++++ + 2 files changed, 16 insertions(+) + +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1366,6 +1366,12 @@ static int dwc3_core_init(struct dwc3 *d + if (dwc->dis_tx_ipgap_linecheck_quirk) + reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS; + ++ if (dwc->enh_nak_fs_quirk) ++ reg |= DWC3_GUCTL1_NAK_PER_ENH_FS; ++ ++ if (dwc->enh_nak_hs_quirk) ++ reg |= DWC3_GUCTL1_NAK_PER_ENH_HS; ++ + if (dwc->parkmode_disable_ss_quirk) + reg |= DWC3_GUCTL1_PARKMODE_DISABLE_SS; + +@@ -1669,6 +1675,10 @@ static void dwc3_get_properties(struct d + "snps,resume-hs-terminations"); + dwc->ulpi_ext_vbus_drv = device_property_read_bool(dev, + "snps,ulpi-ext-vbus-drv"); ++ dwc->enh_nak_fs_quirk = device_property_read_bool(dev, ++ "snps,enhanced-nak-fs-quirk"); ++ dwc->enh_nak_hs_quirk = device_property_read_bool(dev, ++ "snps,enhanced-nak-hs-quirk"); + dwc->parkmode_disable_ss_quirk = device_property_read_bool(dev, + "snps,parkmode-disable-ss-quirk"); + dwc->parkmode_disable_hs_quirk = device_property_read_bool(dev, +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -269,6 +269,8 @@ + #define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28) + #define DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK BIT(26) + #define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24) ++#define DWC3_GUCTL1_NAK_PER_ENH_FS BIT(19) ++#define DWC3_GUCTL1_NAK_PER_ENH_HS BIT(18) + #define DWC3_GUCTL1_PARKMODE_DISABLE_SS BIT(17) + #define DWC3_GUCTL1_PARKMODE_DISABLE_HS BIT(16) + #define DWC3_GUCTL1_PARKMODE_DISABLE_FSLS BIT(15) +@@ -1118,6 +1120,8 @@ struct dwc3_scratchpad_array { + * generation after resume from suspend. + * @ulpi_ext_vbus_drv: Set to confiure the upli chip to drives CPEN pin + * VBUS with an external supply. ++ * @enh_nak_fs_quirk: Set to schedule more handshakes to Async FS endpoints. ++ * @enh_nak_hs_quirk: Set to schedule more handshakes to Async HS endpoints. + * @parkmode_disable_ss_quirk: If set, disable park mode feature for all + * Superspeed instances. + * @parkmode_disable_hs_quirk: If set, disable park mode feature for all +@@ -1348,6 +1352,8 @@ struct dwc3 { + unsigned dis_tx_ipgap_linecheck_quirk:1; + unsigned resume_hs_terminations:1; + unsigned ulpi_ext_vbus_drv:1; ++ unsigned enh_nak_fs_quirk:1; ++ unsigned enh_nak_hs_quirk:1; + unsigned parkmode_disable_ss_quirk:1; + unsigned parkmode_disable_hs_quirk:1; + unsigned parkmode_disable_fsls_quirk:1; diff --git a/target/linux/bcm27xx/patches-6.6/950-1360-DTS-rp1-set-enhanced-FS-NAK-quirk-for-usb3-controlle.patch b/target/linux/bcm27xx/patches-6.6/950-1360-DTS-rp1-set-enhanced-FS-NAK-quirk-for-usb3-controlle.patch new file mode 100644 index 0000000000..a305dc13fd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1360-DTS-rp1-set-enhanced-FS-NAK-quirk-for-usb3-controlle.patch @@ -0,0 +1,30 @@ +From 803757627b48bdad9530b50053321fdea6dfcab4 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 6 Nov 2024 10:54:58 +0000 +Subject: [PATCH] DTS: rp1: set enhanced FS NAK quirk for usb3 controllers + +There seem to be only benefits, and no downsides. + +Signed-off-by: Jonathan Bell +--- + arch/arm64/boot/dts/broadcom/rp1.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/broadcom/rp1.dtsi ++++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi +@@ -1077,6 +1077,7 @@ + usb3-lpm-capable; + snps,axi-pipe-limit = /bits/ 8 <8>; + snps,dis_rxdet_inp3_quirk; ++ snps,enhanced-nak-fs-quirk; + snps,parkmode-disable-ss-quirk; + snps,parkmode-disable-hs-quirk; + snps,parkmode-disable-fsls-quirk; +@@ -1093,6 +1094,7 @@ + usb3-lpm-capable; + snps,axi-pipe-limit = /bits/ 8 <8>; + snps,dis_rxdet_inp3_quirk; ++ snps,enhanced-nak-fs-quirk; + snps,parkmode-disable-ss-quirk; + snps,parkmode-disable-hs-quirk; + snps,parkmode-disable-fsls-quirk; diff --git a/target/linux/bcm27xx/patches-6.6/950-1361-drivers-usb-xhci-prevent-a-theoretical-race-on-non-c.patch b/target/linux/bcm27xx/patches-6.6/950-1361-drivers-usb-xhci-prevent-a-theoretical-race-on-non-c.patch new file mode 100644 index 0000000000..d3ea1041c2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1361-drivers-usb-xhci-prevent-a-theoretical-race-on-non-c.patch @@ -0,0 +1,50 @@ +From e9e852af347ae3ccee4e7abb01f9ef91387980f9 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 6 Nov 2024 11:07:55 +0000 +Subject: [PATCH] drivers: usb: xhci: prevent a theoretical race on + non-coherent platforms + +For platforms that have xHCI controllers attached over PCIe, and +non-coherent routes to main memory, a theoretical race exists between +posting new TRBs to a ring, and writing to the doorbell register. + +In a contended system, write traffic from the CPU may be stalled before +the memory controller, whereas the CPU to Endpoint route is separate +and not likely to be contended. Similarly, the DMA route from the +endpoint to main memory may be separate and uncontended. + +Therefore the xHCI can receive a doorbell write and find a stale view +of a transfer ring. In cases where only a single TRB is ping-ponged at +a time, this can cause the endpoint to not get polled at all. + +Adding a readl() before the write forces a round-trip transaction +across PCIe, definitively serialising the CPU along the PCI +producer-consumer ordering rules. + +Signed-off-by: Jonathan Bell +--- + drivers/usb/host/xhci-ring.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -505,6 +505,19 @@ void xhci_ring_ep_doorbell(struct xhci_h + + trace_xhci_ring_ep_doorbell(slot_id, DB_VALUE(ep_index, stream_id)); + ++ /* ++ * For non-coherent systems with PCIe DMA (such as Pi 4, Pi 5) there ++ * is a theoretical race between the TRB write and barrier, which ++ * is reported complete as soon as the write leaves the CPU domain, ++ * the doorbell write, which may be reported as complete by the RC ++ * at some arbitrary point, and the visibility of new TRBs in system ++ * RAM by the endpoint DMA engine. ++ * ++ * This read before the write positively serialises the CPU state ++ * by incurring a round-trip across the link. ++ */ ++ readl(db_addr); ++ + writel(DB_VALUE(ep_index, stream_id), db_addr); + /* flush the write */ + readl(db_addr); diff --git a/target/linux/bcm27xx/patches-6.6/950-1362-iio-humidity-dht11-Allow-non-zero-decimals.patch b/target/linux/bcm27xx/patches-6.6/950-1362-iio-humidity-dht11-Allow-non-zero-decimals.patch new file mode 100644 index 0000000000..19935d0ea5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1362-iio-humidity-dht11-Allow-non-zero-decimals.patch @@ -0,0 +1,32 @@ +From ce65ed02cb6707ae5c9f3a304f5b0124f4eed559 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 4 Nov 2024 14:10:53 +0000 +Subject: [PATCH] iio: humidity: dht11: Allow non-zero decimals + +The DHT11 datasheet is pretty cryptic, but it does suggest that after +each integer value (humidity and temperature) there are "decimal" +values. Validate these as integers in the range 0-9 and treat them as +tenths of a unit. + +Link: https://github.com/raspberrypi/linux/issues/6220 + +Signed-off-by: Phil Elwell +--- + drivers/iio/humidity/dht11.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/iio/humidity/dht11.c ++++ b/drivers/iio/humidity/dht11.c +@@ -152,9 +152,9 @@ static int dht11_decode(struct dht11 *dh + dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) * + ((temp_int & 0x80) ? -100 : 100); + dht11->humidity = ((hum_int << 8) + hum_dec) * 100; +- } else if (temp_dec == 0 && hum_dec == 0) { /* DHT11 */ +- dht11->temperature = temp_int * 1000; +- dht11->humidity = hum_int * 1000; ++ } else if (temp_dec < 10 && hum_dec < 10) { /* DHT11 */ ++ dht11->temperature = temp_int * 1000 + temp_dec * 100; ++ dht11->humidity = hum_int * 1000 + hum_dec * 100; + } else { + dev_err(dht11->dev, + "Don't know how to decode data: %d %d %d %d\n", diff --git a/target/linux/bcm27xx/patches-6.6/950-1363-drm-vc4-Correct-condition-for-ignoring-a-plane-to-sr.patch b/target/linux/bcm27xx/patches-6.6/950-1363-drm-vc4-Correct-condition-for-ignoring-a-plane-to-sr.patch new file mode 100644 index 0000000000..9b018248a5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1363-drm-vc4-Correct-condition-for-ignoring-a-plane-to-sr.patch @@ -0,0 +1,41 @@ +From c3393ac1098d1f191e37eed73bf366ebc88ac4ee Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 11 Sep 2024 14:49:05 +0100 +Subject: [PATCH] drm/vc4: Correct condition for ignoring a plane to src rect + =0, not <1.0 + +The logic for dropping a plane less than zero didn't account for the +possibility that a plane could be being upscaled with a src_rect with +width/height < 1 pixel, but not 0 subpixels. + +Check for not 0 subpixels, not < 1, in both vc4 and vc6 paths. + +Fixes: dac616899f87 ("drm/vc4: Drop planes that have 0 destination size") +Fixes: f73b18eb0d48 ("drm/vc4: Drop planes that are completely off-screen") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -1160,7 +1160,8 @@ static int vc4_plane_mode_set(struct drm + width = vc4_state->src_w[0] >> 16; + height = vc4_state->src_h[0] >> 16; + +- if (!width || !height || !vc4_state->crtc_w || !vc4_state->crtc_h) { ++ if (!vc4_state->src_w[0] || !vc4_state->src_h[0] || ++ !vc4_state->crtc_w || !vc4_state->crtc_h) { + /* 0 source size probably means the plane is offscreen */ + vc4_state->dlist_initialized = 1; + return 0; +@@ -1698,7 +1699,8 @@ static int vc6_plane_mode_set(struct drm + width = vc4_state->src_w[0] >> 16; + height = vc4_state->src_h[0] >> 16; + +- if (!width || !height || !vc4_state->crtc_w || !vc4_state->crtc_h) { ++ if (!vc4_state->src_w[0] || !vc4_state->src_h[0] || ++ !vc4_state->crtc_w || !vc4_state->crtc_h) { + /* 0 source size probably means the plane is offscreen. + * 0 destination size is a redundant plane. + */ diff --git a/target/linux/bcm27xx/patches-6.6/950-1364-drm-vc4-Use-the-TPZ-scaling-filter-for-1x1-source-im.patch b/target/linux/bcm27xx/patches-6.6/950-1364-drm-vc4-Use-the-TPZ-scaling-filter-for-1x1-source-im.patch new file mode 100644 index 0000000000..5a7b3e4c1e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1364-drm-vc4-Use-the-TPZ-scaling-filter-for-1x1-source-im.patch @@ -0,0 +1,59 @@ +From ca621585c573cae54dc1235d90822e8bcef2f73d Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 11 Sep 2024 15:23:33 +0100 +Subject: [PATCH] drm/vc4: Use the TPZ scaling filter for 1x1 source images + +The documentation says that the TPZ filter can not upscale, +and requesting a scaling factor > 1:1 will output the original +image in the top left, and repeat the right/bottom most pixels +thereafter. +That fits perfectly with upscaling a 1x1 image which is done +a fair amount by some compositors to give solid colour, and it +saves a large amount of LBM (TPZ is based on src size, whilst +PPF is based on dest size). + +Select TPZ filter for images with source rectangle <=1. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -265,7 +265,11 @@ static enum vc4_scaling_mode vc4_get_sca + { + if (dst == src >> 16) + return VC4_SCALING_NONE; +- if (3 * dst >= 2 * (src >> 16)) ++ ++ if (src <= (1 << 16)) ++ /* Source rectangle <= 1 pixel can use TPZ for resize/upscale */ ++ return VC4_SCALING_TPZ; ++ else if (3 * dst >= 2 * (src >> 16)) + return VC4_SCALING_PPF; + else + return VC4_SCALING_TPZ; +@@ -560,12 +564,17 @@ static void vc4_write_tpz(struct vc4_pla + + WARN_ON_ONCE(vc4->gen > VC4_GEN_6); + +- scale = src / dst; ++ if ((dst << 16) < src) { ++ scale = src / dst; + +- /* The specs note that while the reciprocal would be defined +- * as (1<<32)/scale, ~0 is close enough. +- */ +- recip = ~0 / scale; ++ /* The specs note that while the reciprocal would be defined ++ * as (1<<32)/scale, ~0 is close enough. ++ */ ++ recip = ~0 / scale; ++ } else { ++ scale = (1 << 16) + 1; ++ recip = (1 << 16) - 1; ++ } + + vc4_dlist_write(vc4_state, + /* diff --git a/target/linux/bcm27xx/patches-6.6/950-1365-drm-Set-non-desktop-property-to-true-for-writeback-a.patch b/target/linux/bcm27xx/patches-6.6/950-1365-drm-Set-non-desktop-property-to-true-for-writeback-a.patch new file mode 100644 index 0000000000..e8f52cbc43 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1365-drm-Set-non-desktop-property-to-true-for-writeback-a.patch @@ -0,0 +1,30 @@ +From 68b0ff3549148e614e1733d773cee8e689c763c6 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 20 Aug 2024 16:25:10 +0100 +Subject: [PATCH] drm: Set non-desktop property to true for writeback and + virtual connectors + +The non-desktop property "Indicates the output should be ignored for +purposes of displaying a standard desktop environment or console." + +That sounds like it should be true for all writeback and virtual +connectors as you shouldn't render a desktop to them, so set it +by default. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_connector.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/drm_connector.c ++++ b/drivers/gpu/drm/drm_connector.c +@@ -361,7 +361,8 @@ static int __drm_connector_init(struct d + + drm_object_attach_property(&connector->base, + config->non_desktop_property, +- 0); ++ (connector_type != DRM_MODE_CONNECTOR_VIRTUAL && ++ connector_type != DRM_MODE_CONNECTOR_WRITEBACK) ? 0 : 1; + drm_object_attach_property(&connector->base, + config->tile_property, + 0); diff --git a/target/linux/bcm27xx/patches-6.6/950-1366-drm-Increase-plane_mask-to-64bit.patch b/target/linux/bcm27xx/patches-6.6/950-1366-drm-Increase-plane_mask-to-64bit.patch new file mode 100644 index 0000000000..e27058d44c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1366-drm-Increase-plane_mask-to-64bit.patch @@ -0,0 +1,101 @@ +From 8181e682d6f4ef209845ec24f0a1eb37764d6731 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 21 Oct 2022 14:26:12 +0100 +Subject: [PATCH] drm: Increase plane_mask to 64bit. + +The limit of 32 planes per DRM device is dictated by the use +of planes_mask returning a u32. + +Change to a u64 such that 64 planes can be supported by a device. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_atomic.c | 2 +- + drivers/gpu/drm/drm_framebuffer.c | 2 +- + drivers/gpu/drm/drm_mode_config.c | 2 +- + drivers/gpu/drm/drm_plane.c | 2 +- + drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c | 2 +- + include/drm/drm_crtc.h | 2 +- + include/drm/drm_plane.h | 4 ++-- + 7 files changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/drm_atomic.c ++++ b/drivers/gpu/drm/drm_atomic.c +@@ -451,7 +451,7 @@ static void drm_atomic_crtc_print_state( + drm_printf(p, "\tactive_changed=%d\n", state->active_changed); + drm_printf(p, "\tconnectors_changed=%d\n", state->connectors_changed); + drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed); +- drm_printf(p, "\tplane_mask=%x\n", state->plane_mask); ++ drm_printf(p, "\tplane_mask=%llx\n", state->plane_mask); + drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask); + drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask); + drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode)); +--- a/drivers/gpu/drm/drm_framebuffer.c ++++ b/drivers/gpu/drm/drm_framebuffer.c +@@ -959,7 +959,7 @@ static int atomic_remove_fb(struct drm_f + struct drm_connector *conn __maybe_unused; + struct drm_connector_state *conn_state; + int i, ret; +- unsigned plane_mask; ++ u64 plane_mask; + bool disable_crtcs = false; + + retry_disable: +--- a/drivers/gpu/drm/drm_mode_config.c ++++ b/drivers/gpu/drm/drm_mode_config.c +@@ -636,7 +636,7 @@ void drm_mode_config_validate(struct drm + struct drm_encoder *encoder; + struct drm_crtc *crtc; + struct drm_plane *plane; +- u32 primary_with_crtc = 0, cursor_with_crtc = 0; ++ u64 primary_with_crtc = 0, cursor_with_crtc = 0; + unsigned int num_primary = 0; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) +--- a/drivers/gpu/drm/drm_plane.c ++++ b/drivers/gpu/drm/drm_plane.c +@@ -249,7 +249,7 @@ static int __drm_universal_plane_init(st + int ret; + + /* plane index is used with 32bit bitmasks */ +- if (WARN_ON(config->num_total_plane >= 32)) ++ if (WARN_ON(config->num_total_plane >= 64)) + return -EINVAL; + + /* +--- a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c ++++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c +@@ -230,7 +230,7 @@ static int ipu_crtc_atomic_check(struct + { + struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, + crtc); +- u32 primary_plane_mask = drm_plane_mask(crtc->primary); ++ u64 primary_plane_mask = drm_plane_mask(crtc->primary); + + if (crtc_state->active && (primary_plane_mask & crtc_state->plane_mask) == 0) + return -EINVAL; +--- a/include/drm/drm_crtc.h ++++ b/include/drm/drm_crtc.h +@@ -192,7 +192,7 @@ struct drm_crtc_state { + * @plane_mask: Bitmask of drm_plane_mask(plane) of planes attached to + * this CRTC. + */ +- u32 plane_mask; ++ u64 plane_mask; + + /** + * @connector_mask: Bitmask of drm_connector_mask(connector) of +--- a/include/drm/drm_plane.h ++++ b/include/drm/drm_plane.h +@@ -915,9 +915,9 @@ static inline unsigned int drm_plane_ind + * drm_plane_mask - find the mask of a registered plane + * @plane: plane to find mask for + */ +-static inline u32 drm_plane_mask(const struct drm_plane *plane) ++static inline u64 drm_plane_mask(const struct drm_plane *plane) + { +- return 1 << drm_plane_index(plane); ++ return 1ULL << drm_plane_index(plane); + } + + struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx); diff --git a/target/linux/bcm27xx/patches-6.6/950-1367-drm-vc4-Increase-number-of-overlay-planes-from-16-to.patch b/target/linux/bcm27xx/patches-6.6/950-1367-drm-vc4-Increase-number-of-overlay-planes-from-16-to.patch new file mode 100644 index 0000000000..6eae6fc2ac --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1367-drm-vc4-Increase-number-of-overlay-planes-from-16-to.patch @@ -0,0 +1,42 @@ +From 5dc4cef7d7fcda4ea59b9e456a835fa54336af6b Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 21 Oct 2022 14:27:45 +0100 +Subject: [PATCH] drm/vc4: Increase number of overlay planes from 16 to 48 + +The HVS can accept an arbitrary number of planes, provided +that the overall pixel read load is within limits, and +the display list can fit into the dlist memory. + +Now that DRM will support 64 planes per device, increase +the number of overlay planes from 16 to 48 so that the +dlist complexity can be increased (eg 4x4 video wall on +each of 3 displays). + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_connector.c | 2 +- + drivers/gpu/drm/vc4/vc4_plane.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/drm_connector.c ++++ b/drivers/gpu/drm/drm_connector.c +@@ -362,7 +362,7 @@ static int __drm_connector_init(struct d + drm_object_attach_property(&connector->base, + config->non_desktop_property, + (connector_type != DRM_MODE_CONNECTOR_VIRTUAL && +- connector_type != DRM_MODE_CONNECTOR_WRITEBACK) ? 0 : 1; ++ connector_type != DRM_MODE_CONNECTOR_WRITEBACK) ? 0 : 1); + drm_object_attach_property(&connector->base, + config->tile_property, + 0); +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -2517,7 +2517,7 @@ struct drm_plane *vc4_plane_init(struct + return plane; + } + +-#define VC4_NUM_OVERLAY_PLANES 16 ++#define VC4_NUM_OVERLAY_PLANES 48 + + int vc4_plane_create_additional_planes(struct drm_device *drm) + { diff --git a/target/linux/bcm27xx/patches-6.6/950-1368-drm-vc4-Assign-32-overlay-planes-to-writeback-only.patch b/target/linux/bcm27xx/patches-6.6/950-1368-drm-vc4-Assign-32-overlay-planes-to-writeback-only.patch new file mode 100644 index 0000000000..40eff3cc1f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1368-drm-vc4-Assign-32-overlay-planes-to-writeback-only.patch @@ -0,0 +1,71 @@ +From dd340cb082a020fbd42b794493ffd063dd8e15b4 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 15 Aug 2023 15:44:34 +0100 +Subject: [PATCH] drm/vc4: Assign 32 overlay planes to writeback only + +Instead of having 48 generic overlay planes, assign 32 to the +writeback connector so that there is no ambiguity in wlroots +when trying to find a plane for composition using the writeback +connector vs display. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 34 +++++++++++++++++++++++++++++++-- + 1 file changed, 32 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -2517,13 +2517,28 @@ struct drm_plane *vc4_plane_init(struct + return plane; + } + +-#define VC4_NUM_OVERLAY_PLANES 48 ++#define VC4_NUM_OVERLAY_PLANES 16 ++#define VC4_NUM_TXP_OVERLAY_PLANES 32 + + int vc4_plane_create_additional_planes(struct drm_device *drm) + { + struct drm_plane *cursor_plane; + struct drm_crtc *crtc; + unsigned int i; ++ struct drm_crtc *txp_crtc; ++ uint32_t non_txp_crtc_mask; ++ ++ drm_for_each_crtc(crtc, drm) { ++ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); ++ ++ if (vc4_crtc->feeds_txp) { ++ txp_crtc = crtc; ++ break; ++ } ++ } ++ ++ non_txp_crtc_mask = GENMASK(drm->mode_config.num_crtc - 1, 0) - ++ drm_crtc_mask(txp_crtc); + + /* Set up some arbitrary number of planes. We're not limited + * by a set number of physical registers, just the space in +@@ -2537,7 +2552,22 @@ int vc4_plane_create_additional_planes(s + for (i = 0; i < VC4_NUM_OVERLAY_PLANES; i++) { + struct drm_plane *plane = + vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, +- GENMASK(drm->mode_config.num_crtc - 1, 0)); ++ non_txp_crtc_mask); ++ ++ if (IS_ERR(plane)) ++ continue; ++ ++ /* Create zpos property. Max of all the overlays + 1 primary + ++ * 1 cursor plane on a crtc. ++ */ ++ drm_plane_create_zpos_property(plane, i + 1, 1, ++ VC4_NUM_OVERLAY_PLANES + 1); ++ } ++ ++ for (i = 0; i < VC4_NUM_TXP_OVERLAY_PLANES; i++) { ++ struct drm_plane *plane = ++ vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY, ++ drm_crtc_mask(txp_crtc)); + + if (IS_ERR(plane)) + continue; diff --git a/target/linux/bcm27xx/patches-6.6/950-1369-drm-Add-a-DRM_MODE_TRANSPOSE-option-to-the-DRM-rotat.patch b/target/linux/bcm27xx/patches-6.6/950-1369-drm-Add-a-DRM_MODE_TRANSPOSE-option-to-the-DRM-rotat.patch new file mode 100644 index 0000000000..ccda8b05c2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1369-drm-Add-a-DRM_MODE_TRANSPOSE-option-to-the-DRM-rotat.patch @@ -0,0 +1,47 @@ +From b3b3d12cf0734318a0fed0b33e13d714188369db Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 22 Oct 2024 17:17:31 +0100 +Subject: [PATCH] drm: Add a DRM_MODE_TRANSPOSE option to the DRM rotation + property + +Some hardware will implement transpose as a rotation operation, +which when combined with X and Y reflect can result in a rotation, +but is a discrete operation in its own right. + +Add an option for transpose only. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_blend.c | 3 +++ + include/uapi/drm/drm_mode.h | 1 + + 2 files changed, 4 insertions(+) + +--- a/drivers/gpu/drm/drm_blend.c ++++ b/drivers/gpu/drm/drm_blend.c +@@ -263,6 +263,8 @@ EXPORT_SYMBOL(drm_plane_create_alpha_pro + * "reflect-x" + * DRM_MODE_REFLECT_Y: + * "reflect-y" ++ * DRM_MODE_TRANSPOSE: ++ * "transpose" + * + * Rotation is the specified amount in degrees in counter clockwise direction, + * the X and Y axis are within the source rectangle, i.e. the X/Y axis before +@@ -280,6 +282,7 @@ int drm_plane_create_rotation_property(s + { __builtin_ffs(DRM_MODE_ROTATE_270) - 1, "rotate-270" }, + { __builtin_ffs(DRM_MODE_REFLECT_X) - 1, "reflect-x" }, + { __builtin_ffs(DRM_MODE_REFLECT_Y) - 1, "reflect-y" }, ++ { __builtin_ffs(DRM_MODE_TRANSPOSE) - 1, "transpose" }, + }; + struct drm_property *prop; + +--- a/include/uapi/drm/drm_mode.h ++++ b/include/uapi/drm/drm_mode.h +@@ -203,6 +203,7 @@ extern "C" { + */ + #define DRM_MODE_REFLECT_X (1<<4) + #define DRM_MODE_REFLECT_Y (1<<5) ++#define DRM_MODE_TRANSPOSE (1<<6) + + /* + * DRM_MODE_REFLECT_MASK diff --git a/target/linux/bcm27xx/patches-6.6/950-1370-drm-Add-a-rotation-parameter-to-connectors.patch b/target/linux/bcm27xx/patches-6.6/950-1370-drm-Add-a-rotation-parameter-to-connectors.patch new file mode 100644 index 0000000000..e803a7732f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1370-drm-Add-a-rotation-parameter-to-connectors.patch @@ -0,0 +1,164 @@ +From 8fec3ff870499256f2c18fe7983f6ed3fea4faaf Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 22 Oct 2024 17:22:40 +0100 +Subject: [PATCH] drm: Add a rotation parameter to connectors. + +Some connectors, particularly writeback, can implement flip +or transpose operations as writing back to memory. + +Add a connector rotation property to control this. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_atomic_uapi.c | 4 +++ + drivers/gpu/drm/drm_blend.c | 50 ++++++++++++++++++++++++------- + include/drm/drm_blend.h | 5 ++++ + include/drm/drm_connector.h | 11 +++++++ + 4 files changed, 60 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/drm_atomic_uapi.c ++++ b/drivers/gpu/drm/drm_atomic_uapi.c +@@ -811,6 +811,8 @@ static int drm_atomic_connector_set_prop + state->max_requested_bpc = val; + } else if (property == connector->privacy_screen_sw_state_property) { + state->privacy_screen_sw_state = val; ++ } else if (property == connector->rotation_property) { ++ state->rotation = val; + } else if (connector->funcs->atomic_set_property) { + return connector->funcs->atomic_set_property(connector, + state, property, val); +@@ -900,6 +902,8 @@ drm_atomic_connector_get_property(struct + *val = state->max_requested_bpc; + } else if (property == connector->privacy_screen_sw_state_property) { + *val = state->privacy_screen_sw_state; ++ } else if (property == connector->rotation_property) { ++ *val = state->rotation; + } else if (connector->funcs->atomic_get_property) { + return connector->funcs->atomic_get_property(connector, + state, property, val); +--- a/drivers/gpu/drm/drm_blend.c ++++ b/drivers/gpu/drm/drm_blend.c +@@ -235,6 +235,16 @@ int drm_plane_create_alpha_property(stru + } + EXPORT_SYMBOL(drm_plane_create_alpha_property); + ++static const struct drm_prop_enum_list drm_rotate_props[] = { ++ { __builtin_ffs(DRM_MODE_ROTATE_0) - 1, "rotate-0" }, ++ { __builtin_ffs(DRM_MODE_ROTATE_90) - 1, "rotate-90" }, ++ { __builtin_ffs(DRM_MODE_ROTATE_180) - 1, "rotate-180" }, ++ { __builtin_ffs(DRM_MODE_ROTATE_270) - 1, "rotate-270" }, ++ { __builtin_ffs(DRM_MODE_REFLECT_X) - 1, "reflect-x" }, ++ { __builtin_ffs(DRM_MODE_REFLECT_Y) - 1, "reflect-y" }, ++ { __builtin_ffs(DRM_MODE_TRANSPOSE) - 1, "transpose" }, ++}; ++ + /** + * drm_plane_create_rotation_property - create a new rotation property + * @plane: drm plane +@@ -275,15 +285,6 @@ int drm_plane_create_rotation_property(s + unsigned int rotation, + unsigned int supported_rotations) + { +- static const struct drm_prop_enum_list props[] = { +- { __builtin_ffs(DRM_MODE_ROTATE_0) - 1, "rotate-0" }, +- { __builtin_ffs(DRM_MODE_ROTATE_90) - 1, "rotate-90" }, +- { __builtin_ffs(DRM_MODE_ROTATE_180) - 1, "rotate-180" }, +- { __builtin_ffs(DRM_MODE_ROTATE_270) - 1, "rotate-270" }, +- { __builtin_ffs(DRM_MODE_REFLECT_X) - 1, "reflect-x" }, +- { __builtin_ffs(DRM_MODE_REFLECT_Y) - 1, "reflect-y" }, +- { __builtin_ffs(DRM_MODE_TRANSPOSE) - 1, "transpose" }, +- }; + struct drm_property *prop; + + WARN_ON((supported_rotations & DRM_MODE_ROTATE_MASK) == 0); +@@ -291,7 +292,8 @@ int drm_plane_create_rotation_property(s + WARN_ON(rotation & ~supported_rotations); + + prop = drm_property_create_bitmask(plane->dev, 0, "rotation", +- props, ARRAY_SIZE(props), ++ drm_rotate_props, ++ ARRAY_SIZE(drm_rotate_props), + supported_rotations); + if (!prop) + return -ENOMEM; +@@ -307,6 +309,34 @@ int drm_plane_create_rotation_property(s + } + EXPORT_SYMBOL(drm_plane_create_rotation_property); + ++int drm_connector_create_rotation_property(struct drm_connector *conn, ++ unsigned int rotation, ++ unsigned int supported_rotations) ++{ ++ struct drm_property *prop; ++ ++ WARN_ON((supported_rotations & DRM_MODE_ROTATE_MASK) == 0); ++ WARN_ON(!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK)); ++ WARN_ON(rotation & ~supported_rotations); ++ ++ prop = drm_property_create_bitmask(conn->dev, 0, "rotation", ++ drm_rotate_props, ++ ARRAY_SIZE(drm_rotate_props), ++ supported_rotations); ++ if (!prop) ++ return -ENOMEM; ++ ++ drm_object_attach_property(&conn->base, prop, rotation); ++ ++ if (conn->state) ++ conn->state->rotation = rotation; ++ ++ conn->rotation_property = prop; ++ ++ return 0; ++} ++EXPORT_SYMBOL(drm_connector_create_rotation_property); ++ + /** + * drm_rotation_simplify() - Try to simplify the rotation + * @rotation: Rotation to be simplified +--- a/include/drm/drm_blend.h ++++ b/include/drm/drm_blend.h +@@ -34,6 +34,7 @@ + struct drm_device; + struct drm_atomic_state; + struct drm_plane; ++struct drm_connector; + + static inline bool drm_rotation_90_or_270(unsigned int rotation) + { +@@ -58,4 +59,8 @@ int drm_atomic_normalize_zpos(struct drm + struct drm_atomic_state *state); + int drm_plane_create_blend_mode_property(struct drm_plane *plane, + unsigned int supported_modes); ++ ++int drm_connector_create_rotation_property(struct drm_connector *conn, ++ unsigned int rotation, ++ unsigned int supported_rotations); + #endif +--- a/include/drm/drm_connector.h ++++ b/include/drm/drm_connector.h +@@ -1029,6 +1029,11 @@ struct drm_connector_state { + * DRM blob property for HDR output metadata + */ + struct drm_property_blob *hdr_output_metadata; ++ ++ /** ++ * @rotation: Connector property to rotate the maximum output image. ++ */ ++ u32 rotation; + }; + + /** +@@ -1696,6 +1701,12 @@ struct drm_connector { + */ + struct drm_property *privacy_screen_hw_state_property; + ++ /** ++ * @rotation_property: Optional DRM property controlling rotation of the ++ * output. ++ */ ++ struct drm_property *rotation_property; ++ + #define DRM_CONNECTOR_POLL_HPD (1 << 0) + #define DRM_CONNECTOR_POLL_CONNECT (1 << 1) + #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2) diff --git a/target/linux/bcm27xx/patches-6.6/950-1371-drm-vc4-txp-Add-a-rotation-property-to-the-writeback.patch b/target/linux/bcm27xx/patches-6.6/950-1371-drm-vc4-txp-Add-a-rotation-property-to-the-writeback.patch new file mode 100644 index 0000000000..b0e5566ac1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1371-drm-vc4-txp-Add-a-rotation-property-to-the-writeback.patch @@ -0,0 +1,65 @@ +From 8346446098032c62d1de891a97c7f62264b18f81 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 14 Aug 2024 16:41:07 +0100 +Subject: [PATCH] drm/vc4: txp: Add a rotation property to the writeback + connector + +The txp block can implement transpose as it writes out the image +data, so expose that through the new connector rotation property. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_txp.c | 21 +++++++++++++++++---- + 1 file changed, 17 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -15,6 +15,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -259,10 +260,15 @@ static int vc4_txp_connector_atomic_chec + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + + fb = conn_state->writeback_job->fb; +- if (fb->width != crtc_state->mode.hdisplay || +- fb->height != crtc_state->mode.vdisplay) { +- DRM_DEBUG_KMS("Invalid framebuffer size %ux%u\n", +- fb->width, fb->height); ++ if ((conn_state->rotation == DRM_MODE_ROTATE_0 && ++ fb->width != crtc_state->mode.hdisplay && ++ fb->height != crtc_state->mode.vdisplay) || ++ (conn_state->rotation == (DRM_MODE_ROTATE_0 | DRM_MODE_TRANSPOSE) && ++ fb->width != crtc_state->mode.vdisplay && ++ fb->height != crtc_state->mode.hdisplay)) { ++ DRM_DEBUG_KMS("Invalid framebuffer size %ux%u vs mode %ux%u\n", ++ fb->width, fb->height, ++ crtc_state->mode.hdisplay, crtc_state->mode.vdisplay); + return -EINVAL; + } + +@@ -330,6 +336,9 @@ static void vc4_txp_connector_atomic_com + */ + ctrl |= TXP_ALPHA_INVERT; + ++ if (conn_state->rotation & DRM_MODE_TRANSPOSE) ++ ctrl |= TXP_TRANSPOSE; ++ + if (!drm_dev_enter(drm, &idx)) + return; + +@@ -608,6 +617,10 @@ static int vc4_txp_bind(struct device *d + if (ret) + return ret; + ++ drm_connector_create_rotation_property(&txp->connector.base, DRM_MODE_ROTATE_0, ++ DRM_MODE_ROTATE_0 | ++ DRM_MODE_TRANSPOSE); ++ + ret = devm_request_irq(dev, irq, vc4_txp_interrupt, 0, + dev_name(dev), txp); + if (ret) diff --git a/target/linux/bcm27xx/patches-6.6/950-1372-dmaengine-dw-axi-dmac-Allow-client-chosen-width.patch b/target/linux/bcm27xx/patches-6.6/950-1372-dmaengine-dw-axi-dmac-Allow-client-chosen-width.patch new file mode 100644 index 0000000000..90688668b8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1372-dmaengine-dw-axi-dmac-Allow-client-chosen-width.patch @@ -0,0 +1,40 @@ +From a2fa911d90495762047c05dec4241308ae61ca36 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 19 Sep 2024 18:05:00 +0100 +Subject: [PATCH] dmaengine: dw-axi-dmac: Allow client-chosen width + +For devices where transfer lengths are not known upfront, there is a +danger when the destination is wider than the source that partial words +can be lost at the end of a transfer. Ideally the controller would be +able to flush the residue, but it can't - it's not even possible to tell +that there is any. + +Instead, allow the client driver to avoid the problem by setting a +smaller width. + +Signed-off-by: Phil Elwell +--- + drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +@@ -724,6 +724,18 @@ static int dw_axi_dma_set_hw_desc(struct + case DMA_DEV_TO_MEM: + reg_burst_msize = axi_dma_encode_msize(chan->config.src_maxburst); + reg_width = __ffs(chan->config.src_addr_width); ++ /* ++ * For devices where transfer lengths are not known upfront, ++ * there is a danger when the destination is wider than the ++ * source that partial words can be lost at the end of a transfer. ++ * Ideally the controller would be able to flush the residue, but ++ * it can't - it's not even possible to tell that there is any. ++ * Instead, allow the client driver to avoid the problem by setting ++ * a smaller width. ++ */ ++ if (chan->config.dst_addr_width && ++ (chan->config.dst_addr_width < mem_width)) ++ mem_width = chan->config.dst_addr_width; + device_addr = phys_to_dma(chan->chip->dev, chan->config.src_addr); + ctllo = reg_width << CH_CTL_L_SRC_WIDTH_POS | + mem_width << CH_CTL_L_DST_WIDTH_POS | diff --git a/target/linux/bcm27xx/patches-6.6/950-1373-spi-dw-Let-the-DMAC-set-the-transfer-widths.patch b/target/linux/bcm27xx/patches-6.6/950-1373-spi-dw-Let-the-DMAC-set-the-transfer-widths.patch new file mode 100644 index 0000000000..786af04036 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1373-spi-dw-Let-the-DMAC-set-the-transfer-widths.patch @@ -0,0 +1,31 @@ +From 5cf7209c294a58029984880d4858e2d3c7e46a3c Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 19 Sep 2024 18:12:12 +0100 +Subject: [PATCH] spi: dw: Let the DMAC set the transfer widths + +SPI transfers are of defined length, unlike some UART traffic, so it is +safe to let the DMA controller choose a suitable memory width. + +Signed-off-by: Phil Elwell +--- + drivers/spi/spi-dw-dma.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/spi/spi-dw-dma.c ++++ b/drivers/spi/spi-dw-dma.c +@@ -330,7 +330,6 @@ static int dw_spi_dma_config_tx(struct d + txconf.direction = DMA_MEM_TO_DEV; + txconf.dst_addr = dws->dma_addr; + txconf.dst_maxburst = dws->txburst; +- txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + txconf.dst_addr_width = dw_spi_dma_convert_width(dws->n_bytes); + txconf.device_fc = false; + +@@ -431,7 +430,6 @@ static int dw_spi_dma_config_rx(struct d + rxconf.direction = DMA_DEV_TO_MEM; + rxconf.src_addr = dws->dma_addr; + rxconf.src_maxburst = dws->rxburst; +- rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + rxconf.src_addr_width = dw_spi_dma_convert_width(dws->n_bytes); + rxconf.device_fc = false; + diff --git a/target/linux/bcm27xx/patches-6.6/950-1374-serial-pl011-Request-a-memory-width-of-1-byte.patch b/target/linux/bcm27xx/patches-6.6/950-1374-serial-pl011-Request-a-memory-width-of-1-byte.patch new file mode 100644 index 0000000000..860d35b2f3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1374-serial-pl011-Request-a-memory-width-of-1-byte.patch @@ -0,0 +1,25 @@ +From 8894298105f4cb41dfa41e0b0d3c40c3f7b92c44 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 19 Sep 2024 18:22:24 +0100 +Subject: [PATCH] serial: pl011: Request a memory width of 1 byte + +In order to avoid losing residue bytes when a receive is terminated +early, set the destination width to single bytes. + +Link: https://github.com/raspberrypi/linux/issues/6365 + +Signed-off-by: Phil Elwell +--- + drivers/tty/serial/amba-pl011.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -468,6 +468,7 @@ static void pl011_dma_probe(struct uart_ + .src_addr = uap->port.mapbase + + pl011_reg_to_offset(uap, REG_DR), + .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, ++ .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, + .direction = DMA_DEV_TO_MEM, + .src_maxburst = uap->fifosize >> 2, + .device_fc = false, diff --git a/target/linux/bcm27xx/patches-6.6/950-1377-drivers-usb-xhci-set-HID-bit-in-streaming-endpoint-c.patch b/target/linux/bcm27xx/patches-6.6/950-1377-drivers-usb-xhci-set-HID-bit-in-streaming-endpoint-c.patch new file mode 100644 index 0000000000..230537f505 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1377-drivers-usb-xhci-set-HID-bit-in-streaming-endpoint-c.patch @@ -0,0 +1,56 @@ +From 66aef6ce3557edd9d58d794e4a800c5be49ca0e7 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 11 Nov 2024 10:30:38 +0000 +Subject: [PATCH] drivers: usb: xhci: set HID bit in streaming endpoint + contexts + +The xHC may commence Host Initiated Data Moves for streaming endpoints - +see USB3.2 spec s8.12.1.4.2.4. However, this behaviour is typically +counterproductive as the submission of UAS URBs in {Status, Data, +Command} order and 1 outstanding IO per stream ID means the device never +enters Move Data after a HIMD for Status or Data stages with the same +stream ID. For OUT transfers this is especially inefficient as the host +will start transmitting multiple bulk packets as a burst, all of which +get NAKed by the device - wasting bandwidth. + +Also, some buggy UAS adapters don't properly handle the EP flow control +state this creates - e.g. RTL9210. + +Set Host Initiated Data Move Disable to always defer stream selection to +the device. xHC implementations may treat this field as "don't care, +forced to 1" anyway - xHCI 1.2 s4.12.1. + +Signed-off-by: Jonathan Bell +--- + drivers/usb/host/xhci-mem.c | 8 ++++++++ + drivers/usb/host/xhci.h | 2 ++ + 2 files changed, 10 insertions(+) + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -716,6 +716,14 @@ void xhci_setup_streams_ep_input_ctx(str + ep_ctx->ep_info &= cpu_to_le32(~EP_MAXPSTREAMS_MASK); + ep_ctx->ep_info |= cpu_to_le32(EP_MAXPSTREAMS(max_primary_streams) + | EP_HAS_LSA); ++ ++ /* ++ * Set Host Initiated Data Move Disable to always defer stream ++ * selection to the device. xHC implementations may treat this ++ * field as "don't care, forced to 1" anyway - xHCI 1.2 s4.12.1. ++ */ ++ ep_ctx->ep_info2 |= EP_HID; ++ + ep_ctx->deq = cpu_to_le64(stream_info->ctx_array_dma); + } + +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -492,6 +492,8 @@ struct xhci_ep_ctx { + #define CTX_TO_EP_MAXPSTREAMS(p) (((p) & EP_MAXPSTREAMS_MASK) >> 10) + /* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */ + #define EP_HAS_LSA (1 << 15) ++/* Host initiated data move disable in info2 */ ++#define EP_HID (1 << 7) + /* hosts with LEC=1 use bits 31:24 as ESIT high bits. */ + #define CTX_TO_MAX_ESIT_PAYLOAD_HI(p) (((p) >> 24) & 0xff) + diff --git a/target/linux/bcm27xx/patches-6.6/950-1379-media-i2c-imx477-Add-options-for-slightly-modifying-.patch b/target/linux/bcm27xx/patches-6.6/950-1379-media-i2c-imx477-Add-options-for-slightly-modifying-.patch new file mode 100644 index 0000000000..ee06051957 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1379-media-i2c-imx477-Add-options-for-slightly-modifying-.patch @@ -0,0 +1,199 @@ +From 35e50ee3d66e014d869f0d7a3468bef964d26d32 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 14 Nov 2024 13:14:02 +0000 +Subject: [PATCH] media: i2c: imx477: Add options for slightly modifying the + link freq + +The default link frequency of 450MHz has been noted to interfere +with GPS if they are in close proximty. +Add the option for 453 and 456MHz to move the signal slightly out +of the band. (447MHz can not be offered as corruption is then observed +on the 133x992 10bit mode). + +Signed-off-by: Dave Stevenson + +fixup imx477 gps +--- + drivers/media/i2c/imx477.c | 86 +++++++++++++++++++++++++++++--------- + 1 file changed, 67 insertions(+), 19 deletions(-) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -164,8 +164,48 @@ struct imx477_mode { + struct imx477_reg_list reg_list; + }; + +-static const s64 imx477_link_freq_menu[] = { +- IMX477_DEFAULT_LINK_FREQ, ++/* Link frequency setup */ ++enum { ++ IMX477_LINK_FREQ_450MHZ, ++ IMX477_LINK_FREQ_453MHZ, ++ IMX477_LINK_FREQ_456MHZ, ++}; ++ ++static const s64 link_freqs[] = { ++ [IMX477_LINK_FREQ_450MHZ] = 450000000, ++ [IMX477_LINK_FREQ_453MHZ] = 453000000, ++ [IMX477_LINK_FREQ_456MHZ] = 456000000, ++}; ++ ++/* 450MHz is the nominal "default" link frequency */ ++static const struct imx477_reg link_450Mhz_regs[] = { ++ {0x030E, 0x00}, ++ {0x030F, 0x96}, ++}; ++ ++static const struct imx477_reg link_453Mhz_regs[] = { ++ {0x030E, 0x00}, ++ {0x030F, 0x97}, ++}; ++ ++static const struct imx477_reg link_456Mhz_regs[] = { ++ {0x030E, 0x00}, ++ {0x030F, 0x98}, ++}; ++ ++static const struct imx477_reg_list link_freq_regs[] = { ++ [IMX477_LINK_FREQ_450MHZ] = { ++ .regs = link_450Mhz_regs, ++ .num_of_regs = ARRAY_SIZE(link_450Mhz_regs) ++ }, ++ [IMX477_LINK_FREQ_453MHZ] = { ++ .regs = link_453Mhz_regs, ++ .num_of_regs = ARRAY_SIZE(link_453Mhz_regs) ++ }, ++ [IMX477_LINK_FREQ_456MHZ] = { ++ .regs = link_456Mhz_regs, ++ .num_of_regs = ARRAY_SIZE(link_456Mhz_regs) ++ }, + }; + + static const struct imx477_reg mode_common_regs[] = { +@@ -558,8 +598,6 @@ static const struct imx477_reg mode_4056 + {0x0309, 0x0c}, + {0x030b, 0x02}, + {0x030d, 0x02}, +- {0x030e, 0x00}, +- {0x030f, 0x96}, + {0x0310, 0x01}, + {0x0820, 0x07}, + {0x0821, 0x08}, +@@ -659,8 +697,6 @@ static const struct imx477_reg mode_2028 + {0x0309, 0x0c}, + {0x030b, 0x02}, + {0x030d, 0x02}, +- {0x030e, 0x00}, +- {0x030f, 0x96}, + {0x0310, 0x01}, + {0x0820, 0x07}, + {0x0821, 0x08}, +@@ -760,8 +796,6 @@ static const struct imx477_reg mode_2028 + {0x0309, 0x0c}, + {0x030b, 0x02}, + {0x030d, 0x02}, +- {0x030e, 0x00}, +- {0x030f, 0x96}, + {0x0310, 0x01}, + {0x0820, 0x07}, + {0x0821, 0x08}, +@@ -890,8 +924,6 @@ static const struct imx477_reg mode_1332 + {0x0309, 0x0a}, + {0x030b, 0x02}, + {0x030d, 0x02}, +- {0x030e, 0x00}, +- {0x030f, 0x96}, + {0x0310, 0x01}, + {0x0820, 0x07}, + {0x0821, 0x08}, +@@ -1121,6 +1153,8 @@ struct imx477 { + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hblank; + ++ unsigned int link_freq_idx; ++ + /* Current mode */ + const struct imx477_mode *mode; + +@@ -1712,7 +1746,7 @@ static int imx477_get_selection(struct v + static int imx477_start_streaming(struct imx477 *imx477) + { + struct i2c_client *client = v4l2_get_subdevdata(&imx477->sd); +- const struct imx477_reg_list *reg_list; ++ const struct imx477_reg_list *reg_list, *freq_regs; + const struct imx477_reg_list *extra_regs; + int ret, tm; + +@@ -1725,6 +1759,13 @@ static int imx477_start_streaming(struct + extra_regs->num_of_regs); + } + ++ if (!ret) { ++ /* Update the link frequency registers */ ++ freq_regs = &link_freq_regs[imx477->link_freq_idx]; ++ ret = imx477_write_regs(imx477, freq_regs->regs, ++ freq_regs->num_of_regs); ++ } ++ + if (ret) { + dev_err(&client->dev, "%s failed to set common settings\n", + __func__); +@@ -2010,9 +2051,8 @@ static int imx477_init_controls(struct i + /* LINK_FREQ is also read only */ + imx477->link_freq = + v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx477_ctrl_ops, +- V4L2_CID_LINK_FREQ, +- ARRAY_SIZE(imx477_link_freq_menu) - 1, 0, +- imx477_link_freq_menu); ++ V4L2_CID_LINK_FREQ, 1, 0, ++ &link_freqs[imx477->link_freq_idx]); + if (imx477->link_freq) + imx477->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + +@@ -2110,13 +2150,14 @@ static void imx477_free_controls(struct + mutex_destroy(&imx477->mutex); + } + +-static int imx477_check_hwcfg(struct device *dev) ++static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477) + { + struct fwnode_handle *endpoint; + struct v4l2_fwnode_endpoint ep_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + int ret = -EINVAL; ++ int i; + + endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); + if (!endpoint) { +@@ -2141,11 +2182,18 @@ static int imx477_check_hwcfg(struct dev + goto error_out; + } + +- if (ep_cfg.nr_of_link_frequencies != 1 || +- ep_cfg.link_frequencies[0] != IMX477_DEFAULT_LINK_FREQ) { ++ for (i = 0; i < ARRAY_SIZE(link_freqs); i++) { ++ if (link_freqs[i] == ep_cfg.link_frequencies[0]) { ++ imx477->link_freq_idx = i; ++ break; ++ } ++ } ++ ++ if (i == ARRAY_SIZE(link_freqs)) { + dev_err(dev, "Link frequency not supported: %lld\n", + ep_cfg.link_frequencies[0]); +- goto error_out; ++ ret = -EINVAL; ++ goto error_out; + } + + ret = 0; +@@ -2206,7 +2254,7 @@ static int imx477_probe(struct i2c_clien + (const struct imx477_compatible_data *)match->data; + + /* Check the hardware configuration in device tree */ +- if (imx477_check_hwcfg(dev)) ++ if (imx477_check_hwcfg(dev, imx477)) + return -EINVAL; + + /* Default the trigger mode from OF to -1, which means invalid */ diff --git a/target/linux/bcm27xx/patches-6.6/950-1380-dtoverlays-Add-link-frequency-override-to-imx477-378.patch b/target/linux/bcm27xx/patches-6.6/950-1380-dtoverlays-Add-link-frequency-override-to-imx477-378.patch new file mode 100644 index 0000000000..47d3d39200 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1380-dtoverlays-Add-link-frequency-override-to-imx477-378.patch @@ -0,0 +1,43 @@ +From 7e253a062d5a14de13ccfb410570975099c238be Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 14 Nov 2024 13:15:24 +0000 +Subject: [PATCH] dtoverlays: Add link-frequency override to imx477/378 overlay + +Copy of the imx708 change. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/overlays/README | 4 ++++ + arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi | 1 + + 2 files changed, 5 insertions(+) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -2780,6 +2780,8 @@ Params: rotation Mounting + camera clamping I/Os such as XVS to 0V. + sync-source Configure as vsync source + sync-sink Configure as vsync sink ++ link-frequency Allowable link frequency values to use in Hz: ++ 450000000 (default), 453000000, 456000000. + + + Name: imx462 +@@ -2822,6 +2824,8 @@ Params: rotation Mounting + camera clamping I/Os such as XVS to 0V. + sync-source Configure as vsync source + sync-sink Configure as vsync sink ++ link-frequency Allowable link frequency values to use in Hz: ++ 450000000 (default), 453000000, 456000000. + + + Name: imx500 +--- a/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi ++++ b/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi +@@ -80,6 +80,7 @@ + <&cam_node>, "clocks:0=",<&cam0_clk>, + <&cam_node>, "VANA-supply:0=",<&cam0_reg>; + always-on = <0>, "+99"; ++ link-frequency = <&cam_endpoint>,"link-frequencies#0"; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.6/950-1381-dmaengine-dw-axi-dmac-Only-start-idle-channels.patch b/target/linux/bcm27xx/patches-6.6/950-1381-dmaengine-dw-axi-dmac-Only-start-idle-channels.patch new file mode 100644 index 0000000000..81b7f805f3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1381-dmaengine-dw-axi-dmac-Only-start-idle-channels.patch @@ -0,0 +1,29 @@ +From 59a8855b51c1d8acf37d3c80f34782d71f474617 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 13 Nov 2024 10:37:22 +0000 +Subject: [PATCH] dmaengine: dw-axi-dmac: Only start idle channels + +Attempting to start a non-idle channel causes an error message to be +logged, and is inefficient. Test for emptiness of the desc_issued list +before doing so. + +Signed-off-by: Phil Elwell +--- + drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +@@ -536,9 +536,11 @@ static void dma_chan_issue_pending(struc + { + struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan); + unsigned long flags; ++ bool was_empty; + + spin_lock_irqsave(&chan->vc.lock, flags); +- if (vchan_issue_pending(&chan->vc)) ++ was_empty = list_empty(&chan->vc.desc_issued); ++ if (vchan_issue_pending(&chan->vc) && was_empty) + axi_chan_start_first_queued(chan); + spin_unlock_irqrestore(&chan->vc.lock, flags); + } diff --git a/target/linux/bcm27xx/patches-6.6/950-1351-mailbox-Add-RP1-mailbox-support.patch b/target/linux/bcm27xx/patches-6.6/950-1382-mailbox-Add-RP1-mailbox-support.patch similarity index 100% rename from target/linux/bcm27xx/patches-6.6/950-1351-mailbox-Add-RP1-mailbox-support.patch rename to target/linux/bcm27xx/patches-6.6/950-1382-mailbox-Add-RP1-mailbox-support.patch diff --git a/target/linux/bcm27xx/patches-6.6/950-1352-firmware-Add-an-RP1-firmware-interface.patch b/target/linux/bcm27xx/patches-6.6/950-1383-firmware-Add-an-RP1-firmware-interface-over-mbox.patch similarity index 100% rename from target/linux/bcm27xx/patches-6.6/950-1352-firmware-Add-an-RP1-firmware-interface.patch rename to target/linux/bcm27xx/patches-6.6/950-1383-firmware-Add-an-RP1-firmware-interface-over-mbox.patch diff --git a/target/linux/bcm27xx/patches-6.6/950-1353-misc-Add-RP1-PIO-driver.patch b/target/linux/bcm27xx/patches-6.6/950-1384-misc-Add-RP1-PIO-driver.patch similarity index 100% rename from target/linux/bcm27xx/patches-6.6/950-1353-misc-Add-RP1-PIO-driver.patch rename to target/linux/bcm27xx/patches-6.6/950-1384-misc-Add-RP1-PIO-driver.patch diff --git a/target/linux/bcm27xx/patches-6.6/950-1386-dts-bcm2712-rpi-Add-RP1-firmware-and-mailboxes.patch b/target/linux/bcm27xx/patches-6.6/950-1386-dts-bcm2712-rpi-Add-RP1-firmware-and-mailboxes.patch new file mode 100644 index 0000000000..2afb809e5e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1386-dts-bcm2712-rpi-Add-RP1-firmware-and-mailboxes.patch @@ -0,0 +1,118 @@ +From 0b76dec8dfba8c1a4793dff0c86bf73d088a812e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 1 Nov 2024 09:12:01 +0000 +Subject: [PATCH] dts: bcm2712-rpi: Add RP1 firmware and mailboxes + +Declare the communications channel to RP1. + +Signed-off-by: Phil Elwell +--- + .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 4 +-- + .../boot/dts/broadcom/bcm2712-rpi-cm5.dtsi | 4 +-- + arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 4 +++ + arch/arm64/boot/dts/broadcom/rp1.dtsi | 27 +++++++++++++++++++ + 4 files changed, 35 insertions(+), 4 deletions(-) + +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts +@@ -195,7 +195,7 @@ i2c_rp1boot: &_i2c3 { }; + // This is the RP1 peripheral space + ranges = <0xc0 0x40000000 + 0x02000000 0x00 0x00000000 +- 0x00 0x00400000>; ++ 0x00 0x00410000>; + + dma-ranges = + // inbound RP1 1x_xxxxxxxx -> PCIe 1x_xxxxxxxx +@@ -207,7 +207,7 @@ i2c_rp1boot: &_i2c3 { }; + // This allows the RP1 DMA controller to address RP1 hardware + <0xc0 0x40000000 + 0x02000000 0x0 0x00000000 +- 0x0 0x00400000>, ++ 0x0 0x00410000>, + + // inbound RP1 0x_xxxxxxxx -> PCIe 1x_xxxxxxxx + <0x00 0x00000000 +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi +@@ -176,7 +176,7 @@ i2c_rp1boot: &_i2c3 { }; + // This is the RP1 peripheral space + ranges = <0xc0 0x40000000 + 0x02000000 0x00 0x00000000 +- 0x00 0x00400000>; ++ 0x00 0x00410000>; + + dma-ranges = + // inbound RP1 1x_xxxxxxxx -> PCIe 1x_xxxxxxxx +@@ -188,7 +188,7 @@ i2c_rp1boot: &_i2c3 { }; + // This allows the RP1 DMA controller to address RP1 hardware + <0xc0 0x40000000 + 0x02000000 0x0 0x00000000 +- 0x0 0x00400000>, ++ 0x0 0x00410000>, + + // inbound RP1 0x_xxxxxxxx -> PCIe 1x_xxxxxxxx + <0x00 0x00000000 +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi +@@ -294,6 +294,10 @@ pciex4: &pcie2 { }; + status = "okay"; + }; + ++&rp1_mbox { ++ status = "okay"; ++}; ++ + /* Add some gpiomem nodes to make the devices accessible to userspace. + * /dev/gpiomem should expose the registers for the interface with DT alias + * gpio. +--- a/arch/arm64/boot/dts/broadcom/rp1.dtsi ++++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi +@@ -13,6 +13,14 @@ + + // ranges and dma-ranges must be provided by the includer + ++ rp1_mbox: mailbox@8000 { ++ compatible = "raspberrypi,rp1-mbox"; ++ status = "disabled"; ++ reg = <0xc0 0x40008000 0x0 0x4000>; // SYSCFG ++ interrupts = ; ++ #mbox-cells = <1>; ++ }; ++ + rp1_clocks: clocks@18000 { + compatible = "raspberrypi,rp1-clocks"; + #clock-cells = <1>; +@@ -1183,6 +1191,19 @@ + assigned-clocks = <&rp1_clocks RP1_CLK_DPI>; + assigned-clock-parents = <&rp1_clocks RP1_PLL_VIDEO>; + }; ++ ++ sram: sram@400000 { ++ compatible = "mmio-sram"; ++ reg = <0xc0 0x40400000 0x0 0x10000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0xc0 0x40400000 0x10000>; ++ ++ rp1_fw_shmem: shmem@ff00 { ++ compatible = "raspberrypi,rp1-shmem"; ++ reg = <0xff00 0x100>; // firmware mailbox buffer ++ }; ++ }; + }; + }; + +@@ -1281,6 +1302,12 @@ + }; + + / { ++ rp1_firmware: rp1_firmware { ++ compatible = "raspberrypi,rp1-firmware", "simple-mfd"; ++ mboxes = <&rp1_mbox 0>; ++ shmem = <&rp1_fw_shmem>; ++ }; ++ + rp1_vdd_3v3: rp1_vdd_3v3 { + compatible = "regulator-fixed"; + regulator-name = "vdd-3v3"; diff --git a/target/linux/bcm27xx/patches-6.6/950-1387-dts-bcm2712-rpi-Add-the-RP1-PIO-device.patch b/target/linux/bcm27xx/patches-6.6/950-1387-dts-bcm2712-rpi-Add-the-RP1-PIO-device.patch new file mode 100644 index 0000000000..29e54277c0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1387-dts-bcm2712-rpi-Add-the-RP1-PIO-device.patch @@ -0,0 +1,55 @@ +From 3e3c1b9922b22d362a4a9133361597ac80b974bb Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 1 Nov 2024 09:13:53 +0000 +Subject: [PATCH] dts: bcm2712-rpi: Add the RP1 PIO device + +Declare the device that proxies RP1's PIO hardware. + +Signed-off-by: Phil Elwell +--- + arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 5 +++++ + arch/arm64/boot/dts/broadcom/rp1.dtsi | 12 ++++++++++++ + 2 files changed, 17 insertions(+) + +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi +@@ -97,6 +97,10 @@ + }; + }; + ++pio: &rp1_pio { ++ status = "okay"; ++}; ++ + / { + chosen: chosen { + bootargs = "reboot=w coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe cgroup_disable=memory numa_policy=interleave"; +@@ -129,6 +133,7 @@ + i2c12 = &i2c_rp1boot; + mailbox = &mailbox; + mmc0 = &sdio1; ++ pio0 = &pio; + serial0 = &uart0; + serial1 = &uart1; + serial10 = &uart10; +--- a/arch/arm64/boot/dts/broadcom/rp1.dtsi ++++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi +@@ -1028,6 +1028,18 @@ + status = "disabled"; + }; + ++ rp1_pio: pio@178000 { ++ reg = <0xc0 0x40178000 0x0 0x20>; ++ compatible = "raspberrypi,rp1-pio"; ++ firmware = <&rp1_firmware>; ++ dmas = <&rp1_dma RP1_DMA_PIO_CH0_TX>, <&rp1_dma RP1_DMA_PIO_CH0_RX>, ++ <&rp1_dma RP1_DMA_PIO_CH1_TX>, <&rp1_dma RP1_DMA_PIO_CH1_RX>, ++ <&rp1_dma RP1_DMA_PIO_CH2_TX>, <&rp1_dma RP1_DMA_PIO_CH2_RX>, ++ <&rp1_dma RP1_DMA_PIO_CH3_TX>, <&rp1_dma RP1_DMA_PIO_CH3_RX>; ++ dma-names = "tx0", "rx0", "tx1", "rx1", "tx2", "rx2", "tx3", "rx3"; ++ status = "disabled"; ++ }; ++ + rp1_mmc0: mmc@180000 { + reg = <0xc0 0x40180000 0x0 0x100>; + compatible = "raspberrypi,rp1-dwcmshc"; diff --git a/target/linux/bcm27xx/patches-6.6/950-1355-misc-rp1-pio-Add-an-in-kernel.patch b/target/linux/bcm27xx/patches-6.6/950-1388-misc-rp1-pio-Add-an-in-kernel-API.patch similarity index 100% rename from target/linux/bcm27xx/patches-6.6/950-1355-misc-rp1-pio-Add-an-in-kernel.patch rename to target/linux/bcm27xx/patches-6.6/950-1388-misc-rp1-pio-Add-an-in-kernel-API.patch diff --git a/target/linux/bcm27xx/patches-6.6/950-1356-pwm-Add-pwm-pio-rp1-driver.patch b/target/linux/bcm27xx/patches-6.6/950-1389-pwm-Add-pwm-pio-rp1-driver.patch similarity index 98% rename from target/linux/bcm27xx/patches-6.6/950-1356-pwm-Add-pwm-pio-rp1-driver.patch rename to target/linux/bcm27xx/patches-6.6/950-1389-pwm-Add-pwm-pio-rp1-driver.patch index 3f787de9d9..9eed5f568d 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1356-pwm-Add-pwm-pio-rp1-driver.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1389-pwm-Add-pwm-pio-rp1-driver.patch @@ -15,7 +15,7 @@ Signed-off-by: Phil Elwell --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig -@@ -454,6 +454,17 @@ config PWM_PCA9685 +@@ -465,6 +465,17 @@ config PWM_PCA9685 To compile this driver as a module, choose M here: the module will be called pwm-pca9685. @@ -35,7 +35,7 @@ Signed-off-by: Phil Elwell depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile -@@ -41,6 +41,7 @@ obj-$(CONFIG_PWM_MXS) += pwm-mxs.o +@@ -42,6 +42,7 @@ obj-$(CONFIG_PWM_MXS) += pwm-mxs.o obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o diff --git a/target/linux/bcm27xx/patches-6.6/950-1391-overlays-Add-pwm-pio-overlay.patch b/target/linux/bcm27xx/patches-6.6/950-1391-overlays-Add-pwm-pio-overlay.patch new file mode 100644 index 0000000000..bd6d633319 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1391-overlays-Add-pwm-pio-overlay.patch @@ -0,0 +1,99 @@ +From ba7e2e3d03a432acbc338c6c03e46dcd97cfa1b3 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 7 Nov 2024 11:41:33 +0000 +Subject: [PATCH] overlays: Add pwm-pio overlay + +Add an overlay to enable a single-channel PIO-assisted PWM interface on any +header pin. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 8 ++++ + arch/arm/boot/dts/overlays/overlay_map.dts | 4 ++ + .../arm/boot/dts/overlays/pwm-pio-overlay.dts | 39 +++++++++++++++++++ + 4 files changed, 52 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/pwm-pio-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -219,6 +219,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + pwm-2chan.dtbo \ + pwm-gpio.dtbo \ + pwm-ir-tx.dtbo \ ++ pwm-pio.dtbo \ + pwm1.dtbo \ + qca7000.dtbo \ + qca7000-uart0.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -3926,6 +3926,14 @@ Params: gpio_pin Output G + func Pin function (default 2 = Alt5) + + ++Name: pwm-pio ++Info: Configures a GPIO pin as PIO-assisted PWM output. Unlike hardware PWM, ++ this can be used on any RP1 GPIO in bank 0 (0-27). Up to 4 are ++ supported, assuming nothing else is using PIO. Pi 5 only. ++Load: dtoverlay=pwm-pio,= ++Params: gpio Output GPIO (0-27, default 4) ++ ++ + Name: pwm1 + Info: Configures one or two PWM channel on PWM1 (BCM2711 only) + N.B.: +--- a/arch/arm/boot/dts/overlays/overlay_map.dts ++++ b/arch/arm/boot/dts/overlays/overlay_map.dts +@@ -240,6 +240,10 @@ + bcm2712; + }; + ++ pwm-pio { ++ bcm2712; ++ }; ++ + pwm1 { + bcm2711; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pwm-pio-overlay.dts +@@ -0,0 +1,39 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Device tree overlay for RP1 PIO PWM. ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&gpio>; ++ __overlay__ { ++ pwm_pio_pins: pwm_pio_pins@4 { ++ brcm,pins = <4>; /* gpio 4 */ ++ function = "pio"; ++ bias-disable; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "/"; ++ __overlay__ { ++ pwm_pio: pwm_pio@4 { ++ compatible = "raspberrypi,pwm-pio-rp1"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_pio_pins>; ++ gpios = <&gpio 4 0>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ gpio = <&pwm_pio>,"gpios:4", ++ <&pwm_pio_pins>,"brcm,pins:0", ++ /* modify reg values to allow multiple instantiation */ ++ <&pwm_pio>,"reg:0", ++ <&pwm_pio_pins>,"reg:0"; ++ }; ++}; diff --git a/target/linux/bcm27xx/patches-6.6/950-1354-fixup-musc-add-RP1-PIO-driver.patch b/target/linux/bcm27xx/patches-6.6/950-1392-fixup-misc-Add-RP1-PIO-driver.patch similarity index 100% rename from target/linux/bcm27xx/patches-6.6/950-1354-fixup-musc-add-RP1-PIO-driver.patch rename to target/linux/bcm27xx/patches-6.6/950-1392-fixup-misc-Add-RP1-PIO-driver.patch diff --git a/target/linux/bcm27xx/patches-6.6/950-1394-misc-rp1-pio-Add-compat_ioctl-method.patch b/target/linux/bcm27xx/patches-6.6/950-1394-misc-rp1-pio-Add-compat_ioctl-method.patch index bffa2418a1..6862a74e21 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1394-misc-rp1-pio-Add-compat_ioctl-method.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1394-misc-rp1-pio-Add-compat_ioctl-method.patch @@ -1,7 +1,7 @@ From b4472d09b1ffdafd8132803ffbec62596e559fd8 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 18 Nov 2024 09:10:52 +0000 -Subject: [PATCH 1394/1482] misc: rp1-pio: Add compat_ioctl method +Subject: [PATCH] misc: rp1-pio: Add compat_ioctl method Provide a compat_ioctl method, to support running a 64-bit kernel with a 32-bit userland. @@ -13,7 +13,7 @@ Signed-off-by: Phil Elwell --- a/drivers/misc/rp1-pio.c +++ b/drivers/misc/rp1-pio.c -@@ -1023,11 +1023,75 @@ static long rp1_pio_ioctl(struct file *f +@@ -996,11 +996,75 @@ static long rp1_pio_ioctl(struct file *f return ret; } diff --git a/target/linux/bcm27xx/patches-6.6/950-0998-i2c-designware-Add-support-for-bus-clear-feature.patch b/target/linux/bcm27xx/patches-6.6/950-1396-i2c-designware-Add-support-for-bus-clear-feature.patch similarity index 93% rename from target/linux/bcm27xx/patches-6.6/950-0998-i2c-designware-Add-support-for-bus-clear-feature.patch rename to target/linux/bcm27xx/patches-6.6/950-1396-i2c-designware-Add-support-for-bus-clear-feature.patch index 691484d46e..bc20db253a 100644 --- a/target/linux/bcm27xx/patches-6.6/950-0998-i2c-designware-Add-support-for-bus-clear-feature.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1396-i2c-designware-Add-support-for-bus-clear-feature.patch @@ -1,7 +1,7 @@ -From 24cb07b0c0724a22e474d12e7c2d5b834bf3b076 Mon Sep 17 00:00:00 2001 +From 0e4968617aad7d0f88e0a630499202eaae407a19 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 26 Mar 2024 15:57:46 +0000 -Subject: [PATCH 0998/1085] i2c: designware: Add support for bus clear feature +Subject: [PATCH] i2c: designware: Add support for bus clear feature Newer versions of the DesignWare I2C block support the detection of stuck signals, and a mechanism to recover from them. Add the required @@ -108,7 +108,7 @@ Signed-off-by: Phil Elwell DW_IC_TX_ABRT_10ADDR1_NOACK | \ --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c -@@ -212,6 +212,7 @@ static int i2c_dw_set_timings_master(str +@@ -215,6 +215,7 @@ static int i2c_dw_set_timings_master(str */ static int i2c_dw_init_master(struct dw_i2c_dev *dev) { @@ -116,7 +116,7 @@ Signed-off-by: Phil Elwell int ret; ret = i2c_dw_acquire_lock(dev); -@@ -235,6 +236,17 @@ static int i2c_dw_init_master(struct dw_ +@@ -238,6 +239,17 @@ static int i2c_dw_init_master(struct dw_ regmap_write(dev->map, DW_IC_HS_SCL_LCNT, dev->hs_lcnt); } @@ -134,7 +134,7 @@ Signed-off-by: Phil Elwell /* Write SDA hold time if supported */ if (dev->sda_hold_time) regmap_write(dev->map, DW_IC_SDA_HOLD, dev->sda_hold_time); -@@ -1071,6 +1083,7 @@ int i2c_dw_probe_master(struct dw_i2c_de +@@ -1074,6 +1086,7 @@ int i2c_dw_probe_master(struct dw_i2c_de struct i2c_adapter *adap = &dev->adapter; unsigned long irq_flags; unsigned int ic_con; @@ -142,7 +142,7 @@ Signed-off-by: Phil Elwell int ret; init_completion(&dev->cmd_complete); -@@ -1106,7 +1119,11 @@ int i2c_dw_probe_master(struct dw_i2c_de +@@ -1109,7 +1122,11 @@ int i2c_dw_probe_master(struct dw_i2c_de if (ret) return ret; diff --git a/target/linux/bcm27xx/patches-6.6/950-1397-drivers-media-pci-Update-Hailo-accelerator-device-dr.patch b/target/linux/bcm27xx/patches-6.6/950-1397-drivers-media-pci-Update-Hailo-accelerator-device-dr.patch new file mode 100644 index 0000000000..3ad28d6886 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1397-drivers-media-pci-Update-Hailo-accelerator-device-dr.patch @@ -0,0 +1,3592 @@ +From 32511f035b086bca254d8adab234cef3541492b4 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Thu, 17 Oct 2024 11:37:29 +0100 +Subject: [PATCH] drivers: media: pci: Update Hailo accelerator device driver + to v4.19 + +Sourced from https://github.com/hailo-ai/hailort-drivers/ + +Signed-off-by: Naushir Patuck +--- + drivers/media/pci/hailo/Makefile | 4 +- + drivers/media/pci/hailo/common/fw_operation.c | 50 ++- + drivers/media/pci/hailo/common/fw_operation.h | 8 +- + .../media/pci/hailo/common/fw_validation.c | 10 +- + .../media/pci/hailo/common/fw_validation.h | 7 +- + .../pci/hailo/common/hailo_ioctl_common.h | 28 +- + .../media/pci/hailo/common/hailo_resource.c | 23 +- + .../media/pci/hailo/common/hailo_resource.h | 2 +- + drivers/media/pci/hailo/common/pcie_common.c | 380 +++++++++--------- + drivers/media/pci/hailo/common/pcie_common.h | 38 +- + drivers/media/pci/hailo/common/soc_structs.h | 79 ++++ + drivers/media/pci/hailo/common/utils.h | 23 +- + drivers/media/pci/hailo/common/vdma_common.c | 93 +++-- + drivers/media/pci/hailo/common/vdma_common.h | 22 +- + drivers/media/pci/hailo/src/fops.c | 284 ++----------- + drivers/media/pci/hailo/src/fops.h | 5 +- + drivers/media/pci/hailo/src/nnc.c | 299 ++++++++++++++ + drivers/media/pci/hailo/src/nnc.h | 22 + + drivers/media/pci/hailo/src/pci_soc_ioctl.c | 155 ------- + drivers/media/pci/hailo/src/pcie.c | 166 +++----- + drivers/media/pci/hailo/src/pcie.h | 26 +- + drivers/media/pci/hailo/src/soc.c | 244 +++++++++++ + .../pci/hailo/src/{pci_soc_ioctl.h => soc.h} | 13 +- + drivers/media/pci/hailo/src/sysfs.c | 2 +- + drivers/media/pci/hailo/src/sysfs.h | 2 +- + drivers/media/pci/hailo/src/utils.c | 26 -- + drivers/media/pci/hailo/utils/compact.h | 2 +- + drivers/media/pci/hailo/utils/fw_common.h | 2 +- + .../pci/hailo/utils/integrated_nnc_utils.c | 10 +- + .../pci/hailo/utils/integrated_nnc_utils.h | 2 +- + drivers/media/pci/hailo/utils/logs.c | 2 +- + drivers/media/pci/hailo/utils/logs.h | 2 +- + drivers/media/pci/hailo/vdma/ioctl.c | 18 +- + drivers/media/pci/hailo/vdma/ioctl.h | 6 +- + drivers/media/pci/hailo/vdma/memory.c | 12 +- + drivers/media/pci/hailo/vdma/memory.h | 2 +- + drivers/media/pci/hailo/vdma/vdma.c | 39 +- + drivers/media/pci/hailo/vdma/vdma.h | 5 +- + 38 files changed, 1224 insertions(+), 889 deletions(-) + create mode 100644 drivers/media/pci/hailo/common/soc_structs.h + create mode 100644 drivers/media/pci/hailo/src/nnc.c + create mode 100644 drivers/media/pci/hailo/src/nnc.h + delete mode 100755 drivers/media/pci/hailo/src/pci_soc_ioctl.c + create mode 100644 drivers/media/pci/hailo/src/soc.c + rename drivers/media/pci/hailo/src/{pci_soc_ioctl.h => soc.h} (53%) + mode change 100755 => 100644 + delete mode 100644 drivers/media/pci/hailo/src/utils.c + +--- a/drivers/media/pci/hailo/Makefile ++++ b/drivers/media/pci/hailo/Makefile +@@ -8,9 +8,9 @@ obj-$(CONFIG_MEDIA_PCI_HAILO) := hailo_p + + hailo_pci-objs += src/pcie.o + hailo_pci-objs += src/fops.o +-hailo_pci-objs += src/utils.o + hailo_pci-objs += src/sysfs.o +-hailo_pci-objs += src/pci_soc_ioctl.o ++hailo_pci-objs += src/nnc.o ++hailo_pci-objs += src/soc.o + + hailo_pci-objs += $(COMMON_SRC_DIRECTORY)/fw_validation.o + hailo_pci-objs += $(COMMON_SRC_DIRECTORY)/fw_operation.o +--- a/drivers/media/pci/hailo/common/fw_operation.c ++++ b/drivers/media/pci/hailo/common/fw_operation.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: MIT + /** +- * Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved. +-**/ ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. ++ **/ + + #include "fw_operation.h" + +@@ -15,7 +15,10 @@ typedef struct { + u32 chip_offset; + } FW_DEBUG_BUFFER_HEADER_t; + +-#define DEBUG_BUFFER_DATA_SIZE (DEBUG_BUFFER_TOTAL_SIZE - sizeof(FW_DEBUG_BUFFER_HEADER_t)) ++#define DEBUG_BUFFER_DATA_SIZE (DEBUG_BUFFER_TOTAL_SIZE - sizeof(FW_DEBUG_BUFFER_HEADER_t)) ++#define PCIE_D2H_NOTIFICATION_SRAM_OFFSET (0x640 + 0x640) ++#define PCIE_APP_CPU_DEBUG_OFFSET (8*1024) ++#define PCIE_CORE_CPU_DEBUG_OFFSET (PCIE_APP_CPU_DEBUG_OFFSET + DEBUG_BUFFER_TOTAL_SIZE) + + int hailo_read_firmware_notification(struct hailo_resource *resource, struct hailo_d2h_notification *notification) + { +@@ -35,6 +38,21 @@ int hailo_read_firmware_notification(str + return 0; + } + ++int hailo_pcie_read_firmware_notification(struct hailo_resource *resource, ++ struct hailo_d2h_notification *notification) ++{ ++ struct hailo_resource notification_resource; ++ ++ if (PCIE_D2H_NOTIFICATION_SRAM_OFFSET > resource->size) { ++ return -EINVAL; ++ } ++ ++ notification_resource.address = resource->address + PCIE_D2H_NOTIFICATION_SRAM_OFFSET, ++ notification_resource.size = sizeof(struct hailo_d2h_notification); ++ ++ return hailo_read_firmware_notification(¬ification_resource, notification); ++} ++ + static inline size_t calculate_log_ready_to_read(FW_DEBUG_BUFFER_HEADER_t *header) + { + size_t ready_to_read = 0; +@@ -100,4 +118,30 @@ long hailo_read_firmware_log(struct hail + + params->read_bytes = ready_to_read; + return 0; ++} ++ ++long hailo_pcie_read_firmware_log(struct hailo_resource *resource, struct hailo_read_log_params *params) ++{ ++ long err = 0; ++ struct hailo_resource log_resource = {resource->address, DEBUG_BUFFER_TOTAL_SIZE}; ++ ++ if (HAILO_CPU_ID_CPU0 == params->cpu_id) { ++ log_resource.address += PCIE_APP_CPU_DEBUG_OFFSET; ++ } else if (HAILO_CPU_ID_CPU1 == params->cpu_id) { ++ log_resource.address += PCIE_CORE_CPU_DEBUG_OFFSET; ++ } else { ++ return -EINVAL; ++ } ++ ++ if (0 == params->buffer_size) { ++ params->read_bytes = 0; ++ return 0; ++ } ++ ++ err = hailo_read_firmware_log(&log_resource, params); ++ if (0 != err) { ++ return err; ++ } ++ ++ return 0; + } +\ No newline at end of file +--- a/drivers/media/pci/hailo/common/fw_operation.h ++++ b/drivers/media/pci/hailo/common/fw_operation.h +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: MIT + /** +- * Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved. +-**/ ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. ++ **/ + + #ifndef _HAILO_COMMON_FIRMWARE_OPERATION_H_ + #define _HAILO_COMMON_FIRMWARE_OPERATION_H_ +@@ -16,8 +16,12 @@ extern "C" { + + int hailo_read_firmware_notification(struct hailo_resource *resource, struct hailo_d2h_notification *notification); + ++int hailo_pcie_read_firmware_notification(struct hailo_resource *resource, struct hailo_d2h_notification *notification); ++ + long hailo_read_firmware_log(struct hailo_resource *fw_logger_resource, struct hailo_read_log_params *params); + ++long hailo_pcie_read_firmware_log(struct hailo_resource *resource, struct hailo_read_log_params *params); ++ + #ifdef __cplusplus + } + #endif +--- a/drivers/media/pci/hailo/common/fw_validation.c ++++ b/drivers/media/pci/hailo/common/fw_validation.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: MIT + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #include "fw_validation.h" +@@ -85,15 +85,15 @@ exit: + } + + int FW_VALIDATION__validate_cert_header(uintptr_t firmware_base_address, +- size_t firmware_size, u32 *outer_consumed_firmware_offset, secure_boot_certificate_t **out_firmware_cert) ++ size_t firmware_size, u32 *outer_consumed_firmware_offset, secure_boot_certificate_header_t **out_firmware_cert) + { + +- secure_boot_certificate_t *firmware_cert = NULL; ++ secure_boot_certificate_header_t *firmware_cert = NULL; + int err = -EINVAL; + u32 consumed_firmware_offset = *outer_consumed_firmware_offset; + +- firmware_cert = (secure_boot_certificate_t *) (firmware_base_address + consumed_firmware_offset); +- CONSUME_FIRMWARE(sizeof(secure_boot_certificate_t), -EINVAL); ++ firmware_cert = (secure_boot_certificate_header_t *) (firmware_base_address + consumed_firmware_offset); ++ CONSUME_FIRMWARE(sizeof(secure_boot_certificate_header_t), -EINVAL); + + if ((MAXIMUM_FIRMWARE_CERT_KEY_SIZE < firmware_cert->key_size) || + (MAXIMUM_FIRMWARE_CERT_CONTENT_SIZE < firmware_cert->content_size)) { +--- a/drivers/media/pci/hailo/common/fw_validation.h ++++ b/drivers/media/pci/hailo/common/fw_validation.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: MIT + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef PCIE_COMMON_FIRMWARE_HEADER_UTILS_H_ +@@ -44,8 +44,7 @@ typedef struct { + typedef struct { + u32 key_size; + u32 content_size; +- u8 certificates_data[0]; +-} secure_boot_certificate_t; ++} secure_boot_certificate_header_t; + + #ifdef _MSC_VER + #pragma warning(pop) +@@ -60,6 +59,6 @@ int FW_VALIDATION__validate_fw_header(ui + firmware_header_t **out_firmware_header, enum hailo_board_type board_type); + + int FW_VALIDATION__validate_cert_header(uintptr_t firmware_base_address, +- size_t firmware_size, u32 *outer_consumed_firmware_offset, secure_boot_certificate_t **out_firmware_cert); ++ size_t firmware_size, u32 *outer_consumed_firmware_offset, secure_boot_certificate_header_t **out_firmware_cert); + + #endif +\ No newline at end of file +--- a/drivers/media/pci/hailo/common/hailo_ioctl_common.h ++++ b/drivers/media/pci/hailo/common/hailo_ioctl_common.h +@@ -1,13 +1,13 @@ + // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) AND MIT + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _HAILO_IOCTL_COMMON_H_ + #define _HAILO_IOCTL_COMMON_H_ + + #define HAILO_DRV_VER_MAJOR 4 +-#define HAILO_DRV_VER_MINOR 18 ++#define HAILO_DRV_VER_MINOR 19 + #define HAILO_DRV_VER_REVISION 0 + + #define _STRINGIFY_EXPANDED( x ) #x +@@ -17,10 +17,11 @@ + + // This value is not easily changeable. + // For example: the channel interrupts ioctls assume we have up to 32 channels +-#define MAX_VDMA_CHANNELS_PER_ENGINE (32) +-#define MAX_VDMA_ENGINES (3) +-#define SIZE_OF_VDMA_DESCRIPTOR (16) +-#define VDMA_DEST_CHANNELS_START (16) ++#define MAX_VDMA_CHANNELS_PER_ENGINE (32) ++#define VDMA_CHANNELS_PER_ENGINE_PER_DIRECTION (16) ++#define MAX_VDMA_ENGINES (3) ++#define SIZE_OF_VDMA_DESCRIPTOR (16) ++#define VDMA_DEST_CHANNELS_START (16) + + #define HAILO_VDMA_MAX_ONGOING_TRANSFERS (128) + #define HAILO_VDMA_MAX_ONGOING_TRANSFERS_MASK (HAILO_VDMA_MAX_ONGOING_TRANSFERS - 1) +@@ -37,8 +38,8 @@ + #define FW_ACCESS_APP_CPU_CONTROL_MASK (1 << FW_ACCESS_CONTROL_INTERRUPT_SHIFT) + #define FW_ACCESS_DRIVER_SHUTDOWN_SHIFT (2) + #define FW_ACCESS_DRIVER_SHUTDOWN_MASK (1 << FW_ACCESS_DRIVER_SHUTDOWN_SHIFT) +-#define FW_ACCESS_SOC_CONNECT_SHIFT (3) +-#define FW_ACCESS_SOC_CONNECT_MASK (1 << FW_ACCESS_SOC_CONNECT_SHIFT) ++#define FW_ACCESS_SOC_CONTROL_SHIFT (3) ++#define FW_ACCESS_SOC_CONTROL_MASK (1 << FW_ACCESS_SOC_CONTROL_SHIFT) + + #define INVALID_VDMA_CHANNEL (0xff) + +@@ -245,6 +246,12 @@ struct hailo_desc_list_release_params { + uintptr_t desc_handle; // in + }; + ++struct hailo_write_action_list_params { ++ uint8_t *data; // in ++ size_t size; // in ++ uint64_t dma_address; // out ++}; ++ + /* structure used in ioctl HAILO_DESC_LIST_BIND_VDMA_BUFFER */ + struct hailo_desc_list_program_params { + size_t buffer_handle; // in +@@ -508,6 +515,7 @@ struct hailo_vdma_launch_transfer_params + + /* structure used in ioctl HAILO_SOC_CONNECT */ + struct hailo_soc_connect_params { ++ uint16_t port_number; // in + uint8_t input_channel_index; // out + uint8_t output_channel_index; // out + uintptr_t input_desc_handle; // in +@@ -522,6 +530,7 @@ struct hailo_soc_close_params { + + /* structure used in ioctl HAILO_PCI_EP_ACCEPT */ + struct hailo_pci_ep_accept_params { ++ uint16_t port_number; // in + uint8_t input_channel_index; // out + uint8_t output_channel_index; // out + uintptr_t input_desc_handle; // in +@@ -562,6 +571,7 @@ struct tCompatibleHailoIoctlData + struct hailo_soc_close_params SocCloseParams; + struct hailo_pci_ep_accept_params AcceptParams; + struct hailo_pci_ep_close_params PciEpCloseParams; ++ struct hailo_write_action_list_params WriteActionListParams; + } Buffer; + }; + #endif // _MSC_VER +@@ -632,6 +642,7 @@ enum hailo_nnc_ioctl_code { + HAILO_DISABLE_NOTIFICATION_CODE, + HAILO_READ_LOG_CODE, + HAILO_RESET_NN_CORE_CODE, ++ HAILO_WRITE_ACTION_LIST_CODE, + + // Must be last + HAILO_NNC_IOCTL_MAX_NR +@@ -642,6 +653,7 @@ enum hailo_nnc_ioctl_code { + #define HAILO_DISABLE_NOTIFICATION _IO_(HAILO_NNC_IOCTL_MAGIC, HAILO_DISABLE_NOTIFICATION_CODE) + #define HAILO_READ_LOG _IOWR_(HAILO_NNC_IOCTL_MAGIC, HAILO_READ_LOG_CODE, struct hailo_read_log_params) + #define HAILO_RESET_NN_CORE _IO_(HAILO_NNC_IOCTL_MAGIC, HAILO_RESET_NN_CORE_CODE) ++#define HAILO_WRITE_ACTION_LIST _IOW_(HAILO_NNC_IOCTL_MAGIC, HAILO_WRITE_ACTION_LIST_CODE, struct hailo_write_action_list_params) + + enum hailo_soc_ioctl_code { + HAILO_SOC_IOCTL_CONNECT_CODE, +--- a/drivers/media/pci/hailo/common/hailo_resource.c ++++ b/drivers/media/pci/hailo/common/hailo_resource.c +@@ -1,24 +1,31 @@ + // SPDX-License-Identifier: MIT + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #include "hailo_resource.h" + ++#include "utils.h" ++ + #include + #include + #include + #include + ++#define ALIGN_TO_32_BIT(addr) ((addr) & (~((uintptr_t)0x3))) + + u8 hailo_resource_read8(struct hailo_resource *resource, size_t offset) + { +- return ioread8((u8*)resource->address + offset); ++ u32 val = ioread32((u8*)ALIGN_TO_32_BIT(resource->address + offset)); ++ u64 offset_in_bits = BITS_IN_BYTE * ((resource->address + offset) - ALIGN_TO_32_BIT(resource->address + offset)); ++ return (u8)READ_BITS_AT_OFFSET(BYTE_SIZE * BITS_IN_BYTE, offset_in_bits, val); + } + + u16 hailo_resource_read16(struct hailo_resource *resource, size_t offset) + { +- return ioread16((u8*)resource->address + offset); ++ u32 val = ioread32((u8*)ALIGN_TO_32_BIT(resource->address + offset)); ++ u64 offset_in_bits = BITS_IN_BYTE * ((resource->address + offset) - ALIGN_TO_32_BIT(resource->address + offset)); ++ return (u16)READ_BITS_AT_OFFSET(WORD_SIZE * BITS_IN_BYTE, offset_in_bits, val); + } + + u32 hailo_resource_read32(struct hailo_resource *resource, size_t offset) +@@ -28,12 +35,18 @@ u32 hailo_resource_read32(struct hailo_r + + void hailo_resource_write8(struct hailo_resource *resource, size_t offset, u8 value) + { +- iowrite8(value, (u8*)resource->address + offset); ++ u32 initial_val = ioread32((u8*)ALIGN_TO_32_BIT(resource->address + offset)); ++ u64 offset_in_bits = BITS_IN_BYTE * ((resource->address + offset) - ALIGN_TO_32_BIT(resource->address + offset)); ++ iowrite32(WRITE_BITS_AT_OFFSET(BYTE_SIZE * BITS_IN_BYTE, offset_in_bits, initial_val, value), ++ (u8*)ALIGN_TO_32_BIT(resource->address + offset)); + } + + void hailo_resource_write16(struct hailo_resource *resource, size_t offset, u16 value) + { +- iowrite16(value, (u8*)resource->address + offset); ++ u32 initial_val = ioread32((u8*)ALIGN_TO_32_BIT(resource->address + offset)); ++ u64 offset_in_bits = BITS_IN_BYTE * ((resource->address + offset) - ALIGN_TO_32_BIT(resource->address + offset)); ++ iowrite32(WRITE_BITS_AT_OFFSET(WORD_SIZE * BITS_IN_BYTE, offset_in_bits, initial_val, value), ++ (u8*)ALIGN_TO_32_BIT(resource->address + offset)); + } + + void hailo_resource_write32(struct hailo_resource *resource, size_t offset, u32 value) +--- a/drivers/media/pci/hailo/common/hailo_resource.h ++++ b/drivers/media/pci/hailo/common/hailo_resource.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: MIT + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _HAILO_COMMON_HAILO_RESOURCE_H_ +--- a/drivers/media/pci/hailo/common/pcie_common.c ++++ b/drivers/media/pci/hailo/common/pcie_common.c +@@ -1,10 +1,11 @@ + // SPDX-License-Identifier: MIT + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #include "pcie_common.h" + #include "fw_operation.h" ++#include "soc_structs.h" + + #include + #include +@@ -35,10 +36,6 @@ + #define FIRMWARE_LOAD_WAIT_MAX_RETRIES (100) + #define FIRMWARE_LOAD_SLEEP_MS (50) + +-#define PCIE_APP_CPU_DEBUG_OFFSET (8*1024) +-#define PCIE_CORE_CPU_DEBUG_OFFSET (PCIE_APP_CPU_DEBUG_OFFSET + DEBUG_BUFFER_TOTAL_SIZE) +- +-#define PCIE_D2H_NOTIFICATION_SRAM_OFFSET (0x640 + 0x640) + #define PCIE_REQUEST_SIZE_OFFSET (0x640) + + #define PCIE_CONFIG_VENDOR_OFFSET (0x0098) +@@ -59,7 +56,6 @@ struct hailo_fw_addresses { + u32 app_fw_code_ram_base; + u32 boot_key_cert; + u32 boot_cont_cert; +- u32 boot_fw_trigger; + u32 core_code_ram_base; + u32 core_fw_header; + u32 atr0_trsl_addr1; +@@ -69,13 +65,11 @@ struct hailo_fw_addresses { + + struct loading_stage { + const struct hailo_file_batch *batch; ++ u32 trigger_address; + }; + + struct hailo_board_compatibility { + struct hailo_fw_addresses fw_addresses; +- const char *fw_filename; +- const struct hailo_config_constants board_cfg; +- const struct hailo_config_constants fw_cfg; + const struct loading_stage stages[MAX_LOADING_STAGES]; + }; + +@@ -85,28 +79,32 @@ static const struct hailo_file_batch hai + .address = 0xA0000, + .max_size = 0x8004, + .is_mandatory = true, +- .has_header = false ++ .has_header = false, ++ .has_core = false + }, + { + .filename = "hailo/hailo10h/u-boot.dtb.signed", + .address = 0xA8004, + .max_size = 0x20000, + .is_mandatory = true, +- .has_header = false ++ .has_header = false, ++ .has_core = false + }, + { + .filename = "hailo/hailo10h/scu_fw.bin", + .address = 0x20000, + .max_size = 0x40000, + .is_mandatory = true, +- .has_header = true ++ .has_header = true, ++ .has_core = false + }, + { + .filename = NULL, + .address = 0x00, + .max_size = 0x00, + .is_mandatory = false, +- .has_header = false ++ .has_header = false, ++ .has_core = false + } + }; + +@@ -116,36 +114,140 @@ static const struct hailo_file_batch hai + .address = 0x85000000, + .max_size = 0x1000000, + .is_mandatory = true, +- .has_header = false ++ .has_header = false, ++ .has_core = false + }, + { + .filename = "hailo/hailo10h/u-boot-tfa.itb", + .address = 0x86000000, + .max_size = 0x1000000, + .is_mandatory = true, +- .has_header = false ++ .has_header = false, ++ .has_core = false + }, + { + .filename = "hailo/hailo10h/fitImage", + .address = 0x87000000, + .max_size = 0x1000000, + .is_mandatory = true, +- .has_header = false ++ .has_header = false, ++ .has_core = false + }, + { + .filename = "hailo/hailo10h/core-image-minimal-hailo10-m2.ext4.gz", + .address = 0x88000000, + .max_size = 0x20000000, // Max size 512MB + .is_mandatory = true, +- .has_header = false ++ .has_header = false, ++ .has_core = false + }, + }; + ++// If loading linux from EMMC - only need few files from second batch (u-boot-spl.bin and u-boot-tfa.itb) ++static const struct hailo_file_batch hailo10h_files_stg2_linux_in_emmc[] = { ++ { ++ .filename = "hailo/hailo10h/u-boot-spl.bin", ++ .address = 0x85000000, ++ .max_size = 0x1000000, ++ .is_mandatory = true, ++ .has_header = false, ++ .has_core = false ++ }, ++ { ++ .filename = "hailo/hailo10h/u-boot-tfa.itb", ++ .address = 0x86000000, ++ .max_size = 0x1000000, ++ .is_mandatory = true, ++ .has_header = false, ++ .has_core = false ++ }, ++ { ++ .filename = NULL, ++ .address = 0x00, ++ .max_size = 0x00, ++ .is_mandatory = false, ++ .has_header = false, ++ .has_core = false ++ }, ++}; ++ ++static const struct hailo_file_batch hailo8_files_stg1[] = { ++ { ++ .filename = "hailo/hailo8_fw.4.19.0.bin", ++ .address = 0x20000, ++ .max_size = 0x50000, ++ .is_mandatory = true, ++ .has_header = true, ++ .has_core = true ++ }, ++ { ++ .filename = "hailo/hailo8_board_cfg.bin", ++ .address = 0x60001000, ++ .max_size = PCIE_HAILO8_BOARD_CFG_MAX_SIZE, ++ .is_mandatory = false, ++ .has_header = false, ++ .has_core = false ++ }, ++ { ++ .filename = "hailo/hailo8_fw_cfg.bin", ++ .address = 0x60001500, ++ .max_size = PCIE_HAILO8_FW_CFG_MAX_SIZE, ++ .is_mandatory = false, ++ .has_header = false, ++ .has_core = false ++ }, ++ { ++ .filename = NULL, ++ .address = 0x00, ++ .max_size = 0x00, ++ .is_mandatory = false, ++ .has_header = false, ++ .has_core = false ++ } ++}; ++ ++static const struct hailo_file_batch hailo10h_legacy_files_stg1[] = { ++ { ++ .filename = "hailo/hailo15_fw.bin", ++ .address = 0x20000, ++ .max_size = 0x100000, ++ .is_mandatory = true, ++ .has_header = true, ++ .has_core = true ++ }, ++ { ++ .filename = NULL, ++ .address = 0x00, ++ .max_size = 0x00, ++ .is_mandatory = false, ++ .has_header = false, ++ .has_core = false ++ } ++}; ++ ++static const struct hailo_file_batch pluto_files_stg1[] = { ++ { ++ .filename = "hailo/pluto_fw.bin", ++ .address = 0x20000, ++ .max_size = 0x100000, ++ .is_mandatory = true, ++ .has_header = true, ++ .has_core = true ++ }, ++ { ++ .filename = NULL, ++ .address = 0x00, ++ .max_size = 0x00, ++ .is_mandatory = false, ++ .has_header = false, ++ .has_core = false ++ } ++}; ++ + static const struct hailo_board_compatibility compat[HAILO_BOARD_TYPE_COUNT] = { + [HAILO_BOARD_TYPE_HAILO8] = { + .fw_addresses = { + .boot_fw_header = 0xE0030, +- .boot_fw_trigger = 0xE0980, + .boot_key_cert = 0xE0048, + .boot_cont_cert = 0xE0390, + .app_fw_code_ram_base = 0x60000, +@@ -155,22 +257,16 @@ static const struct hailo_board_compatib + .raise_ready_offset = 0x1684, + .boot_status = 0xe0000, + }, +- .fw_filename = "hailo/hailo8_fw.bin", +- .board_cfg = { +- .filename = "hailo/hailo8_board_cfg.bin", +- .address = 0x60001000, +- .max_size = PCIE_HAILO8_BOARD_CFG_MAX_SIZE, +- }, +- .fw_cfg = { +- .filename = "hailo/hailo8_fw_cfg.bin", +- .address = 0x60001500, +- .max_size = PCIE_HAILO8_FW_CFG_MAX_SIZE, ++ .stages = { ++ { ++ .batch = hailo8_files_stg1, ++ .trigger_address = 0xE0980 ++ }, + }, + }, + [HAILO_BOARD_TYPE_HAILO10H_LEGACY] = { + .fw_addresses = { + .boot_fw_header = 0x88000, +- .boot_fw_trigger = 0x88c98, + .boot_key_cert = 0x88018, + .boot_cont_cert = 0x886a8, + .app_fw_code_ram_base = 0x20000, +@@ -180,22 +276,16 @@ static const struct hailo_board_compatib + .raise_ready_offset = 0x1754, + .boot_status = 0x80000, + }, +- .fw_filename = "hailo/hailo15_fw.bin", +- .board_cfg = { +- .filename = NULL, +- .address = 0, +- .max_size = 0, +- }, +- .fw_cfg = { +- .filename = NULL, +- .address = 0, +- .max_size = 0, ++ .stages = { ++ { ++ .batch = hailo10h_legacy_files_stg1, ++ .trigger_address = 0x88c98 ++ }, + }, + }, + [HAILO_BOARD_TYPE_HAILO10H] = { + .fw_addresses = { + .boot_fw_header = 0x88000, +- .boot_fw_trigger = 0x88c98, + .boot_key_cert = 0x88018, + .boot_cont_cert = 0x886a8, + .app_fw_code_ram_base = 0x20000, +@@ -205,23 +295,18 @@ static const struct hailo_board_compatib + .raise_ready_offset = 0x1754, + .boot_status = 0x80000, + }, +- .fw_filename = NULL, +- .board_cfg = { +- .filename = NULL, +- .address = 0, +- .max_size = 0, +- }, +- .fw_cfg = { +- .filename = NULL, +- .address = 0, +- .max_size = 0, +- }, + .stages = { + { + .batch = hailo10h_files_stg1, ++ .trigger_address = 0x88c98 + }, + { + .batch = hailo10h_files_stg2, ++ .trigger_address = 0x84000000 ++ }, ++ { ++ .batch = hailo10h_files_stg2_linux_in_emmc, ++ .trigger_address = 0x84000000 + }, + }, + }, +@@ -230,7 +315,6 @@ static const struct hailo_board_compatib + [HAILO_BOARD_TYPE_PLUTO] = { + .fw_addresses = { + .boot_fw_header = 0x88000, +- .boot_fw_trigger = 0x88c98, + .boot_key_cert = 0x88018, + .boot_cont_cert = 0x886a8, + .app_fw_code_ram_base = 0x20000, +@@ -241,16 +325,11 @@ static const struct hailo_board_compatib + .raise_ready_offset = 0x174c, + .boot_status = 0x80000, + }, +- .fw_filename = "hailo/pluto_fw.bin", +- .board_cfg = { +- .filename = NULL, +- .address = 0, +- .max_size = 0, +- }, +- .fw_cfg = { +- .filename = NULL, +- .address = 0, +- .max_size = 0, ++ .stages = { ++ { ++ .batch = pluto_files_stg1, ++ .trigger_address = 0x88c98 ++ }, + }, + } + }; +@@ -340,21 +419,6 @@ void hailo_pcie_write_firmware_driver_sh + hailo_resource_write32(&resources->fw_access, fw_addresses->raise_ready_offset, fw_access_value); + } + +-int hailo_pcie_read_firmware_notification(struct hailo_pcie_resources *resources, +- struct hailo_d2h_notification *notification) +-{ +- struct hailo_resource notification_resource; +- +- if (PCIE_D2H_NOTIFICATION_SRAM_OFFSET > resources->fw_access.size) { +- return -EINVAL; +- } +- +- notification_resource.address = resources->fw_access.address + PCIE_D2H_NOTIFICATION_SRAM_OFFSET, +- notification_resource.size = sizeof(struct hailo_d2h_notification); +- +- return hailo_read_firmware_notification(¬ification_resource, notification); +-} +- + int hailo_pcie_configure_atr_table(struct hailo_resource *bridge_config, u64 trsl_addr, u32 atr_index) + { + size_t offset = 0; +@@ -388,7 +452,7 @@ static void write_memory_chunk(struct ha + u32 ATR_INDEX = 0; + BUG_ON(dest_offset + len > (u32)resources->fw_access.size); + +- (void)hailo_pcie_configure_atr_table(&resources->config, (u64)dest, ATR_INDEX); ++ (void)hailo_pcie_configure_atr_table(&resources->config, dest, ATR_INDEX); + (void)hailo_resource_write_buffer(&resources->fw_access, dest_offset, len, src); + } + +@@ -398,13 +462,13 @@ static void read_memory_chunk( + u32 ATR_INDEX = 0; + BUG_ON(src_offset + len > (u32)resources->fw_access.size); + +- (void)hailo_pcie_configure_atr_table(&resources->config, (u64)src, ATR_INDEX); ++ (void)hailo_pcie_configure_atr_table(&resources->config, src, ATR_INDEX); + (void)hailo_resource_read_buffer(&resources->fw_access, src_offset, len, dest); + } + + // Note: this function modify the device ATR table (that is also used by the firmware for control and vdma). + // Use with caution, and restore the original atr if needed. +-void write_memory(struct hailo_pcie_resources *resources, hailo_ptr_t dest, const void *src, u32 len) ++static void write_memory(struct hailo_pcie_resources *resources, hailo_ptr_t dest, const void *src, u32 len) + { + struct hailo_atr_config previous_atr = {0}; + hailo_ptr_t base_address = (dest & ~ATR_TABLE_SIZE_MASK); +@@ -417,8 +481,8 @@ void write_memory(struct hailo_pcie_reso + + if (base_address != dest) { + // Data is not aligned, write the first chunk +- chunk_len = min(base_address + ATR_TABLE_SIZE - dest, len); +- write_memory_chunk(resources, base_address, dest - base_address, src, chunk_len); ++ chunk_len = min((u32)(base_address + ATR_TABLE_SIZE - dest), len); ++ write_memory_chunk(resources, base_address, (u32)(dest - base_address), src, chunk_len); + offset += chunk_len; + } + +@@ -447,8 +511,8 @@ static void read_memory(struct hailo_pci + + if (base_address != src) { + // Data is not aligned, write the first chunk +- chunk_len = min(base_address + ATR_TABLE_SIZE - src, len); +- read_memory_chunk(resources, base_address, src - base_address, dest, chunk_len); ++ chunk_len = min((u32)(base_address + ATR_TABLE_SIZE - src), len); ++ read_memory_chunk(resources, base_address, (u32)(src - base_address), dest, chunk_len); + offset += chunk_len; + } + +@@ -463,12 +527,12 @@ static void read_memory(struct hailo_pci + } + + static void hailo_write_app_firmware(struct hailo_pcie_resources *resources, firmware_header_t *fw_header, +- secure_boot_certificate_t *fw_cert) ++ secure_boot_certificate_header_t *fw_cert) + { + const struct hailo_fw_addresses *fw_addresses = &(compat[resources->board_type].fw_addresses); +- void *fw_code = (void*)((u8*)fw_header + sizeof(firmware_header_t)); +- void *key_data = &fw_cert->certificates_data[0]; +- void *content_data = &fw_cert->certificates_data[fw_cert->key_size]; ++ u8 *fw_code = ((u8*)fw_header + sizeof(firmware_header_t)); ++ u8 *key_data = ((u8*)fw_cert + sizeof(secure_boot_certificate_header_t)); ++ u8 *content_data = key_data + fw_cert->key_size; + + write_memory(resources, fw_addresses->boot_fw_header, fw_header, sizeof(firmware_header_t)); + +@@ -487,13 +551,11 @@ static void hailo_write_core_firmware(st + write_memory(resources, fw_addresses->core_fw_header, fw_header, sizeof(firmware_header_t)); + } + +-void hailo_trigger_firmware_boot(struct hailo_pcie_resources *resources) ++void hailo_trigger_firmware_boot(struct hailo_pcie_resources *resources, u32 address) + { +- const struct hailo_fw_addresses *fw_addresses = &(compat[resources->board_type].fw_addresses); + u32 pcie_finished = 1; + +- write_memory(resources, fw_addresses->boot_fw_trigger, +- (void*)&pcie_finished, sizeof(pcie_finished)); ++ write_memory(resources, address, (void*)&pcie_finished, sizeof(pcie_finished)); + } + + u32 hailo_get_boot_status(struct hailo_pcie_resources *resources) +@@ -501,8 +563,7 @@ u32 hailo_get_boot_status(struct hailo_p + u32 boot_status = 0; + const struct hailo_fw_addresses *fw_addresses = &(compat[resources->board_type].fw_addresses); + +- read_memory(resources, fw_addresses->boot_status, +- &boot_status, sizeof(boot_status)); ++ read_memory(resources, fw_addresses->boot_status, &boot_status, sizeof(boot_status)); + + return boot_status; + } +@@ -517,11 +578,11 @@ u32 hailo_get_boot_status(struct hailo_p + */ + static int FW_VALIDATION__validate_fw_headers(uintptr_t firmware_base_address, size_t firmware_size, + firmware_header_t **out_app_firmware_header, firmware_header_t **out_core_firmware_header, +- secure_boot_certificate_t **out_firmware_cert, enum hailo_board_type board_type) ++ secure_boot_certificate_header_t **out_firmware_cert, enum hailo_board_type board_type) + { + firmware_header_t *app_firmware_header = NULL; + firmware_header_t *core_firmware_header = NULL; +- secure_boot_certificate_t *firmware_cert = NULL; ++ secure_boot_certificate_header_t *firmware_cert = NULL; + int err = -EINVAL; + u32 consumed_firmware_offset = 0; + +@@ -571,25 +632,25 @@ exit: + return err; + } + +-static int write_single_file(struct hailo_pcie_resources *resources, const struct hailo_file_batch *files_batch, struct device *dev) ++static int write_single_file(struct hailo_pcie_resources *resources, const struct hailo_file_batch *file_info, struct device *dev) + { + const struct firmware *firmware = NULL; + firmware_header_t *app_firmware_header = NULL; +- secure_boot_certificate_t *firmware_cert = NULL; ++ secure_boot_certificate_header_t *firmware_cert = NULL; + firmware_header_t *core_firmware_header = NULL; + int err = 0; + +- err = request_firmware_direct(&firmware, files_batch->filename, dev); ++ err = request_firmware_direct(&firmware, file_info->filename, dev); + if (err < 0) { + return err; + } + +- if (firmware->size > files_batch->max_size) { ++ if (firmware->size > file_info->max_size) { + release_firmware(firmware); + return -EFBIG; + } + +- if (files_batch->has_header) { ++ if (file_info->has_header) { + err = FW_VALIDATION__validate_fw_headers((uintptr_t)firmware->data, firmware->size, + &app_firmware_header, &core_firmware_header, &firmware_cert, resources->board_type); + if (err < 0) { +@@ -598,8 +659,11 @@ static int write_single_file(struct hail + } + + hailo_write_app_firmware(resources, app_firmware_header, firmware_cert); ++ if (file_info->has_core) { ++ hailo_write_core_firmware(resources, core_firmware_header); ++ } + } else { +- write_memory(resources, files_batch->address, (void*)firmware->data, firmware->size); ++ write_memory(resources, file_info->address, (void*)firmware->data, firmware->size); + } + + release_firmware(firmware); +@@ -632,31 +696,13 @@ int hailo_pcie_write_firmware_batch(stru + dev_notice(dev, "File %s written successfully\n", files_batch[file_index].filename); + } + +- return 0; +-} +- +-int hailo_pcie_write_firmware(struct hailo_pcie_resources *resources, const void *fw_data, size_t fw_size) +-{ +- firmware_header_t *app_firmware_header = NULL; +- secure_boot_certificate_t *firmware_cert = NULL; +- firmware_header_t *core_firmware_header = NULL; +- +- int err = FW_VALIDATION__validate_fw_headers((uintptr_t)fw_data, fw_size, +- &app_firmware_header, &core_firmware_header, &firmware_cert, resources->board_type); +- if (err < 0) { +- return err; +- } +- +- hailo_write_app_firmware(resources, app_firmware_header, firmware_cert); +- hailo_write_core_firmware(resources, core_firmware_header); +- +- hailo_trigger_firmware_boot(resources); ++ hailo_trigger_firmware_boot(resources, compat[resources->board_type].stages[stage].trigger_address); + + return 0; + } + + // TODO: HRT-14147 - remove this function +-bool hailo_pcie_is_device_ready_for_boot(struct hailo_pcie_resources *resources) ++static bool hailo_pcie_is_device_ready_for_boot(struct hailo_pcie_resources *resources) + { + return hailo_get_boot_status(resources) == BOOT_STATUS_UNINITIALIZED; + } +@@ -691,32 +737,6 @@ bool hailo_pcie_wait_for_firmware(struct + return false; + } + +-int hailo_pcie_write_config_common(struct hailo_pcie_resources *resources, const void* config_data, +- const size_t config_size, const struct hailo_config_constants *config_consts) +-{ +- if (config_size > config_consts->max_size) { +- return -EINVAL; +- } +- +- write_memory(resources, config_consts->address, config_data, (u32)config_size); +- return 0; +-} +- +-const struct hailo_config_constants* hailo_pcie_get_board_config_constants(const enum hailo_board_type board_type) { +- BUG_ON(board_type >= HAILO_BOARD_TYPE_COUNT || board_type < 0); +- return &compat[board_type].board_cfg; +-} +- +-const struct hailo_config_constants* hailo_pcie_get_user_config_constants(const enum hailo_board_type board_type) { +- BUG_ON(board_type >= HAILO_BOARD_TYPE_COUNT || board_type < 0); +- return &compat[board_type].fw_cfg; +-} +- +-const char* hailo_pcie_get_fw_filename(const enum hailo_board_type board_type) { +- BUG_ON(board_type >= HAILO_BOARD_TYPE_COUNT || board_type < 0); +- return compat[board_type].fw_filename; +-} +- + void hailo_pcie_update_channel_interrupts_mask(struct hailo_pcie_resources* resources, u32 channels_bitmap) + { + size_t i = 0; +@@ -745,7 +765,7 @@ void hailo_pcie_enable_interrupts(struct + hailo_resource_write32(&resources->config, BCS_SOURCE_INTERRUPT_PER_CHANNEL, 0xFFFFFFFF); + + mask |= (BCS_ISTATUS_HOST_FW_IRQ_CONTROL_MASK | BCS_ISTATUS_HOST_FW_IRQ_NOTIFICATION | +- BCS_ISTATUS_HOST_DRIVER_DOWN | BCS_ISTATUS_SOC_CONNECT_ACCEPTED); ++ BCS_ISTATUS_HOST_DRIVER_DOWN | BCS_ISTATUS_SOC_CONNECT_ACCEPTED | BCS_ISTATUS_SOC_CLOSED_IRQ); + hailo_resource_write32(&resources->config, BSC_IMASK_HOST, mask); + } + +@@ -754,45 +774,15 @@ void hailo_pcie_disable_interrupts(struc + hailo_resource_write32(&resources->config, BSC_IMASK_HOST, 0); + } + +-long hailo_pcie_read_firmware_log(struct hailo_pcie_resources *resources, struct hailo_read_log_params *params) +-{ +- long err = 0; +- struct hailo_resource log_resource = {resources->fw_access.address, DEBUG_BUFFER_TOTAL_SIZE}; +- +- if (HAILO_CPU_ID_CPU0 == params->cpu_id) { +- log_resource.address += PCIE_APP_CPU_DEBUG_OFFSET; +- } else if (HAILO_CPU_ID_CPU1 == params->cpu_id) { +- log_resource.address += PCIE_CORE_CPU_DEBUG_OFFSET; +- } else { +- return -EINVAL; +- } +- +- if (0 == params->buffer_size) { +- params->read_bytes = 0; +- return 0; +- } +- +- err = hailo_read_firmware_log(&log_resource, params); +- if (0 != err) { +- return err; +- } +- +- return 0; +-} +- + static int direct_memory_transfer(struct hailo_pcie_resources *resources, + struct hailo_memory_transfer_params *params) + { +- if (params->address > U32_MAX) { +- return -EFAULT; +- } +- + switch (params->transfer_direction) { + case TRANSFER_READ: +- read_memory(resources, (u32)params->address, params->buffer, (u32)params->count); ++ read_memory(resources, params->address, params->buffer, (u32)params->count); + break; + case TRANSFER_WRITE: +- write_memory(resources, (u32)params->address, params->buffer, (u32)params->count); ++ write_memory(resources, params->address, params->buffer, (u32)params->count); + break; + default: + return -EINVAL; +@@ -845,16 +835,18 @@ int hailo_set_device_type(struct hailo_p + return 0; + } + +-// On PCIe, just return the address +-static u64 encode_dma_address(dma_addr_t dma_address, u8 channel_id) ++// On PCIe, just return the start address ++u64 hailo_pcie_encode_desc_dma_address_range(dma_addr_t dma_address_start, dma_addr_t dma_address_end, u32 step, u8 channel_id) + { + (void)channel_id; +- return (u64)dma_address; ++ (void)dma_address_end; ++ (void)step; ++ return (u64)dma_address_start; + } + + struct hailo_vdma_hw hailo_pcie_vdma_hw = { + .hw_ops = { +- .encode_desc_dma_address = encode_dma_address ++ .encode_desc_dma_address_range = hailo_pcie_encode_desc_dma_address_range, + }, + .ddr_data_id = HAILO_PCIE_HOST_DMA_DATA_ID, + .device_interrupts_bitmask = HAILO_PCIE_DMA_DEVICE_INTERRUPTS_BITMASK, +@@ -862,11 +854,19 @@ struct hailo_vdma_hw hailo_pcie_vdma_hw + .src_channels_bitmask = HAILO_PCIE_DMA_SRC_CHANNELS_BITMASK, + }; + +-void hailo_soc_write_soc_connect(struct hailo_pcie_resources *resources) ++void hailo_pcie_soc_write_request(struct hailo_pcie_resources *resources, ++ const struct hailo_pcie_soc_request *request) + { + const struct hailo_fw_addresses *fw_addresses = &(compat[resources->board_type].fw_addresses); +- const u32 soc_connect_value = FW_ACCESS_SOC_CONNECT_MASK; ++ BUILD_BUG_ON_MSG((sizeof(*request) % sizeof(u32)) != 0, "Request must be a multiple of 4 bytes"); + +- // Write shutdown flag to FW +- hailo_resource_write32(&resources->fw_access, fw_addresses->raise_ready_offset, soc_connect_value); +-} +\ No newline at end of file ++ hailo_resource_write_buffer(&resources->fw_access, 0, sizeof(*request), (void*)request); ++ hailo_resource_write32(&resources->fw_access, fw_addresses->raise_ready_offset, FW_ACCESS_SOC_CONTROL_MASK); ++} ++ ++void hailo_pcie_soc_read_response(struct hailo_pcie_resources *resources, ++ struct hailo_pcie_soc_response *response) ++{ ++ BUILD_BUG_ON_MSG((sizeof(*response) % sizeof(u32)) != 0, "Request must be a multiple of 4 bytes"); ++ hailo_resource_read_buffer(&resources->fw_access, 0, sizeof(*response), response); ++} +--- a/drivers/media/pci/hailo/common/pcie_common.h ++++ b/drivers/media/pci/hailo/common/pcie_common.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: MIT + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _HAILO_COMMON_PCIE_COMMON_H_ +@@ -12,6 +12,7 @@ + #include "fw_operation.h" + #include "utils.h" + #include "vdma_common.h" ++#include "soc_structs.h" + + #include + #include +@@ -21,6 +22,7 @@ + #define BCS_ISTATUS_HOST_FW_IRQ_NOTIFICATION (0x02000000) + #define BCS_ISTATUS_HOST_DRIVER_DOWN (0x08000000) + #define BCS_ISTATUS_SOC_CONNECT_ACCEPTED (0x10000000) ++#define BCS_ISTATUS_SOC_CLOSED_IRQ (0x20000000) + #define BCS_ISTATUS_HOST_VDMA_SRC_IRQ_MASK (0x000000FF) + #define BCS_ISTATUS_HOST_VDMA_DEST_IRQ_MASK (0x0000FF00) + +@@ -42,7 +44,7 @@ + #define PCI_DEVICE_ID_HAILO_HAILO15 0x45C4 + #define PCI_DEVICE_ID_HAILO_PLUTO 0x43a2 + +-typedef u32 hailo_ptr_t; ++typedef u64 hailo_ptr_t; + + struct hailo_pcie_resources { + struct hailo_resource config; // BAR0 +@@ -63,7 +65,8 @@ struct hailo_atr_config { + enum loading_stages { + FIRST_STAGE = 0, + SECOND_STAGE = 1, +- MAX_LOADING_STAGES = 2 ++ SECOND_STAGE_LINUX_IN_EMMC = 2, ++ MAX_LOADING_STAGES = 3 + }; + + enum hailo_pcie_interrupt_masks { +@@ -71,6 +74,7 @@ enum hailo_pcie_interrupt_masks { + FW_NOTIFICATION = BCS_ISTATUS_HOST_FW_IRQ_NOTIFICATION, + DRIVER_DOWN = BCS_ISTATUS_HOST_DRIVER_DOWN, + SOC_CONNECT_ACCEPTED = BCS_ISTATUS_SOC_CONNECT_ACCEPTED, ++ SOC_CLOSED_IRQ = BCS_ISTATUS_SOC_CLOSED_IRQ, + VDMA_SRC_IRQ_MASK = BCS_ISTATUS_HOST_VDMA_SRC_IRQ_MASK, + VDMA_DEST_IRQ_MASK = BCS_ISTATUS_HOST_VDMA_DEST_IRQ_MASK + }; +@@ -80,18 +84,13 @@ struct hailo_pcie_interrupt_source { + u32 vdma_channels_bitmap; + }; + +-struct hailo_config_constants { +- const char *filename; +- u32 address; +- size_t max_size; +-}; +- + struct hailo_file_batch { + const char *filename; + u32 address; + size_t max_size; + bool is_mandatory; + bool has_header; ++ bool has_core; + }; + + // TODO: HRT-6144 - Align Windows/Linux to QNX +@@ -130,27 +129,15 @@ void hailo_pcie_disable_interrupts(struc + int hailo_pcie_write_firmware_control(struct hailo_pcie_resources *resources, const struct hailo_fw_control *command); + int hailo_pcie_read_firmware_control(struct hailo_pcie_resources *resources, struct hailo_fw_control *command); + +-int hailo_pcie_write_firmware(struct hailo_pcie_resources *resources, const void *fw_data, size_t fw_size); + int hailo_pcie_write_firmware_batch(struct device *dev, struct hailo_pcie_resources *resources, u32 stage); + bool hailo_pcie_is_firmware_loaded(struct hailo_pcie_resources *resources); + bool hailo_pcie_wait_for_firmware(struct hailo_pcie_resources *resources); + +-int hailo_pcie_read_firmware_notification(struct hailo_pcie_resources *resources, +- struct hailo_d2h_notification *notification); +- +-int hailo_pcie_write_config_common(struct hailo_pcie_resources *resources, const void* config_data, +- const size_t config_size, const struct hailo_config_constants *config_consts); +-const struct hailo_config_constants* hailo_pcie_get_board_config_constants(const enum hailo_board_type board_type); +-const struct hailo_config_constants* hailo_pcie_get_user_config_constants(const enum hailo_board_type board_type); +-const char* hailo_pcie_get_fw_filename(const enum hailo_board_type board_type); +- +-long hailo_pcie_read_firmware_log(struct hailo_pcie_resources *resources, struct hailo_read_log_params *params); + int hailo_pcie_memory_transfer(struct hailo_pcie_resources *resources, struct hailo_memory_transfer_params *params); + + bool hailo_pcie_is_device_connected(struct hailo_pcie_resources *resources); + void hailo_pcie_write_firmware_driver_shutdown(struct hailo_pcie_resources *resources); +-void write_memory(struct hailo_pcie_resources *resources, hailo_ptr_t dest, const void *src, u32 len); +-void hailo_trigger_firmware_boot(struct hailo_pcie_resources *resources); ++void hailo_trigger_firmware_boot(struct hailo_pcie_resources *resources, u32 address); + + int hailo_set_device_type(struct hailo_pcie_resources *resources); + +@@ -159,7 +146,12 @@ u32 hailo_get_boot_status(struct hailo_p + int hailo_pcie_configure_atr_table(struct hailo_resource *bridge_config, u64 trsl_addr, u32 atr_index); + void hailo_pcie_read_atr_table(struct hailo_resource *bridge_config, struct hailo_atr_config *atr, u32 atr_index); + +-void hailo_soc_write_soc_connect(struct hailo_pcie_resources *resources); ++u64 hailo_pcie_encode_desc_dma_address_range(dma_addr_t dma_address_start, dma_addr_t dma_address_end, u32 step, u8 channel_id); ++ ++void hailo_pcie_soc_write_request(struct hailo_pcie_resources *resources, ++ const struct hailo_pcie_soc_request *request); ++void hailo_pcie_soc_read_response(struct hailo_pcie_resources *resources, ++ struct hailo_pcie_soc_response *response); + + #ifdef __cplusplus + } +--- /dev/null ++++ b/drivers/media/pci/hailo/common/soc_structs.h +@@ -0,0 +1,79 @@ ++// SPDX-License-Identifier: MIT ++/** ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. ++ **/ ++/** ++ * Contains definitions for pcie soc to pcie ep communication ++ */ ++ ++#ifndef __HAILO_COMMON_SOC_STRUCTS__ ++#define __HAILO_COMMON_SOC_STRUCTS__ ++ ++#include ++ ++#pragma pack(push, 1) ++ ++struct hailo_pcie_soc_connect_request { ++ u16 port; ++}; ++ ++struct hailo_pcie_soc_connect_response { ++ u8 input_channel_index; ++ u8 output_channel_index; ++}; ++ ++ ++struct hailo_pcie_soc_close_request { ++ u32 channels_bitmap; ++}; ++ ++struct hailo_pcie_soc_close_response { ++ u8 reserved; ++}; ++ ++enum hailo_pcie_soc_control_code { ++ // Start from big initial value to ensure the right code was used (using 0 ++ // as initiale may cause confusion if the code was not set correctly). ++ HAILO_PCIE_SOC_CONTROL_CODE_CONNECT = 0x100, ++ HAILO_PCIE_SOC_CONTROL_CODE_CLOSE, ++ HAILO_PCIE_SOC_CONTROL_CODE_INVALID, ++}; ++ ++#define HAILO_PCIE_SOC_MAX_REQUEST_SIZE_BYTES (16) ++#define HAILO_PCIE_SOC_MAX_RESPONSE_SIZE_BYTES (16) ++ ++// IRQ to signal the PCIe that the EP was closed/released ++#define PCI_EP_SOC_CLOSED_IRQ (0x00000020) ++#define PCI_EP_SOC_CONNECT_RESPONSE (0x00000010) ++ ++struct hailo_pcie_soc_request { ++ u32 control_code; ++ union { ++ struct hailo_pcie_soc_connect_request connect; ++ struct hailo_pcie_soc_close_request close; ++ u8 pad[HAILO_PCIE_SOC_MAX_REQUEST_SIZE_BYTES]; ++ }; ++}; ++ ++struct hailo_pcie_soc_response { ++ u32 control_code; ++ s32 status; ++ union { ++ struct hailo_pcie_soc_connect_response connect; ++ struct hailo_pcie_soc_close_response close; ++ u8 pad[HAILO_PCIE_SOC_MAX_RESPONSE_SIZE_BYTES]; ++ }; ++}; ++ ++#pragma pack(pop) ++ ++// Compile time validate function. Don't need to call it. ++static inline void __validate_soc_struct_sizes(void) ++{ ++ BUILD_BUG_ON_MSG(sizeof(struct hailo_pcie_soc_request) != ++ sizeof(u32) + HAILO_PCIE_SOC_MAX_REQUEST_SIZE_BYTES, "Invalid request size"); ++ BUILD_BUG_ON_MSG(sizeof(struct hailo_pcie_soc_response) != ++ sizeof(u32) + sizeof(s32) + HAILO_PCIE_SOC_MAX_RESPONSE_SIZE_BYTES, "Invalid response size"); ++} ++ ++#endif /* __HAILO_COMMON_SOC_STRUCTS__ */ +\ No newline at end of file +--- a/drivers/media/pci/hailo/common/utils.h ++++ b/drivers/media/pci/hailo/common/utils.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: MIT + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _HAILO_DRIVER_UTILS_H_ +@@ -8,6 +8,11 @@ + + #include + ++#define DWORD_SIZE (4) ++#define WORD_SIZE (2) ++#define BYTE_SIZE (1) ++#define BITS_IN_BYTE (8) ++ + #define hailo_clear_bit(bit, pval) { *(pval) &= ~(1 << bit); } + #define hailo_test_bit(pos,var_addr) ((*var_addr) & (1<<(pos))) + +@@ -50,6 +55,22 @@ static inline uint8_t ceil_log2(uint32_t + return result; + } + ++// Gets the nearest power of 2 >= value, for any value <= MAX_POWER_OF_2_VALUE. Otherwise POWER_OF_2_ERROR is returned. ++#define MAX_POWER_OF_2_VALUE (0x80000000) ++#define POWER_OF_2_ERROR ((uint32_t)-1) ++static inline uint32_t get_nearest_powerof_2(uint32_t value) ++{ ++ uint32_t power_of_2 = 1; ++ if (value > MAX_POWER_OF_2_VALUE) { ++ return POWER_OF_2_ERROR; ++ } ++ ++ while (value > power_of_2) { ++ power_of_2 <<= 1; ++ } ++ return power_of_2; ++} ++ + #ifndef DIV_ROUND_UP + #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) + #endif +--- a/drivers/media/pci/hailo/common/vdma_common.c ++++ b/drivers/media/pci/hailo/common/vdma_common.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: MIT + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #include "vdma_common.h" +@@ -62,11 +62,6 @@ + #define VDMA_CHANNEL_NUM_PROCESSED_MASK ((1 << VDMA_CHANNEL_NUM_PROCESSED_WIDTH) - 1) + #define VDMA_CHANNEL_NUM_ONGOING_MASK VDMA_CHANNEL_NUM_PROCESSED_MASK + +-#define DWORD_SIZE (4) +-#define WORD_SIZE (2) +-#define BYTE_SIZE (1) +-#define BITS_IN_BYTE (8) +- + #define TIMESTAMPS_CIRC_SPACE(timestamp_list) \ + CIRC_SPACE((timestamp_list).head, (timestamp_list).tail, CHANNEL_IRQ_TIMESTAMPS_SIZE) + #define TIMESTAMPS_CIRC_CNT(timestamp_list) \ +@@ -150,7 +145,7 @@ static bool validate_last_desc_status(st + return true; + } + +-void hailo_vdma_program_descriptor(struct hailo_vdma_descriptor *descriptor, u64 dma_address, size_t page_size, ++static void hailo_vdma_program_descriptor(struct hailo_vdma_descriptor *descriptor, u64 dma_address, size_t page_size, + u8 data_id) + { + descriptor->PageSize_DescControl = (u32)((page_size << DESCRIPTOR_PAGE_SIZE_SHIFT) + +@@ -174,33 +169,45 @@ static int program_descriptors_in_chunk( + u32 max_desc_index, + u8 channel_id) + { +- const u32 desc_per_chunk = DIV_ROUND_UP(chunk_size, desc_list->desc_page_size); ++ const u16 page_size = desc_list->desc_page_size; ++ const u8 ddr_data_id = vdma_hw->ddr_data_id; ++ const u32 descs_to_program = DIV_ROUND_UP(chunk_size, page_size); ++ const u32 starting_desc_index = desc_index; ++ const u32 residue_size = chunk_size % page_size; + struct hailo_vdma_descriptor *dma_desc = NULL; +- u16 size_to_program = 0; +- u32 index = 0; + u64 encoded_addr = 0; + +- for (index = 0; index < desc_per_chunk; index++) { +- if (desc_index > max_desc_index) { +- return -ERANGE; +- } +- +- encoded_addr = vdma_hw->hw_ops.encode_desc_dma_address(chunk_addr, channel_id); +- if (INVALID_VDMA_ADDRESS == encoded_addr) { +- return -EFAULT; +- } ++ if (descs_to_program == 0) { ++ // Nothing to program ++ return 0; ++ } + +- dma_desc = &desc_list->desc_list[desc_index % desc_list->desc_count]; +- size_to_program = chunk_size > desc_list->desc_page_size ? +- desc_list->desc_page_size : (u16)chunk_size; +- hailo_vdma_program_descriptor(dma_desc, encoded_addr, size_to_program, vdma_hw->ddr_data_id); ++ // We iterate through descriptors [desc_index, desc_index + descs_to_program) ++ if (desc_index + descs_to_program > max_desc_index + 1) { ++ return -ERANGE; ++ } + +- chunk_addr += size_to_program; +- chunk_size -= size_to_program; +- desc_index++; ++ encoded_addr = vdma_hw->hw_ops.encode_desc_dma_address_range(chunk_addr, chunk_addr + chunk_size, page_size, channel_id); ++ if (INVALID_VDMA_ADDRESS == encoded_addr) { ++ return -EFAULT; + } + +- return (int)desc_per_chunk; ++ // Program all descriptors except the last one ++ for (desc_index = starting_desc_index; desc_index < starting_desc_index + descs_to_program - 1; desc_index++) { ++ // 'desc_index & desc_list_len_mask' is used instead of modulo; see hailo_vdma_descriptors_list documentation. ++ hailo_vdma_program_descriptor( ++ &desc_list->desc_list[desc_index & desc_list->desc_count_mask], ++ encoded_addr, page_size, ddr_data_id); ++ encoded_addr += page_size; ++ } ++ ++ // Handle the last descriptor outside of the loop ++ // 'desc_index & desc_list_len_mask' is used instead of modulo; see hailo_vdma_descriptors_list documentation. ++ dma_desc = &desc_list->desc_list[desc_index & desc_list->desc_count_mask]; ++ hailo_vdma_program_descriptor(dma_desc, encoded_addr, ++ (residue_size == 0) ? page_size : (u16)residue_size, ddr_data_id); ++ ++ return (int)descs_to_program; + } + + static unsigned long get_interrupts_bitmask(struct hailo_vdma_hw *vdma_hw, +@@ -236,11 +243,11 @@ static int bind_and_program_descriptors_ + { + const u8 channel_id = get_channel_id(channel_index); + int desc_programmed = 0; ++ int descs_programmed_in_chunk = 0; + u32 max_desc_index = 0; + u32 chunk_size = 0; + struct scatterlist *sg_entry = NULL; + unsigned int i = 0; +- int ret = 0; + size_t buffer_current_offset = 0; + dma_addr_t chunk_start_addr = 0; + u32 program_size = buffer->size; +@@ -272,14 +279,14 @@ static int bind_and_program_descriptors_ + (u32)(sg_dma_len(sg_entry)); + chunk_size = min((u32)program_size, chunk_size); + +- ret = program_descriptors_in_chunk(vdma_hw, chunk_start_addr, chunk_size, desc_list, ++ descs_programmed_in_chunk = program_descriptors_in_chunk(vdma_hw, chunk_start_addr, chunk_size, desc_list, + starting_desc, max_desc_index, channel_id); +- if (ret < 0) { +- return ret; ++ if (descs_programmed_in_chunk < 0) { ++ return descs_programmed_in_chunk; + } + +- desc_programmed += ret; +- starting_desc = starting_desc + ret; ++ desc_programmed += descs_programmed_in_chunk; ++ starting_desc = starting_desc + descs_programmed_in_chunk; + program_size -= chunk_size; + buffer_current_offset += sg_dma_len(sg_entry); + } +@@ -583,21 +590,23 @@ void hailo_vdma_engine_disable_channels( + engine->enabled_channels &= ~bitmap; + + for_each_vdma_channel(engine, channel, channel_index) { +- channel_state_init(&channel->state); ++ if (hailo_test_bit(channel_index, &bitmap)) { ++ channel_state_init(&channel->state); + +- while (ONGOING_TRANSFERS_CIRC_CNT(channel->ongoing_transfers) > 0) { +- struct hailo_ongoing_transfer transfer; +- ongoing_transfer_pop(channel, &transfer); +- +- if (channel->last_desc_list == NULL) { +- pr_err("Channel %d has ongoing transfers but no desc list\n", channel->index); +- continue; ++ while (ONGOING_TRANSFERS_CIRC_CNT(channel->ongoing_transfers) > 0) { ++ struct hailo_ongoing_transfer transfer; ++ ongoing_transfer_pop(channel, &transfer); ++ ++ if (channel->last_desc_list == NULL) { ++ pr_err("Channel %d has ongoing transfers but no desc list\n", channel->index); ++ continue; ++ } ++ ++ clear_dirty_descs(channel, &transfer); + } + +- clear_dirty_descs(channel, &transfer); ++ channel->last_desc_list = NULL; + } +- +- channel->last_desc_list = NULL; + } + } + +--- a/drivers/media/pci/hailo/common/vdma_common.h ++++ b/drivers/media/pci/hailo/common/vdma_common.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: MIT + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _HAILO_COMMON_VDMA_COMMON_H_ +@@ -30,7 +30,13 @@ struct hailo_vdma_descriptor { + + struct hailo_vdma_descriptors_list { + struct hailo_vdma_descriptor *desc_list; +- u32 desc_count; // Must be power of 2 if is_circular is set. ++ // Must be power of 2 if is_circular is set. ++ u32 desc_count; ++ // The nearest power of 2 to desc_count (including desc_count), minus 1. ++ // * If the list is circular, then 'index & desc_count_mask' can be used instead of modulo. ++ // * Otherwise, we can't wrap around the list anyway. However, for any index < desc_count, 'index & desc_count_mask' ++ // will return the same value. ++ u32 desc_count_mask; + u16 desc_page_size; + bool is_circular; + }; +@@ -113,9 +119,10 @@ struct hailo_vdma_engine { + }; + + struct hailo_vdma_hw_ops { +- // Accepts some dma_addr_t mapped to the device and encodes it using +- // hw specific encode. returns INVALID_VDMA_ADDRESS on failure. +- u64 (*encode_desc_dma_address)(dma_addr_t dma_address, u8 channel_id); ++ // Accepts start, end and step of an address range (of type dma_addr_t). ++ // Returns the encoded base address or INVALID_VDMA_ADDRESS if the range/step is invalid. ++ // All addresses in the range of [returned_addr, returned_addr + step, returned_addr + 2*step, ..., dma_address_end) are valid. ++ u64 (*encode_desc_dma_address_range)(dma_addr_t dma_address_start, dma_addr_t dma_address_end, u32 step, u8 channel_id); + }; + + struct hailo_vdma_hw { +@@ -136,12 +143,9 @@ struct hailo_vdma_hw { + for (index = 0, element = &array[index]; index < size; index++, element = &array[index]) + + #define for_each_vdma_channel(engine, channel, channel_index) \ +- _for_each_element_array(engine->channels, MAX_VDMA_CHANNELS_PER_ENGINE, \ ++ _for_each_element_array((engine)->channels, MAX_VDMA_CHANNELS_PER_ENGINE, \ + channel, channel_index) + +-void hailo_vdma_program_descriptor(struct hailo_vdma_descriptor *descriptor, u64 dma_address, size_t page_size, +- u8 data_id); +- + /** + * Program the given descriptors list to map the given buffer. + * +--- a/drivers/media/pci/hailo/src/fops.c ++++ b/drivers/media/pci/hailo/src/fops.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #include +@@ -19,14 +19,14 @@ + #include + #endif + +-#include "utils.h" + #include "fops.h" + #include "vdma_common.h" + #include "utils/logs.h" + #include "vdma/memory.h" + #include "vdma/ioctl.h" + #include "utils/compact.h" +-#include "pci_soc_ioctl.h" ++#include "nnc.h" ++#include "soc.h" + + + #if LINUX_VERSION_CODE >= KERNEL_VERSION( 4, 13, 0 ) +@@ -48,13 +48,6 @@ + // On pcie driver there is only one dma engine + #define DEFAULT_VDMA_ENGINE_INDEX (0) + +-#if !defined(HAILO_EMULATOR) +-#define DEFAULT_SHUTDOWN_TIMEOUT_MS (5) +-#else /* !defined(HAILO_EMULATOR) */ +-#define DEFAULT_SHUTDOWN_TIMEOUT_MS (1000) +-#endif /* !defined(HAILO_EMULATOR) */ +- +-static long hailo_add_notification_wait(struct hailo_pcie_board *board, struct file *filp); + + static struct hailo_file_context *create_file_context(struct hailo_pcie_board *board, struct file *filp) + { +@@ -124,7 +117,7 @@ int hailo_pcie_fops_open(struct inode *i + + previous_power_state = pBoard->pDev->current_state; + if (PCI_D0 != previous_power_state) { +- hailo_info(pBoard, "Waking up board"); ++ hailo_info(pBoard, "Waking up board change state from %d to PCI_D0\n", previous_power_state); + err = pci_set_power_state(pBoard->pDev, PCI_D0); + if (err < 0) { + hailo_err(pBoard, "Failed waking up board %d", err); +@@ -148,7 +141,11 @@ int hailo_pcie_fops_open(struct inode *i + interrupts_enabled_by_filp = true; + } + +- err = hailo_add_notification_wait(pBoard, filp); ++ if (pBoard->pcie_resources.accelerator_type == HAILO_ACCELERATOR_TYPE_NNC) { ++ err = hailo_nnc_file_context_init(pBoard, context); ++ } else { ++ err = hailo_soc_file_context_init(pBoard, context); ++ } + if (err < 0) { + goto l_release_irq; + } +@@ -166,6 +163,7 @@ l_release_irq: + + l_revert_power_state: + if (pBoard->pDev->current_state != previous_power_state) { ++ hailo_info(pBoard, "Power changing state from %d to %d\n", previous_power_state, pBoard->pDev->current_state); + if (pci_set_power_state(pBoard->pDev, previous_power_state) < 0) { + hailo_err(pBoard, "Failed setting power state back to %d\n", (int)previous_power_state); + } +@@ -180,34 +178,6 @@ l_exit: + return err; + } + +-int hailo_pcie_driver_down(struct hailo_pcie_board *board) +-{ +- long completion_result = 0; +- int err = 0; +- +- reinit_completion(&board->driver_down.reset_completed); +- +- hailo_pcie_write_firmware_driver_shutdown(&board->pcie_resources); +- +- // Wait for response +- completion_result = +- wait_for_completion_timeout(&board->driver_down.reset_completed, msecs_to_jiffies(DEFAULT_SHUTDOWN_TIMEOUT_MS)); +- if (completion_result <= 0) { +- if (0 == completion_result) { +- hailo_err(board, "hailo_pcie_driver_down, timeout waiting for shutdown response (timeout_ms=%d)\n", DEFAULT_SHUTDOWN_TIMEOUT_MS); +- err = -ETIMEDOUT; +- } else { +- hailo_info(board, "hailo_pcie_driver_down, wait for completion failed with err=%ld (process was interrupted or killed)\n", +- completion_result); +- err = completion_result; +- } +- goto l_exit; +- } +- +-l_exit: +- return err; +-} +- + int hailo_pcie_fops_release(struct inode *inode, struct file *filp) + { + struct hailo_pcie_board *board = (struct hailo_pcie_board *)filp->private_data; +@@ -234,12 +204,10 @@ int hailo_pcie_fops_release(struct inode + hailo_err(board, "Invalid file context\n"); + } + +- hailo_pcie_clear_notification_wait_list(board, filp); +- +- if (filp == board->vdma.used_by_filp) { +- if (hailo_pcie_driver_down(board)) { +- hailo_err(board, "Failed sending FW shutdown event"); +- } ++ if (board->pcie_resources.accelerator_type == HAILO_ACCELERATOR_TYPE_NNC) { ++ hailo_nnc_file_context_finalize(board, context); ++ } else { ++ hailo_soc_file_context_finalize(board, context); + } + + hailo_vdma_file_context_finalize(&context->vdma_context, &board->vdma, filp); +@@ -250,6 +218,7 @@ int hailo_pcie_fops_release(struct inode + hailo_disable_interrupts(board); + + if (power_mode_enabled()) { ++ hailo_info(board, "Power change state to PCI_D3hot\n"); + if (board->pDev && pci_set_power_state(board->pDev, PCI_D3hot) < 0) { + hailo_err(board, "Failed setting power state to D3hot"); + } +@@ -301,44 +270,23 @@ static long hailo_memory_transfer_ioctl( + return err; + } + +-static long hailo_read_log_ioctl(struct hailo_pcie_board *pBoard, unsigned long arg) +-{ +- long err = 0; +- struct hailo_read_log_params params; +- +- if (copy_from_user(¶ms, (void __user*)arg, sizeof(params))) { +- hailo_err(pBoard, "HAILO_READ_LOG, copy_from_user fail\n"); +- return -ENOMEM; +- } +- +- if (0 > (err = hailo_pcie_read_firmware_log(&pBoard->pcie_resources, ¶ms))) { +- hailo_err(pBoard, "HAILO_READ_LOG, reading from log failed with error: %ld \n", err); +- return err; +- } +- +- if (copy_to_user((void*)arg, ¶ms, sizeof(params))) { +- return -ENOMEM; +- } +- +- return 0; +-} +- + static void firmware_notification_irq_handler(struct hailo_pcie_board *board) + { + struct hailo_notification_wait *notif_wait_cursor = NULL; + int err = 0; + unsigned long irq_saved_flags = 0; + +- spin_lock_irqsave(&board->notification_read_spinlock, irq_saved_flags); +- err = hailo_pcie_read_firmware_notification(&board->pcie_resources, &board->notification_cache); +- spin_unlock_irqrestore(&board->notification_read_spinlock, irq_saved_flags); ++ spin_lock_irqsave(&board->nnc.notification_read_spinlock, irq_saved_flags); ++ err = hailo_pcie_read_firmware_notification(&board->pcie_resources.fw_access, &board->nnc.notification_cache); ++ spin_unlock_irqrestore(&board->nnc.notification_read_spinlock, irq_saved_flags); + + if (err < 0) { + hailo_err(board, "Failed reading firmware notification"); + } + else { ++ // TODO: HRT-14502 move interrupt handling to nnc + rcu_read_lock(); +- list_for_each_entry_rcu(notif_wait_cursor, &board->notification_wait_list, notification_wait_list) ++ list_for_each_entry_rcu(notif_wait_cursor, &board->nnc.notification_wait_list, notification_wait_list) + { + complete(¬if_wait_cursor->notification_completion); + } +@@ -374,7 +322,7 @@ irqreturn_t hailo_irqhandler(int irq, vo + + // wake fw_control if needed + if (irq_source.interrupt_bitmask & FW_CONTROL) { +- complete(&board->fw_control.completion); ++ complete(&board->nnc.fw_control.completion); + } + + // wake driver_down if needed +@@ -392,7 +340,14 @@ irqreturn_t hailo_irqhandler(int irq, vo + } + + if (irq_source.interrupt_bitmask & SOC_CONNECT_ACCEPTED) { +- complete_all(&board->soc_connect_accepted); ++ complete_all(&board->soc.control_resp_ready); ++ } ++ ++ if (irq_source.interrupt_bitmask & SOC_CLOSED_IRQ) { ++ hailo_info(board, "hailo_irqhandler - SOC_CLOSED_IRQ\n"); ++ // always use bitmap=0xFFFFFFFF - it is ok to wake all interrupts since each handler will check if the stream was aborted or not. ++ hailo_vdma_wakeup_interrupts(&board->vdma, &board->vdma.vdma_engines[DEFAULT_VDMA_ENGINE_INDEX], ++ 0xFFFFFFFF); + } + + if (0 != irq_source.vdma_channels_bitmap) { +@@ -404,170 +359,11 @@ irqreturn_t hailo_irqhandler(int irq, vo + return return_value; + } + +-static long hailo_get_notification_wait_thread(struct hailo_pcie_board *pBoard, struct file *filp, +- struct hailo_notification_wait **current_waiting_thread) +-{ +- struct hailo_notification_wait *cursor = NULL; +- // note: safe to access without rcu because the notification_wait_list is closed only on file release +- list_for_each_entry(cursor, &pBoard->notification_wait_list, notification_wait_list) +- { +- if ((current->tgid == cursor->tgid) && (filp == cursor->filp)) { +- *current_waiting_thread = cursor; +- return 0; +- } +- } +- +- return -EFAULT; +-} +- +-static long hailo_add_notification_wait(struct hailo_pcie_board *board, struct file *filp) +-{ +- struct hailo_notification_wait *new_notification_wait = NULL; +- if (!(new_notification_wait = kmalloc(sizeof(*new_notification_wait), GFP_KERNEL))) { +- hailo_err(board, "Failed to allocate notification wait structure.\n"); +- return -ENOMEM; +- } +- new_notification_wait->tgid = current->tgid; +- new_notification_wait->filp = filp; +- new_notification_wait->is_disabled = false; +- init_completion(&new_notification_wait->notification_completion); +- list_add_rcu(&new_notification_wait->notification_wait_list, &board->notification_wait_list); +- return 0; +-} +- +-static long hailo_read_notification_ioctl(struct hailo_pcie_board *pBoard, unsigned long arg, struct file *filp, +- bool* should_up_board_mutex) +-{ +- long err = 0; +- struct hailo_notification_wait *current_waiting_thread = NULL; +- struct hailo_d2h_notification *notification = &pBoard->notification_to_user; +- unsigned long irq_saved_flags; +- +- err = hailo_get_notification_wait_thread(pBoard, filp, ¤t_waiting_thread); +- if (0 != err) { +- goto l_exit; +- } +- up(&pBoard->mutex); +- +- if (0 > (err = wait_for_completion_interruptible(¤t_waiting_thread->notification_completion))) { +- hailo_info(pBoard, +- "HAILO_READ_NOTIFICATION - wait_for_completion_interruptible error. err=%ld. tgid=%d (process was interrupted or killed)\n", +- err, current_waiting_thread->tgid); +- *should_up_board_mutex = false; +- goto l_exit; +- } +- +- if (down_interruptible(&pBoard->mutex)) { +- hailo_info(pBoard, "HAILO_READ_NOTIFICATION - down_interruptible error (process was interrupted or killed)\n"); +- *should_up_board_mutex = false; +- err = -ERESTARTSYS; +- goto l_exit; +- } +- +- // Check if was disabled +- if (current_waiting_thread->is_disabled) { +- hailo_info(pBoard, "HAILO_READ_NOTIFICATION, can't find notification wait for tgid=%d\n", current->tgid); +- err = -EINVAL; +- goto l_exit; +- } +- +- reinit_completion(¤t_waiting_thread->notification_completion); +- +- spin_lock_irqsave(&pBoard->notification_read_spinlock, irq_saved_flags); +- notification->buffer_len = pBoard->notification_cache.buffer_len; +- memcpy(notification->buffer, pBoard->notification_cache.buffer, notification->buffer_len); +- spin_unlock_irqrestore(&pBoard->notification_read_spinlock, irq_saved_flags); +- +- if (copy_to_user((void __user*)arg, notification, sizeof(*notification))) { +- hailo_err(pBoard, "HAILO_READ_NOTIFICATION copy_to_user fail\n"); +- err = -ENOMEM; +- goto l_exit; +- } +- +-l_exit: +- return err; +-} +- +-static long hailo_disable_notification(struct hailo_pcie_board *pBoard, struct file *filp) +-{ +- struct hailo_notification_wait *cursor = NULL; +- +- hailo_info(pBoard, "HAILO_DISABLE_NOTIFICATION: disable notification"); +- rcu_read_lock(); +- list_for_each_entry_rcu(cursor, &pBoard->notification_wait_list, notification_wait_list) { +- if ((current->tgid == cursor->tgid) && (filp == cursor->filp)) { +- cursor->is_disabled = true; +- complete(&cursor->notification_completion); +- break; +- } +- } +- rcu_read_unlock(); +- +- return 0; +-} +- +-static int hailo_fw_control(struct hailo_pcie_board *pBoard, unsigned long arg, bool* should_up_board_mutex) +-{ +- struct hailo_fw_control *command = &pBoard->fw_control.command; +- long completion_result = 0; +- int err = 0; +- +- up(&pBoard->mutex); +- *should_up_board_mutex = false; +- +- if (down_interruptible(&pBoard->fw_control.mutex)) { +- hailo_info(pBoard, "hailo_fw_control down_interruptible fail tgid:%d (process was interrupted or killed)\n", current->tgid); +- return -ERESTARTSYS; +- } +- +- if (copy_from_user(command, (void __user*)arg, sizeof(*command))) { +- hailo_err(pBoard, "hailo_fw_control, copy_from_user fail\n"); +- err = -ENOMEM; +- goto l_exit; +- } +- +- reinit_completion(&pBoard->fw_control.completion); +- +- err = hailo_pcie_write_firmware_control(&pBoard->pcie_resources, command); +- if (err < 0) { +- hailo_err(pBoard, "Failed writing fw control to pcie\n"); +- goto l_exit; +- } +- +- // Wait for response +- completion_result = wait_for_completion_interruptible_timeout(&pBoard->fw_control.completion, msecs_to_jiffies(command->timeout_ms)); +- if (completion_result <= 0) { +- if (0 == completion_result) { +- hailo_err(pBoard, "hailo_fw_control, timeout waiting for control (timeout_ms=%d)\n", command->timeout_ms); +- err = -ETIMEDOUT; +- } else { +- hailo_info(pBoard, "hailo_fw_control, wait for completion failed with err=%ld (process was interrupted or killed)\n", completion_result); +- err = -EINTR; +- } +- goto l_exit; +- } +- +- err = hailo_pcie_read_firmware_control(&pBoard->pcie_resources, command); +- if (err < 0) { +- hailo_err(pBoard, "Failed reading fw control from pcie\n"); +- goto l_exit; +- } +- +- if (copy_to_user((void __user*)arg, command, sizeof(*command))) { +- hailo_err(pBoard, "hailo_fw_control, copy_to_user fail\n"); +- err = -ENOMEM; +- goto l_exit; +- } +- +-l_exit: +- up(&pBoard->fw_control.mutex); +- return err; +-} +- + static long hailo_query_device_properties(struct hailo_pcie_board *board, unsigned long arg) + { + struct hailo_device_properties props = { + .desc_max_page_size = board->desc_max_page_size, ++ .board_type = board->pcie_resources.board_type, + .allocation_mode = board->allocation_mode, + .dma_type = HAILO_DMA_TYPE_PCIE, + .dma_engines_count = board->vdma.vdma_engines_count, +@@ -618,24 +414,6 @@ static long hailo_general_ioctl(struct h + } + } + +-static long hailo_nnc_ioctl(struct hailo_pcie_board *board, unsigned int cmd, unsigned long arg, +- struct file *filp, bool *should_up_board_mutex) +-{ +- switch (cmd) { +- case HAILO_FW_CONTROL: +- return hailo_fw_control(board, arg, should_up_board_mutex); +- case HAILO_READ_NOTIFICATION: +- return hailo_read_notification_ioctl(board, arg, filp, should_up_board_mutex); +- case HAILO_DISABLE_NOTIFICATION: +- return hailo_disable_notification(board, filp); +- case HAILO_READ_LOG: +- return hailo_read_log_ioctl(board, arg); +- default: +- hailo_err(board, "Invalid nnc ioctl code 0x%x (nr: %d)\n", cmd, _IOC_NR(cmd)); +- return -ENOTTY; +- } +-} +- + long hailo_pcie_fops_unlockedioctl(struct file* filp, unsigned int cmd, unsigned long arg) + { + long err = 0; +@@ -694,7 +472,7 @@ long hailo_pcie_fops_unlockedioctl(struc + hailo_err(board, "Ioctl %d is not supported on this accelerator type\n", _IOC_TYPE(cmd)); + err = -EINVAL; + } else { +- err = hailo_soc_ioctl(board, &context->vdma_context, &board->vdma, cmd, arg); ++ err = hailo_soc_ioctl(board, context, &board->vdma, cmd, arg); + } + break; + case HAILO_NNC_IOCTL_MAGIC: +--- a/drivers/media/pci/hailo/src/fops.h ++++ b/drivers/media/pci/hailo/src/fops.h +@@ -1,16 +1,17 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _HAILO_PCI_FOPS_H_ + #define _HAILO_PCI_FOPS_H_ + ++#include "pcie.h" ++ + int hailo_pcie_fops_open(struct inode* inode, struct file* filp); + int hailo_pcie_fops_release(struct inode* inode, struct file* filp); + long hailo_pcie_fops_unlockedioctl(struct file* filp, unsigned int cmd, unsigned long arg); + int hailo_pcie_fops_mmap(struct file* filp, struct vm_area_struct *vma); +-int hailo_pcie_driver_down(struct hailo_pcie_board *board); + void hailo_pcie_ep_init(struct hailo_pcie_board *board); + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) +--- /dev/null ++++ b/drivers/media/pci/hailo/src/nnc.c +@@ -0,0 +1,299 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/** ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. ++ **/ ++/** ++ * A Hailo PCIe NNC device is a device contains a NNC (neural network core) and some basic FW. ++ * The device supports sending controls, receiving notification and reading the FW log. ++ */ ++ ++#include "nnc.h" ++#include "hailo_ioctl_common.h" ++ ++#include "utils/logs.h" ++#include "utils/compact.h" ++ ++#include ++ ++#if !defined(HAILO_EMULATOR) ++#define DEFAULT_SHUTDOWN_TIMEOUT_MS (5) ++#else /* !defined(HAILO_EMULATOR) */ ++#define DEFAULT_SHUTDOWN_TIMEOUT_MS (1000) ++#endif /* !defined(HAILO_EMULATOR) */ ++ ++void hailo_nnc_init(struct hailo_pcie_nnc *nnc) ++{ ++ sema_init(&nnc->fw_control.mutex, 1); ++ spin_lock_init(&nnc->notification_read_spinlock); ++ init_completion(&nnc->fw_control.completion); ++ INIT_LIST_HEAD(&nnc->notification_wait_list); ++ memset(&nnc->notification_cache, 0, sizeof(nnc->notification_cache)); ++} ++ ++void hailo_nnc_finalize(struct hailo_pcie_nnc *nnc) ++{ ++ struct hailo_notification_wait *cursor = NULL; ++ ++ // Lock rcu_read_lock and send notification_completion to wake anyone waiting on the notification_wait_list when removed ++ rcu_read_lock(); ++ list_for_each_entry_rcu(cursor, &nnc->notification_wait_list, notification_wait_list) { ++ cursor->is_disabled = true; ++ complete(&cursor->notification_completion); ++ } ++ rcu_read_unlock(); ++} ++ ++static int hailo_fw_control(struct hailo_pcie_board *board, unsigned long arg, bool* should_up_board_mutex) ++{ ++ struct hailo_fw_control *command = &board->nnc.fw_control.command; ++ long completion_result = 0; ++ int err = 0; ++ ++ up(&board->mutex); ++ *should_up_board_mutex = false; ++ ++ if (down_interruptible(&board->nnc.fw_control.mutex)) { ++ hailo_info(board, "hailo_fw_control down_interruptible fail tgid:%d (process was interrupted or killed)\n", current->tgid); ++ return -ERESTARTSYS; ++ } ++ ++ if (copy_from_user(command, (void __user*)arg, sizeof(*command))) { ++ hailo_err(board, "hailo_fw_control, copy_from_user fail\n"); ++ err = -ENOMEM; ++ goto l_exit; ++ } ++ ++ reinit_completion(&board->nnc.fw_control.completion); ++ ++ err = hailo_pcie_write_firmware_control(&board->pcie_resources, command); ++ if (err < 0) { ++ hailo_err(board, "Failed writing fw control to pcie\n"); ++ goto l_exit; ++ } ++ ++ // Wait for response ++ completion_result = wait_for_completion_interruptible_timeout(&board->nnc.fw_control.completion, msecs_to_jiffies(command->timeout_ms)); ++ if (completion_result <= 0) { ++ if (0 == completion_result) { ++ hailo_err(board, "hailo_fw_control, timeout waiting for control (timeout_ms=%d)\n", command->timeout_ms); ++ err = -ETIMEDOUT; ++ } else { ++ hailo_info(board, "hailo_fw_control, wait for completion failed with err=%ld (process was interrupted or killed)\n", completion_result); ++ err = -EINTR; ++ } ++ goto l_exit; ++ } ++ ++ err = hailo_pcie_read_firmware_control(&board->pcie_resources, command); ++ if (err < 0) { ++ hailo_err(board, "Failed reading fw control from pcie\n"); ++ goto l_exit; ++ } ++ ++ if (copy_to_user((void __user*)arg, command, sizeof(*command))) { ++ hailo_err(board, "hailo_fw_control, copy_to_user fail\n"); ++ err = -ENOMEM; ++ goto l_exit; ++ } ++ ++l_exit: ++ up(&board->nnc.fw_control.mutex); ++ return err; ++} ++ ++static long hailo_get_notification_wait_thread(struct hailo_pcie_board *board, struct file *filp, ++ struct hailo_notification_wait **current_waiting_thread) ++{ ++ struct hailo_notification_wait *cursor = NULL; ++ // note: safe to access without rcu because the notification_wait_list is closed only on file release ++ list_for_each_entry(cursor, &board->nnc.notification_wait_list, notification_wait_list) ++ { ++ if ((current->tgid == cursor->tgid) && (filp == cursor->filp)) { ++ *current_waiting_thread = cursor; ++ return 0; ++ } ++ } ++ ++ return -EFAULT; ++} ++ ++static long hailo_read_notification_ioctl(struct hailo_pcie_board *board, unsigned long arg, struct file *filp, ++ bool* should_up_board_mutex) ++{ ++ long err = 0; ++ struct hailo_notification_wait *current_waiting_thread = NULL; ++ struct hailo_d2h_notification *notification = &board->nnc.notification_to_user; ++ unsigned long irq_saved_flags; ++ ++ err = hailo_get_notification_wait_thread(board, filp, ¤t_waiting_thread); ++ if (0 != err) { ++ goto l_exit; ++ } ++ up(&board->mutex); ++ ++ if (0 > (err = wait_for_completion_interruptible(¤t_waiting_thread->notification_completion))) { ++ hailo_info(board, ++ "HAILO_READ_NOTIFICATION - wait_for_completion_interruptible error. err=%ld. tgid=%d (process was interrupted or killed)\n", ++ err, current_waiting_thread->tgid); ++ *should_up_board_mutex = false; ++ goto l_exit; ++ } ++ ++ if (down_interruptible(&board->mutex)) { ++ hailo_info(board, "HAILO_READ_NOTIFICATION - down_interruptible error (process was interrupted or killed)\n"); ++ *should_up_board_mutex = false; ++ err = -ERESTARTSYS; ++ goto l_exit; ++ } ++ ++ // Check if was disabled ++ if (current_waiting_thread->is_disabled) { ++ hailo_info(board, "HAILO_READ_NOTIFICATION, can't find notification wait for tgid=%d\n", current->tgid); ++ err = -EINVAL; ++ goto l_exit; ++ } ++ ++ reinit_completion(¤t_waiting_thread->notification_completion); ++ ++ spin_lock_irqsave(&board->nnc.notification_read_spinlock, irq_saved_flags); ++ notification->buffer_len = board->nnc.notification_cache.buffer_len; ++ memcpy(notification->buffer, board->nnc.notification_cache.buffer, notification->buffer_len); ++ spin_unlock_irqrestore(&board->nnc.notification_read_spinlock, irq_saved_flags); ++ ++ if (copy_to_user((void __user*)arg, notification, sizeof(*notification))) { ++ hailo_err(board, "HAILO_READ_NOTIFICATION copy_to_user fail\n"); ++ err = -ENOMEM; ++ goto l_exit; ++ } ++ ++l_exit: ++ return err; ++} ++ ++static long hailo_disable_notification(struct hailo_pcie_board *board, struct file *filp) ++{ ++ struct hailo_notification_wait *cursor = NULL; ++ ++ hailo_info(board, "HAILO_DISABLE_NOTIFICATION: disable notification"); ++ rcu_read_lock(); ++ list_for_each_entry_rcu(cursor, &board->nnc.notification_wait_list, notification_wait_list) { ++ if ((current->tgid == cursor->tgid) && (filp == cursor->filp)) { ++ cursor->is_disabled = true; ++ complete(&cursor->notification_completion); ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ ++ return 0; ++} ++ ++static long hailo_read_log_ioctl(struct hailo_pcie_board *board, unsigned long arg) ++{ ++ long err = 0; ++ struct hailo_read_log_params params; ++ ++ if (copy_from_user(¶ms, (void __user*)arg, sizeof(params))) { ++ hailo_err(board, "HAILO_READ_LOG, copy_from_user fail\n"); ++ return -ENOMEM; ++ } ++ ++ if (0 > (err = hailo_pcie_read_firmware_log(&board->pcie_resources.fw_access, ¶ms))) { ++ hailo_err(board, "HAILO_READ_LOG, reading from log failed with error: %ld \n", err); ++ return err; ++ } ++ ++ if (copy_to_user((void*)arg, ¶ms, sizeof(params))) { ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++long hailo_nnc_ioctl(struct hailo_pcie_board *board, unsigned int cmd, unsigned long arg, ++ struct file *filp, bool *should_up_board_mutex) ++{ ++ switch (cmd) { ++ case HAILO_FW_CONTROL: ++ return hailo_fw_control(board, arg, should_up_board_mutex); ++ case HAILO_READ_NOTIFICATION: ++ return hailo_read_notification_ioctl(board, arg, filp, should_up_board_mutex); ++ case HAILO_DISABLE_NOTIFICATION: ++ return hailo_disable_notification(board, filp); ++ case HAILO_READ_LOG: ++ return hailo_read_log_ioctl(board, arg); ++ default: ++ hailo_err(board, "Invalid nnc ioctl code 0x%x (nr: %d)\n", cmd, _IOC_NR(cmd)); ++ return -ENOTTY; ++ } ++} ++ ++ ++static int add_notification_wait(struct hailo_pcie_board *board, struct file *filp) ++{ ++ struct hailo_notification_wait *wait = kmalloc(sizeof(*wait), GFP_KERNEL); ++ if (!wait) { ++ hailo_err(board, "Failed to allocate notification wait structure.\n"); ++ return -ENOMEM; ++ } ++ wait->tgid = current->tgid; ++ wait->filp = filp; ++ wait->is_disabled = false; ++ init_completion(&wait->notification_completion); ++ list_add_rcu(&wait->notification_wait_list, &board->nnc.notification_wait_list); ++ return 0; ++} ++ ++int hailo_nnc_file_context_init(struct hailo_pcie_board *board, struct hailo_file_context *context) ++{ ++ return add_notification_wait(board, context->filp); ++} ++ ++static void clear_notification_wait_list(struct hailo_pcie_board *board, struct file *filp) ++{ ++ struct hailo_notification_wait *cur = NULL, *next = NULL; ++ list_for_each_entry_safe(cur, next, &board->nnc.notification_wait_list, notification_wait_list) { ++ if (cur->filp == filp) { ++ list_del_rcu(&cur->notification_wait_list); ++ synchronize_rcu(); ++ kfree(cur); ++ } ++ } ++} ++ ++int hailo_nnc_driver_down(struct hailo_pcie_board *board) ++{ ++ long completion_result = 0; ++ int err = 0; ++ ++ reinit_completion(&board->driver_down.reset_completed); ++ ++ hailo_pcie_write_firmware_driver_shutdown(&board->pcie_resources); ++ ++ // Wait for response ++ completion_result = ++ wait_for_completion_timeout(&board->driver_down.reset_completed, msecs_to_jiffies(DEFAULT_SHUTDOWN_TIMEOUT_MS)); ++ if (completion_result <= 0) { ++ if (0 == completion_result) { ++ hailo_err(board, "hailo_nnc_driver_down, timeout waiting for shutdown response (timeout_ms=%d)\n", DEFAULT_SHUTDOWN_TIMEOUT_MS); ++ err = -ETIMEDOUT; ++ } else { ++ hailo_info(board, "hailo_nnc_driver_down, wait for completion failed with err=%ld (process was interrupted or killed)\n", ++ completion_result); ++ err = completion_result; ++ } ++ goto l_exit; ++ } ++ ++l_exit: ++ return err; ++} ++ ++void hailo_nnc_file_context_finalize(struct hailo_pcie_board *board, struct hailo_file_context *context) ++{ ++ clear_notification_wait_list(board, context->filp); ++ ++ if (context->filp == board->vdma.used_by_filp) { ++ hailo_nnc_driver_down(board); ++ } ++} +\ No newline at end of file +--- /dev/null ++++ b/drivers/media/pci/hailo/src/nnc.h +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/** ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. ++ **/ ++ ++#ifndef _HAILO_PCI_NNC_H_ ++#define _HAILO_PCI_NNC_H_ ++ ++#include "pcie.h" ++ ++void hailo_nnc_init(struct hailo_pcie_nnc *nnc); ++void hailo_nnc_finalize(struct hailo_pcie_nnc *nnc); ++ ++long hailo_nnc_ioctl(struct hailo_pcie_board *board, unsigned int cmd, unsigned long arg, ++ struct file *filp, bool *should_up_board_mutex); ++ ++int hailo_nnc_file_context_init(struct hailo_pcie_board *board, struct hailo_file_context *context); ++void hailo_nnc_file_context_finalize(struct hailo_pcie_board *board, struct hailo_file_context *context); ++ ++int hailo_nnc_driver_down(struct hailo_pcie_board *board); ++ ++#endif /* _HAILO_PCI_NNC_H_ */ +\ No newline at end of file +--- a/drivers/media/pci/hailo/src/pci_soc_ioctl.c ++++ /dev/null +@@ -1,155 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/** +- * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. +- **/ +-#include "pci_soc_ioctl.h" +- +-#include "utils.h" +-#include "vdma_common.h" +-#include "utils/logs.h" +-#include "vdma/memory.h" +- +-#define PCI_SOC_VDMA_ENGINE_INDEX (0) +-#define PCI_SOC_WAIT_FOR_CONNECT_TIMEOUT_MS (10000) +- +-long hailo_soc_ioctl(struct hailo_pcie_board *board, struct hailo_vdma_file_context *context, +- struct hailo_vdma_controller *controller, unsigned int cmd, unsigned long arg) +-{ +- switch (cmd) { +- case HAILO_SOC_CONNECT: +- return hailo_soc_connect_ioctl(board, context, controller, arg); +- case HAILO_SOC_CLOSE: +- return hailo_soc_close_ioctl(board, controller, arg); +- default: +- hailo_err(board, "Invalid pcie EP ioctl code 0x%x (nr: %d)\n", cmd, _IOC_NR(cmd)); +- return -ENOTTY; +- } +-} +- +-long hailo_soc_connect_ioctl(struct hailo_pcie_board *board, struct hailo_vdma_file_context *context, +- struct hailo_vdma_controller *controller, unsigned long arg) +-{ +- struct hailo_soc_connect_params params; +- struct hailo_vdma_channel *input_channel = NULL; +- struct hailo_vdma_channel *output_channel = NULL; +- struct hailo_vdma_engine *vdma_engine = NULL; +- struct hailo_descriptors_list_buffer *input_descriptors_buffer = NULL; +- struct hailo_descriptors_list_buffer *output_descriptors_buffer = NULL; +- uint8_t depth = 0; +- int err = 0; +- long completion_result = 0; +- +- if (copy_from_user(¶ms, (void *)arg, sizeof(params))) { +- hailo_err(board, "copy_from_user fail\n"); +- return -ENOMEM; +- } +- +- // TODO: have pci_ep choose the channel indexes the soc will use - for now use 0 and 16 +- params.input_channel_index = 0; +- params.output_channel_index = 16; +- +- reinit_completion(&board->soc_connect_accepted); +- hailo_soc_write_soc_connect(&board->pcie_resources); +- +- // Wait for completion +- completion_result = wait_for_completion_interruptible_timeout(&board->soc_connect_accepted, +- msecs_to_jiffies(PCI_SOC_WAIT_FOR_CONNECT_TIMEOUT_MS)); +- if (0 > completion_result) { +- if (0 == completion_result) { +- hailo_err(board, "Timeout waiting for connect to be accepted (timeout_ms=%d)\n", PCI_SOC_WAIT_FOR_CONNECT_TIMEOUT_MS); +- return -ETIMEDOUT; +- } else { +- hailo_info(board, "soc connect failed with err=%ld (process was interrupted or killed)\n", +- completion_result); +- return -EINTR; +- } +- } +- +- vdma_engine = &controller->vdma_engines[PCI_SOC_VDMA_ENGINE_INDEX]; +- input_channel = &vdma_engine->channels[params.input_channel_index]; +- output_channel = &vdma_engine->channels[params.output_channel_index]; +- +- input_descriptors_buffer = hailo_vdma_find_descriptors_buffer(context, params.input_desc_handle); +- output_descriptors_buffer = hailo_vdma_find_descriptors_buffer(context, params.output_desc_handle); +- if (NULL == input_descriptors_buffer || NULL == output_descriptors_buffer) { +- hailo_dev_err(&board->pDev->dev, "input / output descriptors buffer not found \n"); +- return -EINVAL; +- } +- +- // Make sure channels that we are accepting are not already enabled +- if (0 != (vdma_engine->enabled_channels & params.input_channel_index) || +- 0 != (vdma_engine->enabled_channels & params.output_channel_index)) { +- hailo_dev_err(&board->pDev->dev, "Trying to accept already enabled channels\n"); +- return -EINVAL; +- } +- +- if (!is_powerof2((size_t)input_descriptors_buffer->desc_list.desc_count) || +- !is_powerof2((size_t)output_descriptors_buffer->desc_list.desc_count)) { +- hailo_dev_err(&board->pDev->dev, "Invalid desc list size\n"); +- return -EINVAL; +- } +- +- // configure and start input channel +- depth = ceil_log2(input_descriptors_buffer->desc_list.desc_count); +- // DMA Direction is only to get channel index - so +- err = hailo_vdma_start_channel(input_channel->host_regs, input_descriptors_buffer->dma_address, depth, +- board->vdma.hw->ddr_data_id); +- if (err < 0) { +- hailo_dev_err(&board->pDev->dev, "Error starting vdma input channel index %u\n", params.input_channel_index); +- return -EINVAL; +- } +- +- // configure and start output channel +- depth = ceil_log2(output_descriptors_buffer->desc_list.desc_count); +- // DMA Direction is only to get channel index - so +- err = hailo_vdma_start_channel(output_channel->host_regs, output_descriptors_buffer->dma_address, depth, +- board->vdma.hw->ddr_data_id); +- if (err < 0) { +- hailo_dev_err(&board->pDev->dev, "Error starting vdma output channel index %u\n", params.output_channel_index); +- // Close input channel +- hailo_vdma_stop_channel(input_channel->host_regs); +- return -EINVAL; +- } +- +- if (copy_to_user((void *)arg, ¶ms, sizeof(params))) { +- hailo_dev_err(&board->pDev->dev, "copy_to_user fail\n"); +- return -ENOMEM; +- } +- +- return 0; +-} +- +-long hailo_soc_close_ioctl(struct hailo_pcie_board *board, struct hailo_vdma_controller *controller, unsigned long arg) +-{ +- struct hailo_soc_close_params params; +- struct hailo_vdma_channel *input_channel = NULL; +- struct hailo_vdma_channel *output_channel = NULL; +- struct hailo_vdma_engine *vdma_engine = NULL; +- +- if (copy_from_user(¶ms, (void *)arg, sizeof(params))) { +- hailo_dev_err(&board->pDev->dev, "copy_from_user fail\n"); +- return -ENOMEM; +- } +- +- vdma_engine = &controller->vdma_engines[PCI_SOC_VDMA_ENGINE_INDEX]; +- +- if (!hailo_check_channel_index(params.input_channel_index, controller->hw->src_channels_bitmask, true)) { +- hailo_dev_err(&board->pDev->dev, "Invalid input channel index %u\n", params.input_channel_index); +- return -EINVAL; +- } +- +- if (!hailo_check_channel_index(params.output_channel_index, controller->hw->src_channels_bitmask, false)) { +- hailo_dev_err(&board->pDev->dev, "Invalid output channel index %u\n", params.output_channel_index); +- return -EINVAL; +- } +- +- input_channel = &vdma_engine->channels[params.input_channel_index]; +- output_channel = &vdma_engine->channels[params.output_channel_index]; +- +- // Close channels +- hailo_vdma_stop_channel(input_channel->host_regs); +- hailo_vdma_stop_channel(output_channel->host_regs); +- +- hailo_pcie_write_firmware_driver_shutdown(&board->pcie_resources); +- return 0; +-} +\ No newline at end of file +--- a/drivers/media/pci/hailo/src/pcie.c ++++ b/drivers/media/pci/hailo/src/pcie.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #include +@@ -22,6 +22,8 @@ + + #include "hailo_ioctl_common.h" + #include "pcie.h" ++#include "nnc.h" ++#include "soc.h" + #include "fops.h" + #include "sysfs.h" + #include "utils/logs.h" +@@ -40,11 +42,12 @@ enum hailo_allocate_driver_buffer_driver + HAILO_FORCE_BUFFER_FROM_DRIVER = 2, + }; + +-//Debug flag ++// Debug flag + static int force_desc_page_size = 0; + static bool g_is_power_mode_enabled = true; + static int force_allocation_from_driver = HAILO_NO_FORCE_BUFFER; + static bool force_hailo15_legacy_mode = false; ++static bool force_boot_linux_from_eemc = false; + + #define DEVICE_NODE_NAME "hailo" + static int char_major = 0; +@@ -206,7 +209,7 @@ static int hailo_pcie_disable_aspm(struc + /* Double-check ASPM control. If not disabled by the above, the + * BIOS is preventing that from happening (or CONFIG_PCIEASPM is + * not enabled); override by writing PCI config space directly. +- */ ++ */ + err = pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &pdev_aspmc); + if (err < 0) { + hailo_err(board, "Couldn't read LNKCTL capability\n"); +@@ -288,101 +291,59 @@ static void hailo_pcie_remove_board(stru + up(&g_hailo_add_board_mutex); + } + +-static int hailo_write_config(struct hailo_pcie_resources *resources, struct device *dev, +- const struct hailo_config_constants *config_consts) +-{ +- const struct firmware *config = NULL; +- int err = 0; +- +- if (NULL == config_consts->filename) { +- // Config not supported for platform +- return 0; +- } +- +- err = request_firmware_direct(&config, config_consts->filename, dev); +- if (err < 0) { +- hailo_dev_info(dev, "Config %s not found\n", config_consts->filename); +- return 0; +- } +- +- hailo_dev_notice(dev, "Writing config %s\n", config_consts->filename); +- +- err = hailo_pcie_write_config_common(resources, config->data, config->size, config_consts); +- if (err < 0) { +- if (-EINVAL == err) { +- hailo_dev_warn(dev, "Config size %zu is bigger than max %zu\n", config->size, config_consts->max_size); +- } +- release_firmware(config); +- return err; +- } +- +- release_firmware(config); +- return 0; +-} +- + static bool wait_for_firmware_completion(struct completion *fw_load_completion) + { + return (0 != wait_for_completion_timeout(fw_load_completion, msecs_to_jiffies(FIRMWARE_WAIT_TIMEOUT_MS))); + } + +-static int hailo_load_firmware(struct hailo_pcie_resources *resources, ++static int hailo_load_soc_firmware(struct hailo_pcie_resources *resources, + struct device *dev, struct completion *fw_load_completion) + { +- const struct firmware *firmware = NULL; +- int err = 0; + u32 boot_status = 0; ++ int err = 0; ++ u32 second_stage = force_boot_linux_from_eemc ? SECOND_STAGE_LINUX_IN_EMMC : SECOND_STAGE; + + if (hailo_pcie_is_firmware_loaded(resources)) { +- hailo_dev_warn(dev, "Firmware was already loaded\n"); ++ hailo_dev_warn(dev, "Firmware batch was already loaded\n"); + return 0; + } + +- reinit_completion(fw_load_completion); +- +- err = hailo_write_config(resources, dev, hailo_pcie_get_board_config_constants(resources->board_type)); +- if (err < 0) { +- hailo_dev_err(dev, "Failed writing board config"); +- return err; +- } ++ init_completion(fw_load_completion); + +- err = hailo_write_config(resources, dev, hailo_pcie_get_user_config_constants(resources->board_type)); ++ err = hailo_pcie_write_firmware_batch(dev, resources, FIRST_STAGE); + if (err < 0) { +- hailo_dev_err(dev, "Failed writing fw config"); ++ hailo_dev_err(dev, "Failed writing firmware files. err %d\n", err); + return err; + } + +- // read firmware file +- err = request_firmware_direct(&firmware, hailo_pcie_get_fw_filename(resources->board_type), dev); +- if (err < 0) { +- hailo_dev_warn(dev, "Firmware file not found (/lib/firmware/%s), please upload the firmware manually \n", +- hailo_pcie_get_fw_filename(resources->board_type)); +- return 0; ++ if (!wait_for_firmware_completion(fw_load_completion)) { ++ boot_status = hailo_get_boot_status(resources); ++ hailo_dev_err(dev, "Timeout waiting for firmware file, boot status %u\n", boot_status); ++ return -ETIMEDOUT; + } ++ reinit_completion(fw_load_completion); + +- err = hailo_pcie_write_firmware(resources, firmware->data, firmware->size); ++ err = hailo_pcie_write_firmware_batch(dev, resources, second_stage); + if (err < 0) { +- hailo_dev_err(dev, "Failed writing firmware. err %d\n", err); +- release_firmware(firmware); ++ hailo_dev_err(dev, "Failed writing firmware files. err %d\n", err); + return err; + } + +- release_firmware(firmware); +- + if (!wait_for_firmware_completion(fw_load_completion)) { + boot_status = hailo_get_boot_status(resources); + hailo_dev_err(dev, "Timeout waiting for firmware file, boot status %u\n", boot_status); + return -ETIMEDOUT; + } + +- hailo_dev_notice(dev, "Firmware was loaded successfully\n"); ++ hailo_dev_notice(dev, "Firmware Batch loaded successfully\n"); ++ + return 0; + } + +-static int hailo_load_firmware_batch(struct hailo_pcie_resources *resources, ++static int hailo_load_nnc_firmware(struct hailo_pcie_resources *resources, + struct device *dev, struct completion *fw_load_completion) + { + u32 boot_status = 0; +- u32 pcie_finished = 1; + int err = 0; + + if (hailo_pcie_is_firmware_loaded(resources)) { +@@ -398,31 +359,13 @@ static int hailo_load_firmware_batch(str + return err; + } + +- hailo_trigger_firmware_boot(resources); +- + if (!wait_for_firmware_completion(fw_load_completion)) { + boot_status = hailo_get_boot_status(resources); + hailo_dev_err(dev, "Timeout waiting for firmware file, boot status %u\n", boot_status); + return -ETIMEDOUT; + } +- reinit_completion(fw_load_completion); + +- err = hailo_pcie_write_firmware_batch(dev, resources, SECOND_STAGE); +- if (err < 0) { +- hailo_dev_err(dev, "Failed writing firmware files. err %d\n", err); +- return err; +- } +- +- // TODO: HRT-13838 - Remove, move address to compat, make write_memory static +- write_memory(resources, 0x84000000, (void*)&pcie_finished, sizeof(pcie_finished)); +- +- if (!wait_for_firmware_completion(fw_load_completion)) { +- boot_status = hailo_get_boot_status(resources); +- hailo_dev_err(dev, "Timeout waiting for firmware file, boot status %u\n", boot_status); +- return -ETIMEDOUT; +- } +- +- hailo_dev_notice(dev, "Firmware Batch loaded successfully\n"); ++ hailo_dev_notice(dev, "Firmware loaded successfully\n"); + + return 0; + } +@@ -439,15 +382,13 @@ static int hailo_activate_board(struct h + return err; + } + +- switch (board->pcie_resources.board_type) { +- case HAILO_BOARD_TYPE_HAILO10H: +- err = hailo_load_firmware_batch(&board->pcie_resources, &board->pDev->dev, ++ switch (board->pcie_resources.accelerator_type) { ++ case HAILO_ACCELERATOR_TYPE_SOC: ++ err = hailo_load_soc_firmware(&board->pcie_resources, &board->pDev->dev, + &board->fw_loaded_completion); + break; +- case HAILO_BOARD_TYPE_HAILO10H_LEGACY: +- case HAILO_BOARD_TYPE_PLUTO: +- case HAILO_BOARD_TYPE_HAILO8: +- err = hailo_load_firmware(&board->pcie_resources, &board->pDev->dev, ++ case HAILO_ACCELERATOR_TYPE_NNC: ++ err = hailo_load_nnc_firmware(&board->pcie_resources, &board->pDev->dev, + &board->fw_loaded_completion); + break; + default: +@@ -464,6 +405,7 @@ static int hailo_activate_board(struct h + + if (power_mode_enabled()) { + // Setting the device to low power state, until the user opens the device ++ hailo_info(board, "Power change state to PCI_D3hot\n"); + err = pci_set_power_state(board->pDev, PCI_D3hot); + if (err < 0) { + hailo_err(board, "Set power state failed %d\n", err); +@@ -755,21 +697,17 @@ static int hailo_pcie_probe(struct pci_d + + pBoard->interrupts_enabled = false; + init_completion(&pBoard->fw_loaded_completion); +- init_completion(&pBoard->soc_connect_accepted); + + sema_init(&pBoard->mutex, 1); + atomic_set(&pBoard->ref_count, 0); + INIT_LIST_HEAD(&pBoard->open_files_list); + +- sema_init(&pBoard->fw_control.mutex, 1); +- spin_lock_init(&pBoard->notification_read_spinlock); +- init_completion(&pBoard->fw_control.completion); ++ // Init both soc and nnc, since the interrupts are shared. ++ hailo_nnc_init(&pBoard->nnc); ++ hailo_soc_init(&pBoard->soc); + + init_completion(&pBoard->driver_down.reset_completed); + +- INIT_LIST_HEAD(&pBoard->notification_wait_list); +- +- memset(&pBoard->notification_cache, 0, sizeof(pBoard->notification_cache)); + memset(&pBoard->memory_transfer_params, 0, sizeof(pBoard->memory_transfer_params)); + + err = hailo_pcie_vdma_controller_init(&pBoard->vdma, &pBoard->pDev->dev, +@@ -832,7 +770,6 @@ probe_exit: + static void hailo_pcie_remove(struct pci_dev* pDev) + { + struct hailo_pcie_board* pBoard = (struct hailo_pcie_board*) pci_get_drvdata(pDev); +- struct hailo_notification_wait *cursor = NULL; + + pci_notice(pDev, "Remove: Releasing board\n"); + +@@ -864,13 +801,7 @@ static void hailo_pcie_remove(struct pci + + pci_set_drvdata(pDev, NULL); + +- // Lock rcu_read_lock and send notification_completion to wake anyone waiting on the notification_wait_list when removed +- rcu_read_lock(); +- list_for_each_entry_rcu(cursor, &pBoard->notification_wait_list, notification_wait_list) { +- cursor->is_disabled = true; +- complete(&cursor->notification_completion); +- } +- rcu_read_unlock(); ++ hailo_nnc_finalize(&pBoard->nnc); + + up(&pBoard->mutex); + +@@ -889,6 +820,15 @@ static void hailo_pcie_remove(struct pci + + } + ++inline int driver_down(struct hailo_pcie_board *board) ++{ ++ if (board->pcie_resources.accelerator_type == HAILO_ACCELERATOR_TYPE_NNC) { ++ return hailo_nnc_driver_down(board); ++ } else { ++ return hailo_soc_driver_down(board); ++ } ++} ++ + #ifdef CONFIG_PM_SLEEP + static int hailo_pcie_suspend(struct device *dev) + { +@@ -899,17 +839,16 @@ static int hailo_pcie_suspend(struct dev + // lock board to wait for any pending operations + down(&board->mutex); + +- // Disable all interrupts. All interrupts from Hailo chip would be masked. +- hailo_disable_interrupts(board); +- +- // Close all vDMA channels + if (board->vdma.used_by_filp != NULL) { +- err = hailo_pcie_driver_down(board); ++ err = driver_down(board); + if (err < 0) { + dev_notice(dev, "Error while trying to call FW to close vdma channels\n"); + } + } + ++ // Disable all interrupts. All interrupts from Hailo chip would be masked. ++ hailo_disable_interrupts(board); ++ + // Un validate all activae file contexts so every new action would return error to the user. + list_for_each_entry(cur, &board->open_files_list, open_files_list) { + cur->is_valid = false; +@@ -919,8 +858,8 @@ static int hailo_pcie_suspend(struct dev + up(&board->mutex); + + dev_notice(dev, "PM's suspend\n"); +- // Continue system suspend +- return err; ++ // Success Oriented - Continue system suspend even in case of error (otherwise system will not suspend correctly) ++ return 0; + } + + static int hailo_pcie_resume(struct device *dev) +@@ -930,10 +869,10 @@ static int hailo_pcie_resume(struct devi + + if ((err = hailo_activate_board(board)) < 0) { + dev_err(dev, "Failed activating board %d\n", err); +- return err; + } + + dev_notice(dev, "PM's resume\n"); ++ // Success Oriented - Continue system resume even in case of error (otherwise system will not suspend correctly) + return 0; + } + #endif /* CONFIG_PM_SLEEP */ +@@ -954,7 +893,7 @@ static void hailo_pci_reset_prepare(stru + down(&board->mutex); + if (board->vdma.used_by_filp != NULL) { + // Try to close all vDMA channels before reset +- err = hailo_pcie_driver_down(board); ++ err = driver_down(board); + if (err < 0) { + pci_err(pdev, "Error while trying to call FW to close vdma channels (errno %d)\n", err); + } +@@ -1088,6 +1027,9 @@ MODULE_PARM_DESC(force_desc_page_size, " + module_param(force_hailo15_legacy_mode, bool, S_IRUGO); + MODULE_PARM_DESC(force_hailo15_legacy_mode, "Forces work with Hailo15 in legacy mode(relevant for emulators)"); + ++module_param(force_boot_linux_from_eemc, bool, S_IRUGO); ++MODULE_PARM_DESC(force_boot_linux_from_eemc, "Boot the linux image from eemc (Requires special Image)"); ++ + MODULE_AUTHOR("Hailo Technologies Ltd."); + MODULE_DESCRIPTION("Hailo PCIe driver"); + MODULE_LICENSE("GPL v2"); +--- a/drivers/media/pci/hailo/src/pcie.h ++++ b/drivers/media/pci/hailo/src/pcie.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _HAILO_PCI_PCIE_H_ +@@ -41,6 +41,19 @@ struct hailo_fw_boot { + }; + + ++struct hailo_pcie_nnc { ++ struct hailo_fw_control_info fw_control; ++ ++ spinlock_t notification_read_spinlock; ++ struct list_head notification_wait_list; ++ struct hailo_d2h_notification notification_cache; ++ struct hailo_d2h_notification notification_to_user; ++}; ++ ++struct hailo_pcie_soc { ++ struct completion control_resp_ready; ++}; ++ + // Context for each open file handle + // TODO: store board and use as actual context + struct hailo_file_context { +@@ -48,6 +61,7 @@ struct hailo_file_context { + struct file *filp; + struct hailo_vdma_file_context vdma_context; + bool is_valid; ++ u32 soc_used_channels_bitmap; + }; + + struct hailo_pcie_board { +@@ -57,21 +71,17 @@ struct hailo_pcie_board { + atomic_t ref_count; + struct list_head open_files_list; + struct hailo_pcie_resources pcie_resources; +- struct hailo_fw_control_info fw_control; ++ struct hailo_pcie_nnc nnc; ++ struct hailo_pcie_soc soc; + struct hailo_pcie_driver_down_info driver_down; + struct semaphore mutex; + struct hailo_vdma_controller vdma; +- spinlock_t notification_read_spinlock; +- struct list_head notification_wait_list; +- struct hailo_d2h_notification notification_cache; +- struct hailo_d2h_notification notification_to_user; ++ + struct hailo_memory_transfer_params memory_transfer_params; + u32 desc_max_page_size; + enum hailo_allocation_mode allocation_mode; + struct completion fw_loaded_completion; + bool interrupts_enabled; +- // Only needed in accelerator type soc +- struct completion soc_connect_accepted; + }; + + bool power_mode_enabled(void); +--- /dev/null ++++ b/drivers/media/pci/hailo/src/soc.c +@@ -0,0 +1,244 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/** ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. ++ **/ ++/** ++ * A Hailo PCIe NNC device is a device contains a full SoC over PCIe. The SoC contains NNC (neural network core) and ++ * some application processor (pci_ep). ++ */ ++ ++#include "soc.h" ++ ++#include "vdma_common.h" ++#include "utils/logs.h" ++#include "vdma/memory.h" ++ ++#include ++ ++#define PCI_SOC_VDMA_ENGINE_INDEX (0) ++#define PCI_SOC_CONTROL_CONNECT_TIMEOUT_MS (1000) ++#define PCI_SOC_INPUT_CHANNEL_BITMASK (0x000000FF) ++ ++void hailo_soc_init(struct hailo_pcie_soc *soc) ++{ ++ init_completion(&soc->control_resp_ready); ++} ++ ++long hailo_soc_ioctl(struct hailo_pcie_board *board, struct hailo_file_context *context, ++ struct hailo_vdma_controller *controller, unsigned int cmd, unsigned long arg) ++{ ++ switch (cmd) { ++ case HAILO_SOC_CONNECT: ++ return hailo_soc_connect_ioctl(board, context, controller, arg); ++ case HAILO_SOC_CLOSE: ++ return hailo_soc_close_ioctl(board, controller, context, arg); ++ default: ++ hailo_err(board, "Invalid pcie EP ioctl code 0x%x (nr: %d)\n", cmd, _IOC_NR(cmd)); ++ return -ENOTTY; ++ } ++} ++ ++static int soc_control(struct hailo_pcie_board *board, ++ const struct hailo_pcie_soc_request *request, ++ struct hailo_pcie_soc_response *response) ++{ ++ int ret = 0; ++ reinit_completion(&board->soc.control_resp_ready); ++ ++ hailo_pcie_soc_write_request(&board->pcie_resources, request); ++ ++ ret = wait_for_completion_interruptible_timeout(&board->soc.control_resp_ready, ++ msecs_to_jiffies(PCI_SOC_CONTROL_CONNECT_TIMEOUT_MS)); ++ if (ret <= 0) { ++ if (0 == ret) { ++ hailo_err(board, "Timeout waiting for soc control (timeout_ms=%d)\n", PCI_SOC_CONTROL_CONNECT_TIMEOUT_MS); ++ return -ETIMEDOUT; ++ } else { ++ hailo_info(board, "soc control failed with err=%d (process was interrupted or killed)\n", ++ ret); ++ return ret; ++ } ++ } ++ ++ hailo_pcie_soc_read_response(&board->pcie_resources, response); ++ ++ if (response->status < 0) { ++ hailo_err(board, "soc control failed with status=%d\n", response->status); ++ return response->status; ++ } ++ ++ if (response->control_code != request->control_code) { ++ hailo_err(board, "Invalid response control code %d (expected %d)\n", ++ response->control_code, request->control_code); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++long hailo_soc_connect_ioctl(struct hailo_pcie_board *board, struct hailo_file_context *context, ++ struct hailo_vdma_controller *controller, unsigned long arg) ++{ ++ struct hailo_pcie_soc_request request = {0}; ++ struct hailo_pcie_soc_response response = {0}; ++ struct hailo_soc_connect_params params; ++ struct hailo_vdma_channel *input_channel = NULL; ++ struct hailo_vdma_channel *output_channel = NULL; ++ struct hailo_vdma_engine *vdma_engine = &controller->vdma_engines[PCI_SOC_VDMA_ENGINE_INDEX]; ++ struct hailo_descriptors_list_buffer *input_descriptors_buffer = NULL; ++ struct hailo_descriptors_list_buffer *output_descriptors_buffer = NULL; ++ uint8_t depth = 0; ++ int err = 0; ++ ++ if (copy_from_user(¶ms, (void *)arg, sizeof(params))) { ++ hailo_err(board, "copy_from_user fail\n"); ++ return -ENOMEM; ++ } ++ ++ request = (struct hailo_pcie_soc_request) { ++ .control_code = HAILO_PCIE_SOC_CONTROL_CODE_CONNECT, ++ .connect = { ++ .port = params.port_number ++ } ++ }; ++ err = soc_control(board, &request, &response); ++ if (err < 0) { ++ return err; ++ } ++ ++ params.input_channel_index = response.connect.input_channel_index; ++ params.output_channel_index = response.connect.output_channel_index; ++ ++ if (!hailo_check_channel_index(params.input_channel_index, controller->hw->src_channels_bitmask, true)) { ++ hailo_dev_err(&board->pDev->dev, "Invalid input channel index %u\n", params.input_channel_index); ++ return -EINVAL; ++ } ++ ++ if (!hailo_check_channel_index(params.output_channel_index, controller->hw->src_channels_bitmask, false)) { ++ hailo_dev_err(&board->pDev->dev, "Invalid output channel index %u\n", params.output_channel_index); ++ return -EINVAL; ++ } ++ ++ input_channel = &vdma_engine->channels[params.input_channel_index]; ++ output_channel = &vdma_engine->channels[params.output_channel_index]; ++ ++ input_descriptors_buffer = hailo_vdma_find_descriptors_buffer(&context->vdma_context, params.input_desc_handle); ++ output_descriptors_buffer = hailo_vdma_find_descriptors_buffer(&context->vdma_context, params.output_desc_handle); ++ if (NULL == input_descriptors_buffer || NULL == output_descriptors_buffer) { ++ hailo_dev_err(&board->pDev->dev, "input / output descriptors buffer not found \n"); ++ return -EINVAL; ++ } ++ ++ if (!is_powerof2((size_t)input_descriptors_buffer->desc_list.desc_count) || ++ !is_powerof2((size_t)output_descriptors_buffer->desc_list.desc_count)) { ++ hailo_dev_err(&board->pDev->dev, "Invalid desc list size\n"); ++ return -EINVAL; ++ } ++ ++ // configure and start input channel ++ depth = ceil_log2(input_descriptors_buffer->desc_list.desc_count); ++ // DMA Direction is only to get channel index - so ++ err = hailo_vdma_start_channel(input_channel->host_regs, input_descriptors_buffer->dma_address, depth, ++ board->vdma.hw->ddr_data_id); ++ if (err < 0) { ++ hailo_dev_err(&board->pDev->dev, "Error starting vdma input channel index %u\n", params.input_channel_index); ++ return -EINVAL; ++ } ++ ++ // Store the input channels state in bitmap (open) ++ hailo_set_bit(params.input_channel_index, &context->soc_used_channels_bitmap); ++ ++ // configure and start output channel ++ depth = ceil_log2(output_descriptors_buffer->desc_list.desc_count); ++ // DMA Direction is only to get channel index - so ++ err = hailo_vdma_start_channel(output_channel->host_regs, output_descriptors_buffer->dma_address, depth, ++ board->vdma.hw->ddr_data_id); ++ if (err < 0) { ++ hailo_dev_err(&board->pDev->dev, "Error starting vdma output channel index %u\n", params.output_channel_index); ++ // Close input channel ++ hailo_vdma_stop_channel(input_channel->host_regs); ++ return -EINVAL; ++ } ++ ++ // Store the output channels state in bitmap (open) ++ hailo_set_bit(params.output_channel_index, &context->soc_used_channels_bitmap); ++ ++ if (copy_to_user((void *)arg, ¶ms, sizeof(params))) { ++ hailo_dev_err(&board->pDev->dev, "copy_to_user fail\n"); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static int close_channels(struct hailo_pcie_board *board, u32 channels_bitmap) ++{ ++ struct hailo_pcie_soc_request request = {0}; ++ struct hailo_pcie_soc_response response = {0}; ++ struct hailo_vdma_engine *engine = &board->vdma.vdma_engines[PCI_SOC_VDMA_ENGINE_INDEX]; ++ struct hailo_vdma_channel *channel = NULL; ++ u8 channel_index = 0; ++ ++ hailo_info(board, "Closing channels bitmap 0x%x\n", channels_bitmap); ++ for_each_vdma_channel(engine, channel, channel_index) { ++ if (hailo_test_bit(channel_index, &channels_bitmap)) { ++ hailo_vdma_stop_channel(channel->host_regs); ++ } ++ } ++ ++ request = (struct hailo_pcie_soc_request) { ++ .control_code = HAILO_PCIE_SOC_CONTROL_CODE_CLOSE, ++ .close = { ++ .channels_bitmap = channels_bitmap ++ } ++ }; ++ return soc_control(board, &request, &response); ++} ++ ++long hailo_soc_close_ioctl(struct hailo_pcie_board *board, struct hailo_vdma_controller *controller, ++ struct hailo_file_context *context, unsigned long arg) ++{ ++ struct hailo_soc_close_params params; ++ u32 channels_bitmap = 0; ++ int err = 0; ++ ++ if (copy_from_user(¶ms, (void *)arg, sizeof(params))) { ++ hailo_dev_err(&board->pDev->dev, "copy_from_user fail\n"); ++ return -ENOMEM; ++ } ++ ++ // TOOD: check channels are connected ++ ++ channels_bitmap = (1 << params.input_channel_index) | (1 << params.output_channel_index); ++ ++ err = close_channels(board, channels_bitmap); ++ if (0 != err) { ++ hailo_dev_err(&board->pDev->dev, "Error closing channels\n"); ++ return err; ++ } ++ ++ // Store the channel state in bitmap (closed) ++ hailo_clear_bit(params.input_channel_index, &context->soc_used_channels_bitmap); ++ hailo_clear_bit(params.output_channel_index, &context->soc_used_channels_bitmap); ++ ++ return err; ++} ++ ++int hailo_soc_file_context_init(struct hailo_pcie_board *board, struct hailo_file_context *context) ++{ ++ // Nothing to init yet ++ return 0; ++} ++ ++void hailo_soc_file_context_finalize(struct hailo_pcie_board *board, struct hailo_file_context *context) ++{ ++ // close only channels connected by this (by bitmap) ++ if (context->soc_used_channels_bitmap != 0) { ++ close_channels(board, context->soc_used_channels_bitmap); ++ } ++} ++ ++int hailo_soc_driver_down(struct hailo_pcie_board *board) ++{ ++ return close_channels(board, 0xFFFFFFFF); ++} +\ No newline at end of file +--- a/drivers/media/pci/hailo/src/pci_soc_ioctl.h ++++ /dev/null +@@ -1,19 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/** +- * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. +- **/ +- +-#ifndef _HAILO_PCI_SOC_IOCTL_H_ +-#define _HAILO_PCI_SOC_IOCTL_H_ +- +-#include "vdma/ioctl.h" +-#include "pcie.h" +- +- +-long hailo_soc_ioctl(struct hailo_pcie_board *board, struct hailo_vdma_file_context *context, +- struct hailo_vdma_controller *controller, unsigned int cmd, unsigned long arg); +-long hailo_soc_connect_ioctl(struct hailo_pcie_board *board, struct hailo_vdma_file_context *context, +- struct hailo_vdma_controller *controller, unsigned long arg); +-long hailo_soc_close_ioctl(struct hailo_pcie_board *board, struct hailo_vdma_controller *controller, unsigned long arg); +- +-#endif // _HAILO_PCI_SOC_IOCTL_H_ +\ No newline at end of file +--- /dev/null ++++ b/drivers/media/pci/hailo/src/soc.h +@@ -0,0 +1,26 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/** ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. ++ **/ ++ ++#ifndef _HAILO_PCI_SOC_IOCTL_H_ ++#define _HAILO_PCI_SOC_IOCTL_H_ ++ ++#include "vdma/ioctl.h" ++#include "pcie.h" ++ ++ ++void hailo_soc_init(struct hailo_pcie_soc *soc); ++ ++long hailo_soc_ioctl(struct hailo_pcie_board *board, struct hailo_file_context *context, ++ struct hailo_vdma_controller *controller, unsigned int cmd, unsigned long arg); ++long hailo_soc_connect_ioctl(struct hailo_pcie_board *board, struct hailo_file_context *context, ++ struct hailo_vdma_controller *controller, unsigned long arg); ++long hailo_soc_close_ioctl(struct hailo_pcie_board *board, struct hailo_vdma_controller *controller, struct hailo_file_context *context, unsigned long arg); ++ ++int hailo_soc_file_context_init(struct hailo_pcie_board *board, struct hailo_file_context *context); ++void hailo_soc_file_context_finalize(struct hailo_pcie_board *board, struct hailo_file_context *context); ++ ++int hailo_soc_driver_down(struct hailo_pcie_board *board); ++ ++#endif // _HAILO_PCI_SOC_IOCTL_H_ +\ No newline at end of file +--- a/drivers/media/pci/hailo/src/sysfs.c ++++ b/drivers/media/pci/hailo/src/sysfs.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #include "sysfs.h" +--- a/drivers/media/pci/hailo/src/sysfs.h ++++ b/drivers/media/pci/hailo/src/sysfs.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _HAILO_PCI_SYSFS_H_ +--- a/drivers/media/pci/hailo/src/utils.c ++++ /dev/null +@@ -1,26 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. +- **/ +- +-#include +-#include +-#include +-#include +- +-#include "pcie.h" +-#include "utils.h" +-#include "utils/logs.h" +- +- +-void hailo_pcie_clear_notification_wait_list(struct hailo_pcie_board *pBoard, struct file *filp) +-{ +- struct hailo_notification_wait *cur = NULL, *next = NULL; +- list_for_each_entry_safe(cur, next, &pBoard->notification_wait_list, notification_wait_list) { +- if (cur->filp == filp) { +- list_del_rcu(&cur->notification_wait_list); +- synchronize_rcu(); +- kfree(cur); +- } +- } +-} +--- a/drivers/media/pci/hailo/utils/compact.h ++++ b/drivers/media/pci/hailo/utils/compact.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _HAILO_PCI_COMPACT_H_ +--- a/drivers/media/pci/hailo/utils/fw_common.h ++++ b/drivers/media/pci/hailo/utils/fw_common.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _HAILO_LINUX_COMMON_H_ +--- a/drivers/media/pci/hailo/utils/integrated_nnc_utils.c ++++ b/drivers/media/pci/hailo/utils/integrated_nnc_utils.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #include "integrated_nnc_utils.h" +@@ -43,11 +43,19 @@ int hailo_ioremap_shmem(struct platform_ + void __iomem * remap_ptr; + + shmem = of_parse_phandle(pdev->dev.of_node, "shmem", index); ++ if (!shmem) { ++ hailo_dev_err(&pdev->dev, "Failed to find shmem node index: %d in device tree\n", index); ++ return -ENODEV; ++ } ++ + ret = of_address_to_resource(shmem, 0, &res); + if (ret) { + hailo_dev_err(&pdev->dev, "hailo_ioremap_shmem, failed to get memory (index: %d)\n", index); ++ of_node_put(shmem); + return ret; + } ++ ++ // Decrement the refcount of the node + of_node_put(shmem); + + remap_ptr = devm_ioremap(&pdev->dev, res.start, resource_size(&res)); +--- a/drivers/media/pci/hailo/utils/integrated_nnc_utils.h ++++ b/drivers/media/pci/hailo/utils/integrated_nnc_utils.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _INTEGRATED_NNC_UTILS_H_ +--- a/drivers/media/pci/hailo/utils/logs.c ++++ b/drivers/media/pci/hailo/utils/logs.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #include "logs.h" +--- a/drivers/media/pci/hailo/utils/logs.h ++++ b/drivers/media/pci/hailo/utils/logs.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _COMMON_LOGS_H_ +--- a/drivers/media/pci/hailo/vdma/ioctl.c ++++ b/drivers/media/pci/hailo/vdma/ioctl.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #include "ioctl.h" +@@ -12,7 +12,7 @@ + #include + + +-long hailo_vdma_enable_channels_ioctl(struct hailo_vdma_controller *controller, unsigned long arg) ++long hailo_vdma_enable_channels_ioctl(struct hailo_vdma_controller *controller, unsigned long arg, struct hailo_vdma_file_context *context) + { + struct hailo_vdma_enable_channels_params input; + struct hailo_vdma_engine *engine = NULL; +@@ -40,12 +40,15 @@ long hailo_vdma_enable_channels_ioctl(st + hailo_vdma_update_interrupts_mask(controller, engine_index); + hailo_dev_info(controller->dev, "Enabled interrupts for engine %u, channels bitmap 0x%x\n", + engine_index, channels_bitmap); ++ ++ // Update the context with the enabled channels bitmap ++ context->enabled_channels_bitmap[engine_index] |= channels_bitmap; + } + + return 0; + } + +-long hailo_vdma_disable_channels_ioctl(struct hailo_vdma_controller *controller, unsigned long arg) ++long hailo_vdma_disable_channels_ioctl(struct hailo_vdma_controller *controller, unsigned long arg, struct hailo_vdma_file_context *context) + { + struct hailo_vdma_disable_channels_params input; + struct hailo_vdma_engine *engine = NULL; +@@ -77,6 +80,9 @@ long hailo_vdma_disable_channels_ioctl(s + + hailo_dev_info(controller->dev, "Disabled channels for engine %u, bitmap 0x%x\n", + engine_index, channels_bitmap); ++ ++ // Update the context with the disabled channels bitmap ++ context->enabled_channels_bitmap[engine_index] &= ~channels_bitmap; + } + + // Wake up threads waiting +@@ -204,7 +210,7 @@ long hailo_vdma_buffer_map_ioctl(struct + return -EFAULT; + } + +- hailo_dev_info(controller->dev, "address %lx tgid %d size: %zu\n", ++ hailo_dev_dbg(controller->dev, "address %lx tgid %d size: %zu\n", + buf_info.user_address, current->tgid, buf_info.size); + + direction = get_dma_direction(buf_info.data_direction); +@@ -231,7 +237,7 @@ long hailo_vdma_buffer_map_ioctl(struct + } + + list_add(&mapped_buffer->mapped_user_buffer_list, &context->mapped_user_buffer_list); +- hailo_dev_info(controller->dev, "buffer %lx (handle %zu) is mapped\n", ++ hailo_dev_dbg(controller->dev, "buffer %lx (handle %zu) is mapped\n", + buf_info.user_address, buf_info.mapped_handle); + return 0; + } +@@ -247,7 +253,7 @@ long hailo_vdma_buffer_unmap_ioctl(struc + return -EFAULT; + } + +- hailo_dev_info(controller->dev, "unmap user buffer handle %zu\n", buffer_unmap_params.mapped_handle); ++ hailo_dev_dbg(controller->dev, "unmap user buffer handle %zu\n", buffer_unmap_params.mapped_handle); + + mapped_buffer = hailo_vdma_find_mapped_user_buffer(context, buffer_unmap_params.mapped_handle); + if (mapped_buffer == NULL) { +--- a/drivers/media/pci/hailo/vdma/ioctl.h ++++ b/drivers/media/pci/hailo/vdma/ioctl.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #ifndef _HAILO_VDMA_IOCTL_H_ +@@ -8,8 +8,8 @@ + + #include "vdma/vdma.h" + +-long hailo_vdma_enable_channels_ioctl(struct hailo_vdma_controller *controller, unsigned long arg); +-long hailo_vdma_disable_channels_ioctl(struct hailo_vdma_controller *controller, unsigned long arg); ++long hailo_vdma_enable_channels_ioctl(struct hailo_vdma_controller *controller, unsigned long arg, struct hailo_vdma_file_context *context); ++long hailo_vdma_disable_channels_ioctl(struct hailo_vdma_controller *controller, unsigned long arg, struct hailo_vdma_file_context *context); + long hailo_vdma_interrupts_wait_ioctl(struct hailo_vdma_controller *controller, unsigned long arg, + struct semaphore *mutex, bool *should_up_board_mutex); + +--- a/drivers/media/pci/hailo/vdma/memory.c ++++ b/drivers/media/pci/hailo/vdma/memory.c +@@ -1,11 +1,12 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #define pr_fmt(fmt) "hailo: " fmt + + #include "memory.h" ++#include "utils.h" + #include "utils/compact.h" + + #include +@@ -316,6 +317,11 @@ int hailo_desc_list_create(struct device + size_t buffer_size = 0; + const u64 align = VDMA_DESCRIPTOR_LIST_ALIGN; //First addr must be aligned on 64 KB (from the VDMA registers documentation) + ++ if (MAX_POWER_OF_2_VALUE < descriptors_count) { ++ dev_err(dev, "Invalid descriptors count %u\n", descriptors_count); ++ return -EINVAL; ++ } ++ + buffer_size = descriptors_count * sizeof(struct hailo_vdma_descriptor); + buffer_size = ALIGN(buffer_size, align); + +@@ -323,7 +329,7 @@ int hailo_desc_list_create(struct device + &descriptors->dma_address, GFP_KERNEL | __GFP_ZERO); + if (descriptors->kernel_address == NULL) { + dev_err(dev, "Failed to allocate descriptors list, desc_count 0x%x, buffer_size 0x%zx, This failure means there is not a sufficient amount of CMA memory " +- "(contiguous physical memory), This usually is caused by lack of general system memory. Please check you have sufficent memory.\n", ++ "(contiguous physical memory), This usually is caused by lack of general system memory. Please check you have sufficient memory.\n", + descriptors_count, buffer_size); + return -ENOMEM; + } +@@ -333,6 +339,8 @@ int hailo_desc_list_create(struct device + + descriptors->desc_list.desc_list = descriptors->kernel_address; + descriptors->desc_list.desc_count = descriptors_count; ++ // No need to check the return value of get_nearest_powerof_2 because we already checked the input ++ descriptors->desc_list.desc_count_mask = is_circular ? (descriptors_count - 1) : (get_nearest_powerof_2(descriptors_count) - 1); + descriptors->desc_list.desc_page_size = desc_page_size; + descriptors->desc_list.is_circular = is_circular; + +--- a/drivers/media/pci/hailo/vdma/memory.h ++++ b/drivers/media/pci/hailo/vdma/memory.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + /** + * vDMA memory utility (including allocation and mappings) +--- a/drivers/media/pci/hailo/vdma/vdma.c ++++ b/drivers/media/pci/hailo/vdma/vdma.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + + #define pr_fmt(fmt) "hailo: " fmt +@@ -105,6 +105,9 @@ void hailo_vdma_file_context_init(struct + INIT_LIST_HEAD(&context->descriptors_buffer_list); + INIT_LIST_HEAD(&context->vdma_low_memory_buffer_list); + INIT_LIST_HEAD(&context->continuous_buffer_list); ++ ++ BUILD_BUG_ON_MSG(MAX_VDMA_CHANNELS_PER_ENGINE > sizeof(context->enabled_channels_bitmap[0]) * BITS_IN_BYTE, ++ "Unexpected amount of VDMA channels per engine"); + } + + void hailo_vdma_update_interrupts_mask(struct hailo_vdma_controller *controller, +@@ -119,21 +122,22 @@ void hailo_vdma_file_context_finalize(st + { + size_t engine_index = 0; + struct hailo_vdma_engine *engine = NULL; +- const u32 channels_bitmap = 0xFFFFFFFF; // disable all channel interrupts + unsigned long irq_saved_flags = 0; + // In case of FLR, the vdma registers will be NULL + const bool is_device_up = (NULL != controller->dev); + +- if (filp == controller->used_by_filp) { +- for_each_vdma_engine(controller, engine, engine_index) { +- hailo_vdma_engine_disable_channels(engine, channels_bitmap); ++ for_each_vdma_engine(controller, engine, engine_index) { ++ if (context->enabled_channels_bitmap[engine_index]) { ++ hailo_dev_info(controller->dev, "Disabling channels for engine %zu, channels bitmap 0x%x\n", engine_index, ++ context->enabled_channels_bitmap[engine_index]); ++ hailo_vdma_engine_disable_channels(engine, context->enabled_channels_bitmap[engine_index]); + + if (is_device_up) { + hailo_vdma_update_interrupts_mask(controller, engine_index); + } + + spin_lock_irqsave(&controller->interrupts_lock, irq_saved_flags); +- hailo_vdma_engine_clear_channel_interrupts(engine, channels_bitmap); ++ hailo_vdma_engine_clear_channel_interrupts(engine, context->enabled_channels_bitmap[engine_index]); + spin_unlock_irqrestore(&controller->interrupts_lock, irq_saved_flags); + } + } +@@ -148,10 +152,21 @@ void hailo_vdma_file_context_finalize(st + } + } + ++void hailo_vdma_wakeup_interrupts(struct hailo_vdma_controller *controller, struct hailo_vdma_engine *engine, ++ u32 channels_bitmap) ++{ ++ unsigned long irq_saved_flags = 0; ++ ++ spin_lock_irqsave(&controller->interrupts_lock, irq_saved_flags); ++ hailo_vdma_engine_set_channel_interrupts(engine, channels_bitmap); ++ spin_unlock_irqrestore(&controller->interrupts_lock, irq_saved_flags); ++ ++ wake_up_interruptible_all(&controller->interrupts_wq); ++} ++ + void hailo_vdma_irq_handler(struct hailo_vdma_controller *controller, + size_t engine_index, u32 channels_bitmap) + { +- unsigned long irq_saved_flags = 0; + struct hailo_vdma_engine *engine = NULL; + + BUG_ON(engine_index >= controller->vdma_engines_count); +@@ -159,11 +174,7 @@ void hailo_vdma_irq_handler(struct hailo + + hailo_vdma_engine_push_timestamps(engine, channels_bitmap); + +- spin_lock_irqsave(&controller->interrupts_lock, irq_saved_flags); +- hailo_vdma_engine_set_channel_interrupts(engine, channels_bitmap); +- spin_unlock_irqrestore(&controller->interrupts_lock, irq_saved_flags); +- +- wake_up_interruptible_all(&controller->interrupts_wq); ++ hailo_vdma_wakeup_interrupts(controller, engine, channels_bitmap); + } + + long hailo_vdma_ioctl(struct hailo_vdma_file_context *context, struct hailo_vdma_controller *controller, +@@ -171,9 +182,9 @@ long hailo_vdma_ioctl(struct hailo_vdma_ + { + switch (cmd) { + case HAILO_VDMA_ENABLE_CHANNELS: +- return hailo_vdma_enable_channels_ioctl(controller, arg); ++ return hailo_vdma_enable_channels_ioctl(controller, arg, context); + case HAILO_VDMA_DISABLE_CHANNELS: +- return hailo_vdma_disable_channels_ioctl(controller, arg); ++ return hailo_vdma_disable_channels_ioctl(controller, arg, context); + case HAILO_VDMA_INTERRUPTS_WAIT: + return hailo_vdma_interrupts_wait_ioctl(controller, arg, mutex, should_up_board_mutex); + case HAILO_VDMA_INTERRUPTS_READ_TIMESTAMPS: +--- a/drivers/media/pci/hailo/vdma/vdma.h ++++ b/drivers/media/pci/hailo/vdma/vdma.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /** +- * Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved. ++ * Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved. + **/ + /** + * Hailo vdma engine definitions +@@ -130,6 +130,7 @@ struct hailo_vdma_file_context { + struct list_head descriptors_buffer_list; + struct list_head vdma_low_memory_buffer_list; + struct list_head continuous_buffer_list; ++ u32 enabled_channels_bitmap[MAX_VDMA_ENGINES]; + }; + + +@@ -145,6 +146,8 @@ void hailo_vdma_file_context_init(struct + void hailo_vdma_file_context_finalize(struct hailo_vdma_file_context *context, + struct hailo_vdma_controller *controller, struct file *filp); + ++void hailo_vdma_wakeup_interrupts(struct hailo_vdma_controller *controller, struct hailo_vdma_engine *engine, ++ u32 channels_bitmap); + void hailo_vdma_irq_handler(struct hailo_vdma_controller *controller, size_t engine_index, + u32 channels_bitmap); + diff --git a/target/linux/bcm27xx/patches-6.6/950-1398-dtoverlays-enable-SPI-CS-active-high.patch b/target/linux/bcm27xx/patches-6.6/950-1398-dtoverlays-enable-SPI-CS-active-high.patch new file mode 100644 index 0000000000..ecd26a78b8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1398-dtoverlays-enable-SPI-CS-active-high.patch @@ -0,0 +1,108 @@ +From dbf12796d1368286672529d7b03f81066a8c36f3 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 18 Nov 2024 10:55:33 +0100 +Subject: [PATCH] dtoverlays: enable SPI CS active-high + +The documentation isn't very clear explaining how to enable SPI CS +active-high and it takes a long time to understand it. Adding a specific +overlay as a simple example on how to invert this signal can help +understand the solution. + +Link: https://forums.raspberrypi.com/viewtopic.php?t=378222 +Signed-off-by: Iker Pedrosa +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 8 +++ + .../overlays/spi0-1cs-inverted-overlay.dts | 59 +++++++++++++++++++ + 3 files changed, 68 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/spi0-1cs-inverted-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -259,6 +259,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + spi-rtc.dtbo \ + spi0-0cs.dtbo \ + spi0-1cs.dtbo \ ++ spi0-1cs-inverted.dtbo \ + spi0-2cs.dtbo \ + spi1-1cs.dtbo \ + spi1-2cs.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -4438,6 +4438,14 @@ Params: cs0_pin GPIO pin + it for other uses. + + ++Name: spi0-1cs-inverted ++Info: Only use one CS pin for SPI0 and set to active-high ++Load: dtoverlay=spi0-1cs-inverted,= ++Params: cs0_pin GPIO pin for CS0 (default 8) ++ no_miso Don't claim and use the MISO pin (9), freeing ++ it for other uses. ++ ++ + Name: spi0-2cs + Info: Change the CS pins for SPI0 + Load: dtoverlay=spi0-2cs,= +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi0-1cs-inverted-overlay.dts +@@ -0,0 +1,59 @@ ++/dts-v1/; ++/plugin/; ++ ++/* ++ * There are some devices that need an inverted Chip Select (CS) to select the ++ * device signal, as an example the AZDelivery 12864 display. That means that ++ * the CS polarity is active-high. To invert the CS signal the DT needs to set ++ * the cs-gpio to GPIO_ACTIVE_HIGH (0) in the controller and set the ++ * spi-cs-high in the peripheral property. On top of that, since this is a ++ * display the DT also needs to specify the write-only property. ++*/ ++ ++#include ++ ++/ { ++ compatible = "brcm,bcm2835"; ++ ++ fragment@0 { ++ target = <&spi0_cs_pins>; ++ frag0: __overlay__ { ++ brcm,pins = <8>; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi0>; ++ frag1: __overlay__ { ++ cs-gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spidev1>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&spi0_pins>; ++ __dormant__ { ++ brcm,pins = <10 11>; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&spidev0>; ++ __overlay__ { ++ spi-cs-high; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag0>,"brcm,pins:0", ++ <&frag1>,"cs-gpios:4"; ++ no_miso = <0>,"=3"; ++ }; ++}; diff --git a/target/linux/bcm27xx/patches-6.6/950-1399-drm-vc4-hvs-Defer-updating-the-enable_bg_fill-until-.patch b/target/linux/bcm27xx/patches-6.6/950-1399-drm-vc4-hvs-Defer-updating-the-enable_bg_fill-until-.patch new file mode 100644 index 0000000000..8f8af00c9f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1399-drm-vc4-hvs-Defer-updating-the-enable_bg_fill-until-.patch @@ -0,0 +1,64 @@ +From 57b528e557890f25e010b6bc7356b5a716c79db2 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 12 Nov 2024 17:58:52 +0000 +Subject: [PATCH] drm/vc4: hvs: Defer updating the enable_bg_fill until vblank + +The register to enable/disable background fill was being set +from atomic flush, however that will be applied immediately and +can be a while before the vblank. If it was required for the +current frame but not for the next one, that can result in +corruption for part of the current frame. + +Store the state in vc4_hvs, and update it on vblank. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_drv.h | 2 ++ + drivers/gpu/drm/vc4/vc4_hvs.c | 18 ++++++++++-------- + 2 files changed, 12 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -339,6 +339,8 @@ struct vc4_hvs { + unsigned int enabled: 1; + } eof_irq[HVS_NUM_CHANNELS]; + ++ bool bg_fill[HVS_NUM_CHANNELS]; ++ + unsigned long max_core_rate; + + /* Memory manager for CRTCs to allocate space in the display +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1470,14 +1470,7 @@ void vc4_hvs_atomic_flush(struct drm_crt + /* This sets a black background color fill, as is the case + * with other DRM drivers. + */ +- if (enable_bg_fill) +- HVS_WRITE(SCALER6_DISPX_CTRL1(channel), +- HVS_READ(SCALER6_DISPX_CTRL1(channel)) | +- SCALER6(DISPX_CTRL1_BGENB)); +- else +- HVS_WRITE(SCALER6_DISPX_CTRL1(channel), +- HVS_READ(SCALER6_DISPX_CTRL1(channel)) & +- ~SCALER6(DISPX_CTRL1_BGENB)); ++ hvs->bg_fill[channel] = enable_bg_fill; + } else { + /* we can actually run with a lower core clock when background + * fill is enabled on VC4_GEN_5 so leave it enabled always. +@@ -1662,6 +1655,15 @@ static irqreturn_t vc6_hvs_eof_irq_handl + if (hvs->eof_irq[i].desc != irq) + continue; + ++ if (hvs->bg_fill[i]) ++ HVS_WRITE(SCALER6_DISPX_CTRL1(i), ++ HVS_READ(SCALER6_DISPX_CTRL1(i)) | ++ SCALER6(DISPX_CTRL1_BGENB)); ++ else ++ HVS_WRITE(SCALER6_DISPX_CTRL1(i), ++ HVS_READ(SCALER6_DISPX_CTRL1(i)) & ++ ~SCALER6(DISPX_CTRL1_BGENB)); ++ + vc4_hvs_schedule_dlist_sweep(hvs, i); + return IRQ_HANDLED; + } diff --git a/target/linux/bcm27xx/patches-6.6/950-1359-misc-rp1-pio-Add-FIFO.patch b/target/linux/bcm27xx/patches-6.6/950-1400-misc-rp1-pio-Add-FIFO-related-methods.patch similarity index 98% rename from target/linux/bcm27xx/patches-6.6/950-1359-misc-rp1-pio-Add-FIFO.patch rename to target/linux/bcm27xx/patches-6.6/950-1400-misc-rp1-pio-Add-FIFO-related-methods.patch index fff033f5a6..da21526c21 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1359-misc-rp1-pio-Add-FIFO.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1400-misc-rp1-pio-Add-FIFO-related-methods.patch @@ -27,7 +27,7 @@ Signed-off-by: Phil Elwell --- a/drivers/misc/rp1-pio.c +++ b/drivers/misc/rp1-pio.c -@@ -479,6 +479,28 @@ int rp1_pio_sm_set_dmactrl(struct rp1_pi +@@ -476,6 +476,28 @@ int rp1_pio_sm_set_dmactrl(struct rp1_pi } EXPORT_SYMBOL_GPL(rp1_pio_sm_set_dmactrl); @@ -56,7 +56,7 @@ Signed-off-by: Phil Elwell int rp1_pio_gpio_init(struct rp1_pio_client *client, void *param) { struct rp1_gpio_init_args *args = param; -@@ -851,6 +873,8 @@ struct handler_info { +@@ -848,6 +870,8 @@ struct handler_info { HANDLER(SM_PUT, sm_put), HANDLER(SM_GET, sm_get), HANDLER(SM_SET_DMACTRL, sm_set_dmactrl), diff --git a/target/linux/bcm27xx/patches-6.6/950-1401-overlays-Enable-Raspberry-Touch-2-rotation-with-over.patch b/target/linux/bcm27xx/patches-6.6/950-1401-overlays-Enable-Raspberry-Touch-2-rotation-with-over.patch new file mode 100644 index 0000000000..1a709577eb --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1401-overlays-Enable-Raspberry-Touch-2-rotation-with-over.patch @@ -0,0 +1,31 @@ +From fa6ad4bcad4e8db18493a4af640b4b5c95434e70 Mon Sep 17 00:00:00 2001 +From: Just a nerd <157698061+foonerd@users.noreply.github.com> +Date: Wed, 20 Nov 2024 14:08:48 +0000 +Subject: [PATCH] overlays: Enable Raspberry Touch 2 rotation with overlay + +See: https://github.com/raspberrypi/linux/pull/6480 +Signed-off-by: foonerd +--- + arch/arm/boot/dts/overlays/README | 1 + + arch/arm/boot/dts/overlays/vc4-kms-dsi-ili9881-7inch-overlay.dts | 1 + + 2 files changed, 2 insertions(+) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -5249,6 +5249,7 @@ Params: sizex Touchscr + invy Touchscreen inverted y axis + swapxy Touchscreen swapped x y axis + disable_touch Disables the touch screen overlay driver ++ rotation Display rotation {0,90,180,270} (default 0) + dsi0 Use DSI0 and i2c_csi_dsi0 (rather than + the default DSI1 and i2c_csi_dsi). + +--- a/arch/arm/boot/dts/overlays/vc4-kms-dsi-ili9881-7inch-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-ili9881-7inch-overlay.dts +@@ -118,5 +118,6 @@ + invy = <0>, "+11"; + swapxy = <>911>,"touchscreen-swapped-x-y?"; + disable_touch = <>911>, "status=disabled"; ++ rotation = <&dsi_panel>, "rotation:0"; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.6/950-1357-rpi-pio-add-missing.patch b/target/linux/bcm27xx/patches-6.6/950-1402-rp1-pio-Add-missing-static-inline-s.patch similarity index 88% rename from target/linux/bcm27xx/patches-6.6/950-1357-rpi-pio-add-missing.patch rename to target/linux/bcm27xx/patches-6.6/950-1402-rp1-pio-Add-missing-static-inline-s.patch index c871fa681f..643e83b314 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1357-rpi-pio-add-missing.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1402-rp1-pio-Add-missing-static-inline-s.patch @@ -13,7 +13,7 @@ Signed-off-by: Phil Elwell --- a/include/linux/pio_rp1.h +++ b/include/linux/pio_rp1.h -@@ -245,7 +245,7 @@ static inline bool pio_can_add_program_a +@@ -247,7 +247,7 @@ static inline bool pio_can_add_program_a return !rp1_pio_can_add_program(client, &args); } @@ -22,7 +22,7 @@ Signed-off-by: Phil Elwell { struct rp1_pio_add_program_args args; int offset; -@@ -365,7 +365,7 @@ static inline int pio_sm_set_config(stru +@@ -367,7 +367,7 @@ static inline int pio_sm_set_config(stru return rp1_pio_sm_set_config(client, &args); } @@ -31,7 +31,7 @@ Signed-off-by: Phil Elwell { struct rp1_pio_sm_exec_args args = { .sm = sm, .instr = instr, .blocking = false }; -@@ -375,7 +375,7 @@ int pio_sm_exec(struct rp1_pio_client *c +@@ -377,7 +377,7 @@ int pio_sm_exec(struct rp1_pio_client *c return rp1_pio_sm_exec(client, &args); } diff --git a/target/linux/bcm27xx/patches-6.6/950-1358-misc-rpi-pio-back-port-some.patch b/target/linux/bcm27xx/patches-6.6/950-1403-misc-rp1-pio-Back-port-some-6.11-build-fixes.patch similarity index 100% rename from target/linux/bcm27xx/patches-6.6/950-1358-misc-rpi-pio-back-port-some.patch rename to target/linux/bcm27xx/patches-6.6/950-1403-misc-rp1-pio-Back-port-some-6.11-build-fixes.patch diff --git a/target/linux/bcm27xx/patches-6.6/950-1404-Adding-Pimidi-kernel-module.patch b/target/linux/bcm27xx/patches-6.6/950-1404-Adding-Pimidi-kernel-module.patch new file mode 100644 index 0000000000..fd46f25c20 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1404-Adding-Pimidi-kernel-module.patch @@ -0,0 +1,1167 @@ +From 8a6f640708627ac8ebf79f88793038933f169198 Mon Sep 17 00:00:00 2001 +From: Giedrius +Date: Thu, 21 Nov 2024 08:04:02 +0000 +Subject: [PATCH] Adding Pimidi kernel module. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Giedrius Trainavičius +--- + sound/drivers/Kconfig | 10 + + sound/drivers/Makefile | 2 + + sound/drivers/pimidi.c | 1113 ++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 1125 insertions(+) + create mode 100644 sound/drivers/pimidi.c + +--- a/sound/drivers/Kconfig ++++ b/sound/drivers/Kconfig +@@ -263,4 +263,14 @@ config SND_AC97_POWER_SAVE_DEFAULT + + See SND_AC97_POWER_SAVE for more details. + ++config SND_PIMIDI ++ tristate "Pimidi driver" ++ depends on SND_SEQUENCER && CRC8 ++ select SND_RAWMIDI ++ help ++ Say Y here to include support for Blokas Pimidi. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called snd-pimidi. ++ + endif # SND_DRIVERS +--- a/sound/drivers/Makefile ++++ b/sound/drivers/Makefile +@@ -9,6 +9,7 @@ snd-aloop-objs := aloop.o + snd-mtpav-objs := mtpav.o + snd-mts64-objs := mts64.o + snd-pcmtest-objs := pcmtest.o ++snd-pimidi-objs := pimidi.o + snd-portman2x4-objs := portman2x4.o + snd-serial-u16550-objs := serial-u16550.o + snd-serial-generic-objs := serial-generic.o +@@ -23,6 +24,7 @@ obj-$(CONFIG_SND_SERIAL_U16550) += snd-s + obj-$(CONFIG_SND_SERIAL_GENERIC) += snd-serial-generic.o + obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o + obj-$(CONFIG_SND_MTS64) += snd-mts64.o ++obj-$(CONFIG_SND_PIMIDI) += snd-pimidi.o + obj-$(CONFIG_SND_PORTMAN2X4) += snd-portman2x4.o + + obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/ pcsp/ +--- /dev/null ++++ b/sound/drivers/pimidi.c +@@ -0,0 +1,1113 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Pimidi Linux kernel module. ++ * Copyright (C) 2017-2024 Vilniaus Blokas UAB, https://blokas.io/ ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; version 2 of the ++ * License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define PIMIDI_LOG_IMPL(instance, log_func, msg, ...) log_func("pimidi(%s)[%c]: " msg "\n", \ ++ __func__, (instance) ? (instance)->d + '0' : 'G', ## __VA_ARGS__) ++ ++#ifdef PIMIDI_DEBUG ++# define printd(instance, ...) PIMIDI_LOG_IMPL(instance, pr_alert, __VA_ARGS__) ++# define printd_rl(instance, ...) PIMIDI_LOG_IMPL(instance, pr_alert_ratelimited, __VA_ARGS__) ++# define printd_g(...) printd((struct pimidi_instance *)NULL, __VA_ARGS__) ++#else ++# define printd(instance, ...) do {} while (0) ++# define printd_rl(instance, ...) do {} while (0) ++# define printd_g(...) do {} while (0) ++#endif ++ ++#define printe(instance, ...) PIMIDI_LOG_IMPL(instance, pr_err, __VA_ARGS__) ++#define printe_rl(instance, ...) PIMIDI_LOG_IMPL(instance, pr_err_ratelimited, __VA_ARGS__) ++#define printi(instance, ...) PIMIDI_LOG_IMPL(instance, pr_info, __VA_ARGS__) ++#define printw(instance, ...) PIMIDI_LOG_IMPL(instance, pr_warn, __VA_ARGS__) ++#define printw_rl(instance, ...) PIMIDI_LOG_IMPL(instance, pr_warn_ratelimited, __VA_ARGS__) ++ ++#define printe_g(...) printe((struct pimidi_instance *)NULL, __VA_ARGS__) ++#define printi_g(...) printi((struct pimidi_instance *)NULL, __VA_ARGS__) ++ ++DECLARE_CRC8_TABLE(pimidi_crc8_table); ++enum { PIMIDI_CRC8_POLYNOMIAL = 0x83 }; ++enum { PIMIDI_MAX_DEVICES = 4 }; ++enum { PIMIDI_MAX_PACKET_SIZE = 17 }; ++enum { PIMIDI_PORTS = 2 }; ++ ++struct pimidi_shared { ++ // lock protects the shared reset_gpio and devices list. ++ struct mutex lock; ++ struct gpio_desc *reset_gpio; ++ struct workqueue_struct *work_queue; ++ struct list_head devices; ++}; ++ ++static struct pimidi_shared pimidi_global = { ++ .devices = LIST_HEAD_INIT(pimidi_global.devices), ++}; ++ ++struct pimidi_version_t { ++ u8 hwrev; ++ u8 major; ++ u8 minor; ++ u8 build; ++}; ++ ++enum { PIMIDI_IN_FIFO_SIZE = 4096 }; ++ ++struct pimidi_midi_port { ++ // in_lock protects the input substream. ++ struct mutex in_lock; ++ // out_lock protects the output substream. ++ struct mutex out_lock; ++ DECLARE_KFIFO(in_fifo, uint8_t, PIMIDI_IN_FIFO_SIZE); ++ unsigned int last_output_at; ++ unsigned int output_buffer_used_in_millibytes; ++ struct work_struct in_handler; ++ struct delayed_work out_handler; ++ unsigned long enabled_streams; ++ unsigned int tx_cnt; ++ unsigned int rx_cnt; ++}; ++ ++struct pimidi_instance { ++ struct list_head list; ++ struct i2c_client *i2c_client; ++ struct pimidi_version_t version; ++ char serial[11]; ++ char d; ++ struct gpio_desc *data_ready_gpio; ++ ++ struct work_struct drdy_handler; ++ ++ // comm_lock serializes I2C communication. ++ struct mutex comm_lock; ++ char *rx_buf; ++ size_t rx_len; ++ int rx_status; ++ struct completion *rx_completion; ++ ++ struct snd_rawmidi *rawmidi; ++ struct pimidi_midi_port midi_port[PIMIDI_PORTS]; ++ bool stopping; ++}; ++ ++static struct snd_rawmidi_substream *pimidi_find_substream(struct snd_rawmidi *rawmidi, ++ int stream, ++ int number ++ ) ++{ ++ struct snd_rawmidi_substream *substream; ++ ++ list_for_each_entry(substream, &rawmidi->streams[stream].substreams, list) { ++ if (substream->number == number) ++ return substream; ++ } ++ return NULL; ++} ++ ++static void pimidi_midi_in_handler(struct pimidi_instance *instance, int port) ++{ ++ int i, n, err; ++ ++ printd(instance, "(%d)", port); ++ ++ struct pimidi_midi_port *midi_port = &instance->midi_port[port]; ++ ++ if (!test_bit(SNDRV_RAWMIDI_STREAM_INPUT, &midi_port->enabled_streams)) { ++ printd(instance, "Input not enabled for %d", port); ++ return; ++ } ++ ++ u8 data[512]; ++ ++ n = kfifo_out_peek(&midi_port->in_fifo, data, sizeof(data)); ++ printd(instance, "Peeked %d MIDI bytes", n); ++ ++ mutex_lock(&midi_port->in_lock); ++ struct snd_rawmidi_substream *substream = ++ pimidi_find_substream(instance->rawmidi, ++ SNDRV_RAWMIDI_STREAM_INPUT, ++ port); ++ ++ err = snd_rawmidi_receive(substream, data, n); ++ if (err > 0) ++ midi_port->rx_cnt += err; ++ mutex_unlock(&midi_port->in_lock); ++ ++ for (i = 0; i < err; ++i) ++ kfifo_skip(&midi_port->in_fifo); ++ ++ if (n != err) ++ printw_rl(instance, ++ "Not all MIDI data consumed for port %d: %d / %d", port, err, n); ++ ++ if (!kfifo_is_empty(&midi_port->in_fifo) && !instance->stopping) ++ queue_work(pimidi_global.work_queue, &midi_port->in_handler); ++ ++ printd(instance, "Done"); ++} ++ ++static void pimidi_midi_in_handler_0(struct work_struct *work) ++{ ++ pimidi_midi_in_handler(container_of(work, struct pimidi_instance, midi_port[0].in_handler), ++ 0); ++} ++ ++static void pimidi_midi_in_handler_1(struct work_struct *work) ++{ ++ pimidi_midi_in_handler(container_of(work, struct pimidi_instance, midi_port[1].in_handler), ++ 1); ++} ++ ++static void pimidi_midi_out_handler(struct pimidi_instance *instance, int port) ++{ ++ printd(instance, "(%d)", port); ++ if (!test_bit(SNDRV_RAWMIDI_STREAM_OUTPUT, &instance->midi_port[port].enabled_streams)) { ++ printd(instance, "Output not enabled for %d", port); ++ return; ++ } ++ ++ struct pimidi_midi_port *midi_port = &instance->midi_port[port]; ++ ++ struct snd_rawmidi_substream *substream = ++ pimidi_find_substream(instance->rawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, port); ++ ++ mutex_lock(&midi_port->out_lock); ++ ++ enum { MIDI_MILLI_BYTES_PER_JIFFY = 3125000 / HZ }; ++ enum { MIDI_MAX_OUTPUT_BUFFER_SIZE_IN_MILLIBYTES = ++ (512 - PIMIDI_MAX_PACKET_SIZE - 1) * 1000 }; ++ ++ unsigned int now = jiffies; ++ unsigned int millibytes_became_available = ++ (MIDI_MILLI_BYTES_PER_JIFFY) * (now - midi_port->last_output_at); ++ ++ midi_port->output_buffer_used_in_millibytes = ++ midi_port->output_buffer_used_in_millibytes <= ++ millibytes_became_available ? 0 : midi_port->output_buffer_used_in_millibytes - ++ millibytes_became_available; ++ ++ unsigned int output_buffer_available = ++ (MIDI_MAX_OUTPUT_BUFFER_SIZE_IN_MILLIBYTES ++ - midi_port->output_buffer_used_in_millibytes) ++ / 1000; ++ ++ u8 buffer[PIMIDI_MAX_PACKET_SIZE]; ++ int n, batch, err; ++ ++ for (batch = 0; batch < 3; ++batch) { ++ if (output_buffer_available == 0) ++ printd(instance, "Buffer full"); ++ ++ printd(instance, "Buffer available: %u (%u +%u, %u -> %u, dt %u) (%u) @ %u", ++ output_buffer_available, midi_port->output_buffer_used_in_millibytes, ++ millibytes_became_available, midi_port->last_output_at, now, ++ now - midi_port->last_output_at, midi_port->tx_cnt, HZ); ++ midi_port->last_output_at = now; ++ ++ n = output_buffer_available ++ ? snd_rawmidi_transmit_peek(substream, buffer + 1, ++ min(output_buffer_available, ++ sizeof(buffer) - 2)) ++ : 0; ++ if (n > 0) { ++ printd(instance, "Peeked: %d", n); ++ snd_rawmidi_transmit_ack(substream, n); ++ ++ buffer[0] = (port << 4) | n; ++ buffer[n + 1] = ~crc8(pimidi_crc8_table, buffer, n + 1, CRC8_INIT_VALUE); ++ ++#ifdef PIMIDI_DEBUG ++ pr_debug("%s[%d]: Sending %d bytes:", __func__, instance->d, n + 2); ++ int i; ++ ++ for (i = 0; i < n + 2; ++i) ++ pr_cont(" %02x", buffer[i]); ++ ++ pr_cont("\n"); ++#endif ++ mutex_lock(&instance->comm_lock); ++ err = i2c_master_send(instance->i2c_client, buffer, n + 2); ++ mutex_unlock(&instance->comm_lock); ++ ++ if (err < 0) { ++ printe(instance, ++ "Error occurred when sending MIDI data over I2C! (%d)", ++ err); ++ goto cleanup; ++ } ++ ++ midi_port->tx_cnt += n; ++ midi_port->output_buffer_used_in_millibytes += n * 1000; ++ output_buffer_available -= n; ++ } else if (n < 0) { ++ err = n; ++ printe(instance, "snd_rawmidi_transmit_peek returned error %d!", err); ++ goto cleanup; ++ } else { ++ break; ++ } ++ } ++ ++ printd(instance, "Checking if empty %p", substream); ++ if (!snd_rawmidi_transmit_empty(substream) && !instance->stopping) { ++ unsigned int delay = 1; ++ ++ if (output_buffer_available == 0) ++ delay = 125000 / MIDI_MILLI_BYTES_PER_JIFFY; ++ printd(instance, "Queue more work after %u jiffies", delay); ++ mod_delayed_work(pimidi_global.work_queue, &midi_port->out_handler, delay); ++ } ++ ++cleanup: ++ mutex_unlock(&midi_port->out_lock); ++ printd(instance, "Done"); ++} ++ ++static void pimidi_midi_out_handler_0(struct work_struct *work) ++{ ++ pimidi_midi_out_handler(container_of(work, struct pimidi_instance, ++ midi_port[0].out_handler.work), 0); ++} ++ ++static void pimidi_midi_out_handler_1(struct work_struct *work) ++{ ++ pimidi_midi_out_handler(container_of(work, struct pimidi_instance, ++ midi_port[1].out_handler.work), 1); ++} ++ ++static void pimidi_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) ++{ ++ struct pimidi_instance *instance = substream->rmidi->private_data; ++ ++ printd(instance, "(%d, %d, %d)", substream->stream, substream->number, up); ++ ++ if (up == 0) { ++ clear_bit(substream->stream, ++ &instance->midi_port[substream->number].enabled_streams); ++ } else { ++ set_bit(substream->stream, ++ &instance->midi_port[substream->number].enabled_streams); ++ if (!delayed_work_pending(&instance->midi_port[substream->number].out_handler)) { ++ printd(instance, "Queueing work"); ++ queue_delayed_work(pimidi_global.work_queue, ++ &instance->midi_port[substream->number].out_handler, 0); ++ } ++ } ++} ++ ++static void pimidi_midi_output_drain(struct snd_rawmidi_substream *substream) ++{ ++ struct pimidi_instance *instance = substream->rmidi->private_data; ++ ++ printd(instance, "(%d, %d)", substream->stream, substream->number); ++ ++ printd(instance, "Begin draining!"); ++ ++ queue_delayed_work(pimidi_global.work_queue, ++ &instance->midi_port[substream->number].out_handler, 0); ++ ++ unsigned long deadline = jiffies + 5 * HZ; ++ ++ do { ++ printd(instance, "Before flush"); ++ while (delayed_work_pending(&instance->midi_port[substream->number].out_handler)) ++ flush_delayed_work(&instance->midi_port[substream->number].out_handler); ++ printd(instance, "Flushed"); ++ } while (!snd_rawmidi_transmit_empty(substream) && time_before(jiffies, deadline)); ++ ++ printd(instance, "Done!"); ++} ++ ++static int pimidi_midi_output_close(struct snd_rawmidi_substream *substream) ++{ ++ struct pimidi_instance *instance = substream->rmidi->private_data; ++ struct pimidi_midi_port *midi_port = &instance->midi_port[substream->number]; ++ ++ mutex_lock(&midi_port->out_lock); ++ clear_bit(substream->stream, &midi_port->enabled_streams); ++ mutex_unlock(&midi_port->out_lock); ++ return 0; ++} ++ ++static int pimidi_midi_input_close(struct snd_rawmidi_substream *substream) ++{ ++ struct pimidi_instance *instance = substream->rmidi->private_data; ++ struct pimidi_midi_port *midi_port = &instance->midi_port[substream->number]; ++ ++ mutex_lock(&midi_port->in_lock); ++ clear_bit(substream->stream, &midi_port->enabled_streams); ++ mutex_unlock(&midi_port->in_lock); ++ return 0; ++} ++ ++static void pimidi_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) ++{ ++ struct pimidi_instance *instance = substream->rmidi->private_data; ++ ++ printd(instance, "(%d, %d, %d)", substream->stream, substream->number, up); ++ ++ if (up == 0) { ++ clear_bit(substream->stream, ++ &instance->midi_port[substream->number].enabled_streams); ++ cancel_work_sync(&instance->midi_port[substream->number].in_handler); ++ } else { ++ set_bit(substream->stream, ++ &instance->midi_port[substream->number].enabled_streams); ++ if (!instance->stopping) ++ queue_work(pimidi_global.work_queue, ++ &instance->midi_port[substream->number].in_handler); ++ } ++} ++ ++static void pimidi_get_port_info(struct snd_rawmidi *rmidi, int number, ++ struct snd_seq_port_info *seq_port_info) ++{ ++ printd_g("%p, %d, %p", rmidi, number, seq_port_info); ++ seq_port_info->type = ++ SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | ++ SNDRV_SEQ_PORT_TYPE_HARDWARE | ++ SNDRV_SEQ_PORT_TYPE_PORT; ++ strscpy(seq_port_info->name, number == 0 ? "a" : "b", ++ sizeof(seq_port_info->name)); ++ seq_port_info->midi_voices = 0; ++} ++ ++static const struct snd_rawmidi_global_ops pimidi_midi_ops = { ++ .get_port_info = pimidi_get_port_info, ++}; ++ ++static int pimidi_midi_open(struct snd_rawmidi_substream *substream) ++{ ++ printd_g("(%p) stream=%d number=%d", substream, substream->stream, substream->number); ++ return 0; ++} ++ ++static const struct snd_rawmidi_ops pimidi_midi_output_ops = { ++ .open = pimidi_midi_open, ++ .close = pimidi_midi_output_close, ++ .trigger = pimidi_midi_output_trigger, ++ .drain = pimidi_midi_output_drain, ++}; ++ ++static const struct snd_rawmidi_ops pimidi_midi_input_ops = { ++ .open = pimidi_midi_open, ++ .close = pimidi_midi_input_close, ++ .trigger = pimidi_midi_input_trigger, ++}; ++ ++static int pimidi_register(struct pimidi_instance *instance) ++{ ++ int err = 0; ++ ++ mutex_lock(&pimidi_global.lock); ++ printd(instance, "Registering..."); ++ if (!pimidi_global.reset_gpio) { ++ printd_g("Getting reset pin."); ++ pimidi_global.reset_gpio = gpiod_get(&instance->i2c_client->dev, "reset", ++ GPIOD_OUT_LOW); ++ if (IS_ERR(pimidi_global.reset_gpio)) { ++ err = PTR_ERR(pimidi_global.reset_gpio); ++ printe_g("gpiod_get failed: %d", err); ++ pimidi_global.reset_gpio = NULL; ++ mutex_unlock(&pimidi_global.lock); ++ return err; ++ } ++ } ++ list_add_tail(&instance->list, &pimidi_global.devices); ++ mutex_unlock(&pimidi_global.lock); ++ return err; ++} ++ ++static void pimidi_unregister(struct pimidi_instance *instance) ++{ ++ mutex_lock(&pimidi_global.lock); ++ printd(instance, "Unregistering..."); ++ list_del(&instance->list); ++ if (list_empty(&pimidi_global.devices)) { ++ printd_g("Releasing reset pin"); ++ gpiod_put(pimidi_global.reset_gpio); ++ pimidi_global.reset_gpio = NULL; ++ } ++ mutex_unlock(&pimidi_global.lock); ++} ++ ++static void pimidi_perform_reset(void) ++{ ++ mutex_lock(&pimidi_global.lock); ++ ++ printd_g("Performing reset."); ++ ++ struct list_head *p; ++ ++ list_for_each(p, &pimidi_global.devices) { ++ struct pimidi_instance *instance = list_entry(p, struct pimidi_instance, list); ++ ++ printd(instance, "Pausing..."); ++ instance->stopping = true; ++ disable_irq(instance->i2c_client->irq); ++ cancel_work(&instance->drdy_handler); ++ ++ int i; ++ ++ for (i = 0; i < PIMIDI_PORTS; ++i) { ++ cancel_work(&instance->midi_port[i].in_handler); ++ cancel_delayed_work(&instance->midi_port[i].out_handler); ++ } ++ ++ drain_workqueue(pimidi_global.work_queue); ++ } ++ ++ printd_g("Reset = low"); ++ gpiod_set_value(pimidi_global.reset_gpio, 1); ++ ++ list_for_each(p, &pimidi_global.devices) { ++ struct pimidi_instance *instance = list_entry(p, struct pimidi_instance, list); ++ ++ if (gpiod_is_active_low(instance->data_ready_gpio)) ++ gpiod_toggle_active_low(instance->data_ready_gpio); ++ gpiod_direction_output(instance->data_ready_gpio, 1); ++ printd(instance, "DRDY high"); ++ } ++ ++ usleep_range(1000, 5000); ++ printd_g("Reset = high"); ++ gpiod_set_value(pimidi_global.reset_gpio, 0); ++ msleep(30); ++ ++ int i; ++ ++ for (i = 0; i < PIMIDI_MAX_DEVICES; ++i) { ++ usleep_range(1000, 3000); ++ list_for_each(p, &pimidi_global.devices) { ++ struct pimidi_instance *instance = list_entry(p, struct pimidi_instance, ++ list); ++ ++ if (instance->d < i) ++ continue; ++ printd(instance, "DRDY -> %d", !gpiod_get_value(instance->data_ready_gpio)); ++ gpiod_set_value(instance->data_ready_gpio, ++ !gpiod_get_value(instance->data_ready_gpio)); ++ } ++ } ++ usleep_range(16000, 20000); ++ ++ list_for_each(p, &pimidi_global.devices) { ++ struct pimidi_instance *instance = list_entry(p, struct pimidi_instance, list); ++ ++ if (!gpiod_is_active_low(instance->data_ready_gpio)) ++ gpiod_toggle_active_low(instance->data_ready_gpio); ++ ++ printd(instance, "DRDY input"); ++ gpiod_direction_input(instance->data_ready_gpio); ++ ++ printd(instance, "Resume..."); ++ instance->stopping = false; ++ enable_irq(instance->i2c_client->irq); ++ } ++ ++ printd_g("Reset done."); ++ usleep_range(16000, 20000); ++ ++ mutex_unlock(&pimidi_global.lock); ++} ++ ++static int pimidi_read_version(struct pimidi_version_t *version, struct pimidi_instance *instance) ++{ ++ memset(version, 0, sizeof(*version)); ++ ++ const char cmd[4] = { 0xb2, 0x01, 0x01, 0x95 }; ++ ++ char result[9]; ++ ++ memset(result, 0, sizeof(result)); ++ ++ DECLARE_COMPLETION_ONSTACK(done); ++ ++ mutex_lock(&instance->comm_lock); ++ int err = i2c_master_send(instance->i2c_client, cmd, sizeof(cmd)); ++ ++ if (err < 0) { ++ mutex_unlock(&instance->comm_lock); ++ return err; ++ } ++ instance->rx_buf = result; ++ instance->rx_len = sizeof(result); ++ instance->rx_completion = &done; ++ mutex_unlock(&instance->comm_lock); ++ ++ printd(instance, "Waiting for drdy"); ++ wait_for_completion_io_timeout(&done, msecs_to_jiffies(1000u)); ++ printd(instance, "Done waiting"); ++ ++ if (!completion_done(&done)) { ++ mutex_lock(&instance->comm_lock); ++ instance->rx_buf = NULL; ++ instance->rx_len = 0; ++ instance->rx_status = -ETIMEDOUT; ++ instance->rx_completion = NULL; ++ mutex_unlock(&instance->comm_lock); ++ return -ETIMEDOUT; ++ } ++ ++ if (CRC8_GOOD_VALUE(pimidi_crc8_table) != crc8(pimidi_crc8_table, result, sizeof(result), ++ CRC8_INIT_VALUE)) ++ return -EIO; ++ ++ const char expected[4] = { 0xb7, 0x81, 0x01, 0x00 }; ++ ++ if (memcmp(result, expected, sizeof(expected)) != 0) ++ return -EPROTO; ++ ++ u32 v = ntohl(*(uint32_t *)(result + 4)); ++ ++ version->hwrev = v >> 24; ++ version->major = (v & 0x00ff0000) >> 16; ++ version->minor = (v & 0x0000ff00) >> 8; ++ version->build = v & 0x000000ff; ++ ++ return 0; ++} ++ ++static int pimidi_read_serial(char serial[11], struct pimidi_instance *instance) ++{ ++ memset(serial, 0, sizeof(char[11])); ++ ++ const char cmd[4] = { 0xb2, 0x03, 0x04, 0x97 }; ++ ++ char result[PIMIDI_MAX_PACKET_SIZE]; ++ ++ memset(result, 0, sizeof(result)); ++ ++ DECLARE_COMPLETION_ONSTACK(done); ++ ++ mutex_lock(&instance->comm_lock); ++ int err = i2c_master_send(instance->i2c_client, cmd, sizeof(cmd)); ++ ++ if (err < 0) { ++ mutex_unlock(&instance->comm_lock); ++ return err; ++ } ++ instance->rx_buf = result; ++ instance->rx_len = sizeof(result); ++ instance->rx_completion = &done; ++ mutex_unlock(&instance->comm_lock); ++ ++ printd(instance, "Waiting for drdy"); ++ wait_for_completion_io_timeout(&done, msecs_to_jiffies(1000u)); ++ printd(instance, "Done waiting"); ++ ++ if (!completion_done(&done)) { ++ mutex_lock(&instance->comm_lock); ++ instance->rx_buf = NULL; ++ instance->rx_len = 0; ++ instance->rx_status = -ETIMEDOUT; ++ instance->rx_completion = NULL; ++ mutex_unlock(&instance->comm_lock); ++ printe(instance, "Timed out"); ++ return -ETIMEDOUT; ++ } ++ ++ if (CRC8_GOOD_VALUE(pimidi_crc8_table) != crc8(pimidi_crc8_table, result, ++ (result[0] & 0x0f) + 2, CRC8_INIT_VALUE)) ++ return -EIO; ++ ++ const char expected[4] = { 0xbd, 0x83, 0x04, 0x0a }; ++ ++ if (memcmp(result, expected, sizeof(expected)) != 0) { ++ printe(instance, "Unexpected response: %02x %02x %02x %02x", result[0], result[1], ++ result[2], result[3]); ++ return -EPROTO; ++ } ++ ++ memcpy(serial, result + 4, 10); ++ ++ if (strspn(serial, "\xff") == 10) ++ strscpy(serial, "(unset)", 8); ++ ++ return 0; ++} ++ ++static void pimidi_handle_midi_data(struct pimidi_instance *instance, int port, const uint8_t *data, ++ unsigned int n) ++{ ++ printd(instance, "Handling MIDI data for port %d (%u bytes)", port, n); ++ if (n == 0) ++ return; ++ ++ struct pimidi_midi_port *midi_port = &instance->midi_port[port]; ++ ++ kfifo_in(&midi_port->in_fifo, data, n); ++ ++ if (!instance->stopping) ++ queue_work(pimidi_global.work_queue, &midi_port->in_handler); ++ ++ printd(instance, "Done"); ++} ++ ++static void pimidi_drdy_continue(struct pimidi_instance *instance) ++{ ++ if (instance->stopping) { ++ printd(instance, "Refusing to queue work / enable IRQ due to stopping."); ++ return; ++ } ++ ++ if (gpiod_get_value(instance->data_ready_gpio)) { ++ printd_rl(instance, "Queue work due to DRDY line still low"); ++ queue_work(pimidi_global.work_queue, &instance->drdy_handler); ++ } else { ++ printd_rl(instance, "Enabling irq for more data"); ++ enable_irq(gpiod_to_irq(instance->data_ready_gpio)); ++ } ++} ++ ++static void pimidi_drdy_handler(struct work_struct *work) ++{ ++ struct pimidi_instance *instance = container_of(work, struct pimidi_instance, drdy_handler); ++ ++ printd(instance, "(%p)", work); ++ ++ mutex_lock(&instance->comm_lock); ++ if (!instance->rx_completion) { ++ u8 data[PIMIDI_MAX_PACKET_SIZE]; ++ int n = i2c_master_recv(instance->i2c_client, data, 3); ++ ++ if (n < 0) { ++ printe(instance, "Error reading from device: %d", n); ++ mutex_unlock(&instance->comm_lock); ++ pimidi_drdy_continue(instance); ++ return; ++ } ++ ++ if (data[0] == 0xfe) { ++ printe_rl(instance, "Invalid packet 0x%02x 0x%02x 0x%02x", data[0], data[1], ++ data[2]); ++ mutex_unlock(&instance->comm_lock); ++ pimidi_drdy_continue(instance); ++ return; ++ } ++ ++ int len = (data[0] & 0x0f) + 2; ++ ++ if (len > n) { ++ printd(instance, "Need %d more bytes", len - n); ++ int err = i2c_master_recv(instance->i2c_client, data + n, len - n); ++ ++ if (err < 0) { ++ printe(instance, "Error reading remainder from device: %d", err); ++ mutex_unlock(&instance->comm_lock); ++ pimidi_drdy_continue(instance); ++ return; ++#ifdef PIMIDI_DEBUG ++ } else { ++ pr_debug("Recv_2:"); ++ int i; ++ ++ for (i = n; i < len; ++i) ++ pr_cont(" %02x", data[i]); ++ pr_cont("\n"); ++#endif ++ } ++ } ++ ++ if (CRC8_GOOD_VALUE(pimidi_crc8_table) == crc8(pimidi_crc8_table, data, len, ++ CRC8_INIT_VALUE)) { ++ switch (data[0] & 0xf0) { ++ case 0x00: ++ pimidi_handle_midi_data(instance, 0, data + 1, len - 2); ++ break; ++ case 0x10: ++ pimidi_handle_midi_data(instance, 1, data + 1, len - 2); ++ break; ++ default: ++ printd(instance, "Unhandled command %02x", data[0]); ++ break; ++ } ++ } else { ++ printe(instance, "I2C rx corruption detected."); ++ pr_info("Packet [%d]:", len); ++ int i; ++ ++ for (i = 0; i < len; ++i) ++ pr_cont(" %02x", data[i]); ++ pr_cont("\n"); ++ } ++ ++ mutex_unlock(&instance->comm_lock); ++ } else { ++ printd(instance, "Completing drdy"); ++ instance->rx_status = i2c_master_recv(instance->i2c_client, instance->rx_buf, 3); ++ printd(instance, "Recv_1 %02x %02x %02x", instance->rx_buf[0], instance->rx_buf[1], ++ instance->rx_buf[2]); ++ if (instance->rx_len > 3 && instance->rx_status == 3) { ++ instance->rx_status = i2c_master_recv(instance->i2c_client, ++ instance->rx_buf + 3, ++ instance->rx_len - 3); ++ if (instance->rx_status >= 0) ++ instance->rx_status += 3; ++#ifdef PIMIDI_DEBUG ++ pr_debug("Recv_2:"); ++ int i; ++ ++ for (i = 3; i < instance->rx_len; ++i) ++ pr_cont(" %02x", instance->rx_buf[i]); ++ pr_cont("\n"); ++#endif ++ } ++ struct completion *done = instance->rx_completion; ++ ++ instance->rx_buf = NULL; ++ instance->rx_len = 0; ++ instance->rx_completion = NULL; ++ complete_all(done); ++ mutex_unlock(&instance->comm_lock); ++ } ++ ++ pimidi_drdy_continue(instance); ++} ++ ++static irqreturn_t pimidi_drdy_interrupt_handler(int irq, void *dev_id) ++{ ++ struct pimidi_instance *instance = (struct pimidi_instance *)dev_id; ++ ++ if (instance->stopping) { ++ printd(instance, "DRDY interrupt, but stopping, ignoring..."); ++ return IRQ_HANDLED; ++ } ++ ++ printd(instance, "DRDY interrupt, masking"); ++ disable_irq_nosync(irq); ++ ++ printd(instance, "Queue work due to DRDY interrupt"); ++ queue_work(pimidi_global.work_queue, &instance->drdy_handler); ++ ++ return IRQ_HANDLED; ++} ++ ++static void pimidi_proc_stat_show(struct snd_info_entry *entry, struct snd_info_buffer *buffer) ++{ ++ const unsigned int *d = entry->private_data; ++ ++ snd_iprintf(buffer, "%u\n", *d); ++} ++ ++static void pimidi_proc_serial_show(struct snd_info_entry *entry, struct snd_info_buffer *buffer) ++{ ++ struct pimidi_instance *instance = entry->private_data; ++ ++ snd_iprintf(buffer, "%s\n", instance->serial); ++} ++ ++static void pimidi_proc_version_show(struct snd_info_entry *entry, struct snd_info_buffer *buffer) ++{ ++ struct pimidi_instance *instance = entry->private_data; ++ ++ snd_iprintf(buffer, "%u.%u.%u\n", instance->version.major, instance->version.minor, ++ instance->version.build); ++} ++ ++static void pimidi_proc_hwrev_show(struct snd_info_entry *entry, struct snd_info_buffer *buffer) ++{ ++ struct pimidi_instance *instance = entry->private_data; ++ ++ snd_iprintf(buffer, "%u\n", instance->version.hwrev); ++} ++ ++static int pimidi_i2c_probe(struct i2c_client *client) ++{ ++ struct snd_card *card = NULL; ++ int err, d, i; ++ ++ d = client->addr - 0x20; ++ ++ if (d < 0 || d >= 8) { ++ printe_g("Unexpected device address: %d", client->addr); ++ err = -EINVAL; ++ goto finalize; ++ } ++ ++ err = snd_card_new(&client->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, THIS_MODULE, ++ sizeof(struct pimidi_instance), &card); ++ ++ if (err) { ++ printe_g("snd_card_new failed: %d", err); ++ return err; ++ } ++ ++ struct pimidi_instance *instance = (struct pimidi_instance *)card->private_data; ++ ++ instance->i2c_client = client; ++ instance->d = d; ++ ++ struct snd_rawmidi *rawmidi; ++ ++ err = snd_rawmidi_new(card, card->shortname, 0, 2, 2, &rawmidi); ++ if (err < 0) { ++ printe(instance, "snd_rawmidi_new failed: %d", err); ++ goto finalize; ++ } ++ ++ instance->rawmidi = rawmidi; ++ strscpy(rawmidi->name, "pimidi", sizeof(rawmidi->name)); ++ ++ rawmidi->info_flags = ++ SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; ++ rawmidi->private_data = instance; ++ rawmidi->ops = &pimidi_midi_ops; ++ ++ snd_rawmidi_set_ops(rawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &pimidi_midi_output_ops); ++ snd_rawmidi_set_ops(rawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &pimidi_midi_input_ops); ++ ++ instance->data_ready_gpio = devm_gpiod_get(&client->dev, "data-ready", GPIOD_OUT_HIGH); ++ if (IS_ERR(instance->data_ready_gpio)) { ++ err = PTR_ERR(instance->data_ready_gpio); ++ printe(instance, "devm_gpiod_get failed: %d", err); ++ goto finalize; ++ } ++ ++ err = pimidi_register(instance); ++ if (err < 0) { ++ printe(instance, "pimidi_register failed: %d", err); ++ goto finalize; ++ } ++ ++ pimidi_perform_reset(); ++ ++ INIT_WORK(&instance->drdy_handler, pimidi_drdy_handler); ++ mutex_init(&instance->comm_lock); ++ ++ err = devm_request_irq(&client->dev, client->irq, pimidi_drdy_interrupt_handler, ++ IRQF_SHARED | IRQF_TRIGGER_LOW, "data_ready_int", instance); ++ ++ if (err != 0) { ++ printe(instance, "data_available IRQ request failed! %d", err); ++ goto finalize; ++ } ++ ++ err = pimidi_read_version(&instance->version, instance); ++ if (err < 0) { ++ printe(instance, "pimidi_read_version failed: %d", err); ++ goto finalize; ++ } ++ ++ err = pimidi_read_serial(instance->serial, instance); ++ if (err < 0) { ++ printe(instance, "pimidi_read_serial failed: %d", err); ++ goto finalize; ++ } else if (instance->serial[0] != 'P' || instance->serial[1] != 'M' || ++ strlen(instance->serial) != 10) { ++ printe(instance, "Unexpected serial number: %s", instance->serial); ++ err = -EIO; ++ goto finalize; ++ } ++ ++ printi(instance, "pimidi%d hw:%d version %u.%u.%u-%u, serial %s", ++ d, ++ card->number, ++ instance->version.major, ++ instance->version.minor, ++ instance->version.build, ++ instance->version.hwrev, ++ instance->serial ++ ); ++ ++ strscpy(card->driver, "snd-pimidi", sizeof(card->driver)); ++ snprintf(card->shortname, sizeof(card->shortname), "pimidi%d", d); ++ snprintf(card->longname, sizeof(card->longname), "pimidi%d %s", d, instance->serial); ++ snprintf(card->id, sizeof(card->id), "pimidi%d", d); ++ ++ snprintf(pimidi_find_substream(rawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 0)->name, ++ 10u, "pimidi%d-a", d); ++ snprintf(pimidi_find_substream(rawmidi, SNDRV_RAWMIDI_STREAM_INPUT, 0)->name, ++ 10u, "pimidi%d-a", d); ++ snprintf(pimidi_find_substream(rawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 1)->name, ++ 10u, "pimidi%d-b", d); ++ snprintf(pimidi_find_substream(rawmidi, SNDRV_RAWMIDI_STREAM_INPUT, 1)->name, ++ 10u, "pimidi%d-b", d); ++ ++ err = snd_card_ro_proc_new(card, "a-tx", &instance->midi_port[0].tx_cnt, ++ pimidi_proc_stat_show); ++ err = snd_card_ro_proc_new(card, "a-rx", &instance->midi_port[0].rx_cnt, ++ pimidi_proc_stat_show); ++ err = snd_card_ro_proc_new(card, "b-tx", &instance->midi_port[1].tx_cnt, ++ pimidi_proc_stat_show); ++ err = snd_card_ro_proc_new(card, "b-rx", &instance->midi_port[1].rx_cnt, ++ pimidi_proc_stat_show); ++ err = snd_card_ro_proc_new(card, "serial", instance, pimidi_proc_serial_show); ++ err = snd_card_ro_proc_new(card, "version", instance, pimidi_proc_version_show); ++ err = snd_card_ro_proc_new(card, "hwrev", instance, pimidi_proc_hwrev_show); ++ if (err < 0) { ++ printe(instance, "snd_card_ro_proc_new failed: %d", err); ++ goto finalize; ++ } ++ ++ err = snd_card_register(card); ++ if (err < 0) { ++ printe(instance, "snd_card_register failed: %d", err); ++ goto finalize; ++ } ++ ++finalize: ++ if (err) { ++ instance->stopping = true; ++ cancel_work_sync(&instance->drdy_handler); ++ mutex_destroy(&instance->comm_lock); ++ pimidi_unregister(instance); ++ snd_card_free(card); ++ return err; ++ } ++ ++ for (i = 0; i < PIMIDI_PORTS; ++i) { ++ struct pimidi_midi_port *port = &instance->midi_port[i]; ++ ++ mutex_init(&port->in_lock); ++ mutex_init(&port->out_lock); ++ INIT_WORK(&port->in_handler, ++ i == 0 ? pimidi_midi_in_handler_0 : pimidi_midi_in_handler_1); ++ INIT_DELAYED_WORK(&port->out_handler, ++ i == 0 ? pimidi_midi_out_handler_0 : pimidi_midi_out_handler_1); ++ INIT_KFIFO(port->in_fifo); ++ port->last_output_at = jiffies; ++ } ++ ++ i2c_set_clientdata(client, card); ++ return 0; ++} ++ ++static void pimidi_i2c_remove(struct i2c_client *client) ++{ ++ printd_g("(%p)", client); ++ ++ int i; ++ struct snd_card *card = i2c_get_clientdata(client); ++ ++ if (card) { ++ printi_g("Unloading hw:%d %s", card->number, card->longname); ++ struct pimidi_instance *instance = (struct pimidi_instance *)card->private_data; ++ ++ instance->stopping = true; ++ i2c_set_clientdata(client, NULL); ++ devm_free_irq(&client->dev, client->irq, instance); ++ cancel_work_sync(&instance->drdy_handler); ++ ++ for (i = 0; i < PIMIDI_PORTS; ++i) { ++ cancel_work_sync(&instance->midi_port[i].in_handler); ++ cancel_delayed_work_sync(&instance->midi_port[i].out_handler); ++ mutex_destroy(&instance->midi_port[i].out_lock); ++ mutex_destroy(&instance->midi_port[i].in_lock); ++ kfifo_free(&instance->midi_port[i].in_fifo); ++ } ++ ++ mutex_destroy(&instance->comm_lock); ++ pimidi_unregister(instance); ++ snd_card_free(card); ++ } ++} ++ ++static const struct i2c_device_id pimidi_i2c_ids[] = { ++ { "pimidi", 0 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, pimidi_i2c_ids); ++ ++static const struct of_device_id pimidi_i2c_dt_ids[] = { ++ { .compatible = "blokaslabs,pimidi", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, pimidi_i2c_dt_ids); ++ ++static struct i2c_driver pimidi_i2c_driver = { ++ .driver = { ++ .name = "pimidi", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(pimidi_i2c_dt_ids), ++ }, ++ .probe = pimidi_i2c_probe, ++ .remove = pimidi_i2c_remove, ++ .id_table = pimidi_i2c_ids, ++}; ++ ++int pimidi_module_init(void) ++{ ++ int err = 0; ++ ++ mutex_init(&pimidi_global.lock); ++ ++ INIT_LIST_HEAD(&pimidi_global.devices); ++ ++ pimidi_global.work_queue = create_singlethread_workqueue("pimidi"); ++ if (!pimidi_global.work_queue) { ++ err = -ENOMEM; ++ goto cleanup; ++ } ++ ++ err = i2c_add_driver(&pimidi_i2c_driver); ++ if (err < 0) ++ goto cleanup; ++ ++ crc8_populate_msb(pimidi_crc8_table, PIMIDI_CRC8_POLYNOMIAL); ++ ++ return 0; ++ ++cleanup: ++ mutex_destroy(&pimidi_global.lock); ++ return err; ++} ++ ++void pimidi_module_exit(void) ++{ ++ i2c_del_driver(&pimidi_i2c_driver); ++ mutex_lock(&pimidi_global.lock); ++ if (pimidi_global.reset_gpio) { ++ gpiod_put(pimidi_global.reset_gpio); ++ pimidi_global.reset_gpio = NULL; ++ } ++ mutex_unlock(&pimidi_global.lock); ++ ++ destroy_workqueue(pimidi_global.work_queue); ++ pimidi_global.work_queue = NULL; ++ ++ mutex_destroy(&pimidi_global.lock); ++} ++ ++module_init(pimidi_module_init); ++module_exit(pimidi_module_exit); ++ ++MODULE_AUTHOR("Giedrius Trainavi\xc4\x8dius "); ++MODULE_DESCRIPTION("MIDI driver for Blokas Pimidi, https://blokas.io/"); ++MODULE_LICENSE("GPL"); ++ ++/* vim: set ts=8 sw=8 noexpandtab: */ diff --git a/target/linux/bcm27xx/patches-6.6/950-1406-Adding-pimidi-overlay.dts.patch b/target/linux/bcm27xx/patches-6.6/950-1406-Adding-pimidi-overlay.dts.patch new file mode 100644 index 0000000000..ab46dbdb98 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1406-Adding-pimidi-overlay.dts.patch @@ -0,0 +1,100 @@ +From 75ab92b077602734458f0a77e19a3599be29b93b Mon Sep 17 00:00:00 2001 +From: Giedrius +Date: Thu, 21 Nov 2024 08:05:49 +0000 +Subject: [PATCH] Adding pimidi-overlay.dts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Giedrius Trainavičius +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 8 +++ + arch/arm/boot/dts/overlays/pimidi-overlay.dts | 54 +++++++++++++++++++ + 3 files changed, 63 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/pimidi-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -203,6 +203,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + pifi-dac-zero.dtbo \ + pifi-mini-210.dtbo \ + piglow.dtbo \ ++ pimidi.dtbo \ + pineboards-hat-ai.dtbo \ + pineboards-hatdrive-poe-plus.dtbo \ + piscreen.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -3701,6 +3701,14 @@ Load: dtoverlay=piglow + Params: + + ++Name: pimidi ++Info: Configures the Blokas Labs Pimidi card ++Load: dtoverlay=pimidi,= ++Params: sel The position used for the sel rotary switch. ++ Each unit in the stack must be set on a unique ++ position. If param is omitted, sel=0 is assumed. ++ ++ + Name: pineboards-hat-ai + Info: Pineboards Hat Ai! overlay for the Google Coral Edge TPU + Load: dtoverlay=pineboards-hat-ai +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pimidi-overlay.dts +@@ -0,0 +1,54 @@ ++/* ++ * Pimidi Linux kernel module. ++ * Copyright (C) 2017-2024 Vilniaus Blokas UAB, https://blokas.io/ ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; version 2 of the ++ * License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++/ { ++ compatible = "brcm,bcm2835"; ++ ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ status = "okay"; ++ clock-frequency=<1000000>; ++ ++ pimidi_ctrl: pimidi_ctrl@20 { ++ compatible = "blokaslabs,pimidi"; ++ ++ reg = <0x20>; ++ status = "okay"; ++ ++ interrupt-parent = <&gpio>; ++ interrupts = <23 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-names = "data_ready"; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ++ data-ready-gpios = <&gpio 23 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; ++ reset-gpios = <&gpio 22 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ sel = <&pimidi_ctrl>,"reg:0{0=0x20,1=0x21,2=0x22,3=0x23}", ++ <&pimidi_ctrl>,"data-ready-gpios:4{0=23,1=5,2=6,3=27}", ++ <&pimidi_ctrl>,"interrupts:0{0=23,1=5,2=6,3=27}"; ++ }; ++}; diff --git a/target/linux/bcm27xx/patches-6.6/950-0297-staging-vchiq_arm-Add-36-bit-address-support.patch b/target/linux/bcm27xx/patches-6.6/950-1411-staging-vchiq_arm-Add-36-bit-address-support.patch similarity index 98% rename from target/linux/bcm27xx/patches-6.6/950-0297-staging-vchiq_arm-Add-36-bit-address-support.patch rename to target/linux/bcm27xx/patches-6.6/950-1411-staging-vchiq_arm-Add-36-bit-address-support.patch index 11147d9fd9..871b2769b1 100644 --- a/target/linux/bcm27xx/patches-6.6/950-0297-staging-vchiq_arm-Add-36-bit-address-support.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1411-staging-vchiq_arm-Add-36-bit-address-support.patch @@ -1,7 +1,7 @@ -From fc5ed9d9bf0411523220bab60304da6d23257a64 Mon Sep 17 00:00:00 2001 +From a1e4b72997dc3ef423b6f510bfead470475750d4 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 1 Nov 2018 17:31:37 +0000 -Subject: [PATCH 0297/1085] staging: vchiq_arm: Add 36-bit address support +Subject: [PATCH] staging: vchiq_arm: Add 36-bit address support Conditional on a new compatible string, change the pagelist encoding such that the top 24 bits are the pfn, leaving 8 bits for run length diff --git a/target/linux/bcm27xx/patches-6.6/950-0298-staging-vchiq_arm-children-inherit-DMA-config.patch b/target/linux/bcm27xx/patches-6.6/950-1412-staging-vchiq_arm-children-inherit-DMA-config.patch similarity index 87% rename from target/linux/bcm27xx/patches-6.6/950-0298-staging-vchiq_arm-children-inherit-DMA-config.patch rename to target/linux/bcm27xx/patches-6.6/950-1412-staging-vchiq_arm-children-inherit-DMA-config.patch index 87bea65fc7..df93f3a0c4 100644 --- a/target/linux/bcm27xx/patches-6.6/950-0298-staging-vchiq_arm-children-inherit-DMA-config.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1412-staging-vchiq_arm-children-inherit-DMA-config.patch @@ -1,7 +1,7 @@ -From d4712f611e6d60dd9cf09df581f5df6fad6a2207 Mon Sep 17 00:00:00 2001 +From 1129091b2d95273d930acf2926a569b90512a248 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 21 Jul 2020 17:34:09 +0100 -Subject: [PATCH 0298/1085] staging: vchiq_arm: children inherit DMA config +Subject: [PATCH] staging: vchiq_arm: children inherit DMA config Although it is no longer necessary for vchiq's children to have a different DMA configuration to the parent, they do still need to diff --git a/target/linux/bcm27xx/patches-6.6/950-0299-staging-vchiq_arm-Usa-a-DMA-pool-for-small-bulks.patch b/target/linux/bcm27xx/patches-6.6/950-1413-staging-vchiq_arm-Usa-a-DMA-pool-for-small-bulks.patch similarity index 96% rename from target/linux/bcm27xx/patches-6.6/950-0299-staging-vchiq_arm-Usa-a-DMA-pool-for-small-bulks.patch rename to target/linux/bcm27xx/patches-6.6/950-1413-staging-vchiq_arm-Usa-a-DMA-pool-for-small-bulks.patch index 162d333c61..7120123ecf 100644 --- a/target/linux/bcm27xx/patches-6.6/950-0299-staging-vchiq_arm-Usa-a-DMA-pool-for-small-bulks.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1413-staging-vchiq_arm-Usa-a-DMA-pool-for-small-bulks.patch @@ -1,7 +1,7 @@ -From 9f328c347fc9a5495b8383aa2bae1d3bc242a2ab Mon Sep 17 00:00:00 2001 +From 2d26a598ceceaea8a6837146c741eb742bbd4baa Mon Sep 17 00:00:00 2001 From: detule Date: Tue, 2 Oct 2018 04:10:08 -0400 -Subject: [PATCH 0299/1085] staging: vchiq_arm: Usa a DMA pool for small bulks +Subject: [PATCH] staging: vchiq_arm: Usa a DMA pool for small bulks During a bulk transfer we request a DMA allocation to hold the scatter-gather list. Most of the time, this allocation is small diff --git a/target/linux/bcm27xx/patches-6.6/950-0365-staging-vchiq_arm-Add-log_level-module-params.patch b/target/linux/bcm27xx/patches-6.6/950-1414-staging-vchiq_arm-Add-log_level-module-params.patch similarity index 88% rename from target/linux/bcm27xx/patches-6.6/950-0365-staging-vchiq_arm-Add-log_level-module-params.patch rename to target/linux/bcm27xx/patches-6.6/950-1414-staging-vchiq_arm-Add-log_level-module-params.patch index 51815f2619..d85765bc32 100644 --- a/target/linux/bcm27xx/patches-6.6/950-0365-staging-vchiq_arm-Add-log_level-module-params.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1414-staging-vchiq_arm-Add-log_level-module-params.patch @@ -1,7 +1,7 @@ -From 79f24f7454a416fed9106c75ea9b3be480465dda Mon Sep 17 00:00:00 2001 +From 5b29221e96d1ba60a78d5c804a20fa35a6d0517a Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 29 Apr 2022 09:19:10 +0100 -Subject: [PATCH 0365/1085] staging: vchiq_arm: Add log_level module params +Subject: [PATCH] staging: vchiq_arm: Add log_level module params Add module parameters to control the logging levels for the various vchiq logging categories. diff --git a/target/linux/bcm27xx/patches-6.6/950-1415-media-i2c-imx477-Fix-link-frequency-menu.patch b/target/linux/bcm27xx/patches-6.6/950-1415-media-i2c-imx477-Fix-link-frequency-menu.patch new file mode 100644 index 0000000000..9b5b0e47d6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1415-media-i2c-imx477-Fix-link-frequency-menu.patch @@ -0,0 +1,25 @@ +From 8691544f688bd3ae9b6db0845a75ce230fc9e90f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 21 Nov 2024 15:54:58 +0000 +Subject: [PATCH] media: i2c: imx477: Fix link frequency menu + +"media: i2c: imx477: Add options for slightly modifying the link freq" +created a link frequency menu with 2 items in instead of one. +Correct this. + +Signed-off-by: Dave Stevenson +--- + drivers/media/i2c/imx477.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -2051,7 +2051,7 @@ static int imx477_init_controls(struct i + /* LINK_FREQ is also read only */ + imx477->link_freq = + v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx477_ctrl_ops, +- V4L2_CID_LINK_FREQ, 1, 0, ++ V4L2_CID_LINK_FREQ, 0, 0, + &link_freqs[imx477->link_freq_idx]); + if (imx477->link_freq) + imx477->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; diff --git a/target/linux/bcm27xx/patches-6.6/950-1357-misc-rp1-pio-Fix-copy-paste-error-in-pio_rp1.h.patch b/target/linux/bcm27xx/patches-6.6/950-1416-misc-rp1-pio-Fix-copy-paste-error-in-pio_rp1.h.patch similarity index 93% rename from target/linux/bcm27xx/patches-6.6/950-1357-misc-rp1-pio-Fix-copy-paste-error-in-pio_rp1.h.patch rename to target/linux/bcm27xx/patches-6.6/950-1416-misc-rp1-pio-Fix-copy-paste-error-in-pio_rp1.h.patch index 0746e3c32b..cf13be0a04 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1357-misc-rp1-pio-Fix-copy-paste-error-in-pio_rp1.h.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1416-misc-rp1-pio-Fix-copy-paste-error-in-pio_rp1.h.patch @@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell --- a/include/linux/pio_rp1.h +++ b/include/linux/pio_rp1.h -@@ -318,7 +318,7 @@ static inline int pio_sm_unclaim(struct +@@ -320,7 +320,7 @@ static inline int pio_sm_unclaim(struct if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES)) return -EINVAL; diff --git a/target/linux/bcm27xx/patches-6.6/950-1360-misc-rp1-pio-Fix-parameter-checks-wihout-client.patch b/target/linux/bcm27xx/patches-6.6/950-1417-misc-rp1-pio-Fix-parameter-checks-wihout-client.patch similarity index 100% rename from target/linux/bcm27xx/patches-6.6/950-1360-misc-rp1-pio-Fix-parameter-checks-wihout-client.patch rename to target/linux/bcm27xx/patches-6.6/950-1417-misc-rp1-pio-Fix-parameter-checks-wihout-client.patch diff --git a/target/linux/bcm27xx/patches-6.6/950-1418-drm-vc4-dsi-Handle-the-different-command-FIFO-widths.patch b/target/linux/bcm27xx/patches-6.6/950-1418-drm-vc4-dsi-Handle-the-different-command-FIFO-widths.patch new file mode 100644 index 0000000000..5e50af70df --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1418-drm-vc4-dsi-Handle-the-different-command-FIFO-widths.patch @@ -0,0 +1,147 @@ +From 008c93b47b9b965368eb5bbfbef60b816931e0ab Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 20 Nov 2024 13:58:08 +0000 +Subject: [PATCH] drm: vc4: dsi: Handle the different command FIFO widths + +DSI0 and DSI1 have different widths for the command FIFO (24bit +vs 32bit), but the driver was assuming the 32bit width of DSI1 +in all cases. +DSI0 also wants the data packed as 24bit big endian, so the +formatting code needs updating. + +Handle the difference via the variant structure. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_dsi.c | 64 ++++++++++++++++++++++++----------- + 1 file changed, 44 insertions(+), 20 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_dsi.c ++++ b/drivers/gpu/drm/vc4/vc4_dsi.c +@@ -44,7 +44,6 @@ + + #define DSI_CMD_FIFO_DEPTH 16 + #define DSI_PIX_FIFO_DEPTH 256 +-#define DSI_PIX_FIFO_WIDTH 4 + + #define DSI0_CTRL 0x00 + +@@ -170,11 +169,15 @@ + #define DSI1_DISP1_CTRL 0x2c + /* Format of the data written to TXPKT_PIX_FIFO. */ + # define DSI_DISP1_PFORMAT_MASK VC4_MASK(2, 1) +-# define DSI_DISP1_PFORMAT_SHIFT 1 +-# define DSI_DISP1_PFORMAT_16BIT 0 +-# define DSI_DISP1_PFORMAT_24BIT 1 +-# define DSI_DISP1_PFORMAT_32BIT_LE 2 +-# define DSI_DISP1_PFORMAT_32BIT_BE 3 ++# define DSI1_DISP1_PFORMAT_SHIFT 1 ++# define DSI0_DISP1_PFORMAT_16BIT 0 ++# define DSI0_DISP1_PFORMAT_16BIT_ADJ 1 ++# define DSI0_DISP1_PFORMAT_24BIT 2 ++# define DSI0_DISP1_PFORMAT_32BIT_LE 3 /* NB Invalid, but required for macros to work */ ++# define DSI1_DISP1_PFORMAT_16BIT 0 ++# define DSI1_DISP1_PFORMAT_24BIT 1 ++# define DSI1_DISP1_PFORMAT_32BIT_LE 2 ++# define DSI1_DISP1_PFORMAT_32BIT_BE 3 + + /* DISP1 is always command mode. */ + # define DSI_DISP1_ENABLE BIT(0) +@@ -553,6 +556,7 @@ struct vc4_dsi_variant { + unsigned int port; + + bool broken_axi_workaround; ++ unsigned int cmd_fifo_width; + + const char *debugfs_name; + const struct debugfs_reg32 *regs; +@@ -1151,10 +1155,16 @@ static void vc4_dsi_bridge_pre_enable(st + /* Set up DISP1 for transferring long command payloads through + * the pixfifo. + */ +- DSI_PORT_WRITE(DISP1_CTRL, +- VC4_SET_FIELD(DSI_DISP1_PFORMAT_32BIT_LE, +- DSI_DISP1_PFORMAT) | +- DSI_DISP1_ENABLE); ++ if (dsi->variant->cmd_fifo_width == 4) ++ DSI_PORT_WRITE(DISP1_CTRL, ++ VC4_SET_FIELD(DSI_PORT_BIT(DISP1_PFORMAT_32BIT_LE), ++ DSI_DISP1_PFORMAT) | ++ DSI_DISP1_ENABLE); ++ else ++ DSI_PORT_WRITE(DISP1_CTRL, ++ VC4_SET_FIELD(DSI_PORT_BIT(DISP1_PFORMAT_24BIT), ++ DSI_DISP1_PFORMAT) | ++ DSI_DISP1_ENABLE); + + /* Bring AFE out of reset. */ + DSI_PORT_WRITE(PHY_AFEC0, +@@ -1235,9 +1245,9 @@ static ssize_t vc4_dsi_transfer(struct v + pix_fifo_len = 0; + } else { + cmd_fifo_len = (packet.payload_length % +- DSI_PIX_FIFO_WIDTH); ++ dsi->variant->cmd_fifo_width); + pix_fifo_len = ((packet.payload_length - cmd_fifo_len) / +- DSI_PIX_FIFO_WIDTH); ++ dsi->variant->cmd_fifo_width); + } + + WARN_ON_ONCE(pix_fifo_len >= DSI_PIX_FIFO_DEPTH); +@@ -1255,14 +1265,25 @@ static ssize_t vc4_dsi_transfer(struct v + + for (i = 0; i < cmd_fifo_len; i++) + DSI_PORT_WRITE(TXPKT_CMD_FIFO, packet.payload[i]); +- for (i = 0; i < pix_fifo_len; i++) { +- const u8 *pix = packet.payload + cmd_fifo_len + i * 4; ++ if (dsi->variant->cmd_fifo_width == 4) { ++ for (i = 0; i < pix_fifo_len; i++) { ++ const u8 *pix = packet.payload + cmd_fifo_len + i * 4; ++ ++ DSI_PORT_WRITE(TXPKT_PIX_FIFO, ++ pix[0] | ++ pix[1] << 8 | ++ pix[2] << 16 | ++ pix[3] << 24); ++ } ++ } else { ++ for (i = 0; i < pix_fifo_len; i++) { ++ const u8 *pix = packet.payload + cmd_fifo_len + i * 3; + +- DSI_PORT_WRITE(TXPKT_PIX_FIFO, +- pix[0] | +- pix[1] << 8 | +- pix[2] << 16 | +- pix[3] << 24); ++ DSI_PORT_WRITE(TXPKT_PIX_FIFO, ++ pix[2] | ++ pix[1] << 8 | ++ pix[0] << 16); ++ } + } + + if (msg->flags & MIPI_DSI_MSG_USE_LPM) +@@ -1516,6 +1537,7 @@ static const struct drm_encoder_funcs vc + + static const struct vc4_dsi_variant bcm2711_dsi1_variant = { + .port = 1, ++ .cmd_fifo_width = 4, + .debugfs_name = "dsi1_regs", + .regs = dsi1_regs, + .nregs = ARRAY_SIZE(dsi1_regs), +@@ -1523,6 +1545,7 @@ static const struct vc4_dsi_variant bcm2 + + static const struct vc4_dsi_variant bcm2835_dsi0_variant = { + .port = 0, ++ .cmd_fifo_width = 3, + .debugfs_name = "dsi0_regs", + .regs = dsi0_regs, + .nregs = ARRAY_SIZE(dsi0_regs), +@@ -1530,6 +1553,7 @@ static const struct vc4_dsi_variant bcm2 + + static const struct vc4_dsi_variant bcm2835_dsi1_variant = { + .port = 1, ++ .cmd_fifo_width = 4, + .broken_axi_workaround = true, + .debugfs_name = "dsi1_regs", + .regs = dsi1_regs, diff --git a/target/linux/bcm27xx/patches-6.6/950-1419-dts-bcm2712-rpi-For-CM5IO-i2c_csi_dsi-needs-to-be-CA.patch b/target/linux/bcm27xx/patches-6.6/950-1419-dts-bcm2712-rpi-For-CM5IO-i2c_csi_dsi-needs-to-be-CA.patch new file mode 100644 index 0000000000..0aab1043b5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1419-dts-bcm2712-rpi-For-CM5IO-i2c_csi_dsi-needs-to-be-CA.patch @@ -0,0 +1,30 @@ +From eafaa6015fc0ed676f6115905e7c4145d23f5b7d Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 26 Nov 2024 15:53:24 +0000 +Subject: [PATCH] dts: bcm2712-rpi: For CM5IO, i2c_csi_dsi needs to be + CAM/DISP1 + +Noted setting up a display on CM5IO. Add +"dtoverlay=vc4-kms-dsi-ili7881-7inch" fails as it tries to +find the regulator/backlight/touch on i2c_csi_dsi, which pointed +at i2c_csi_dsi0 by default. + +Adding the dsi0 override updated to point at dsi0, and pointed +the i2c at i2c_csi_dsi0, which all works. + +The default with i2c_csi_dsi needs to be consistent in using +dsi1/csi1 and the corresponding i2c interface (i2c_csi_dsi1). + +Signed-off-by: Dave Stevenson +--- + arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5io.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5io.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5io.dtsi +@@ -11,4 +11,4 @@ i2c_csi_dsi0: &i2c6 { // Note: This is f + symlink = "i2c-6"; + }; + +-i2c_csi_dsi: &i2c_csi_dsi0 { }; // The connector that needs no jumper to enable ++i2c_csi_dsi: &i2c_csi_dsi1 { }; // The connector that needs no jumper to enable diff --git a/target/linux/bcm27xx/patches-6.6/950-1420-dts-bcm2712-rpi-cm5-Remove-inaccessible-USB_OC_N.patch b/target/linux/bcm27xx/patches-6.6/950-1420-dts-bcm2712-rpi-cm5-Remove-inaccessible-USB_OC_N.patch new file mode 100644 index 0000000000..e2a01216a3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1420-dts-bcm2712-rpi-cm5-Remove-inaccessible-USB_OC_N.patch @@ -0,0 +1,25 @@ +From d128c123754e9dd03ad72c16851a1652331d6da1 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 27 Nov 2024 10:24:47 +0000 +Subject: [PATCH] dts: bcm2712-rpi-cm5: Remove inaccessible USB_OC_N + +Although VBUS_EN on GPIO42 appears on the CM5's 100-way headers, +USB_OC_N on GPIO43 does not. Remove the signal name to avoid further +confusion and disappointment. + +Signed-off-by: Phil Elwell +--- + arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi +@@ -718,7 +718,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + "-", // GPIO40 + "-", // GPIO41 + "USB_VBUS_EN", // GPIO42 +- "USB_OC_N", // GPIO43 ++ "-", // GPIO43 + "RP1_STAT_LED", // GPIO44 + "FAN_PWM", // GPIO45 + "-", // GPIO46 diff --git a/target/linux/bcm27xx/patches-6.6/950-1421-overlays-qca7000-replace-URL-with-textual-hint.patch b/target/linux/bcm27xx/patches-6.6/950-1421-overlays-qca7000-replace-URL-with-textual-hint.patch new file mode 100644 index 0000000000..8cdb2504a1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1421-overlays-qca7000-replace-URL-with-textual-hint.patch @@ -0,0 +1,33 @@ +From 77389e715039b1feac9c6261727600892cc12fdb Mon Sep 17 00:00:00 2001 +From: Michael Heimpold +Date: Fri, 29 Nov 2024 14:10:04 +0100 +Subject: [PATCH] overlays: qca7000: replace URL with textual hint + +The deep link into the website is not that stable, so let's +replace it with a textual description where to find the +product information. + +Signed-off-by: Michael Heimpold +--- + arch/arm/boot/dts/overlays/qca7000-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/qca7000-uart0-overlay.dts | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/overlays/qca7000-overlay.dts ++++ b/arch/arm/boot/dts/overlays/qca7000-overlay.dts +@@ -1,5 +1,5 @@ + // Overlay for the Qualcomm Atheros QCA7000 on PLC Stamp micro EVK +-// Visit: https://chargebyte.com/products/evaluation-tools/plc-stamp-micro-2-evaluation-board for details ++// Visit: https://chargebyte.com -> Controllers & Modules -> Evaluation Tools -> PLC Stamp Micro 2 Evaluation Board for details + + /dts-v1/; + /plugin/; +--- a/arch/arm/boot/dts/overlays/qca7000-uart0-overlay.dts ++++ b/arch/arm/boot/dts/overlays/qca7000-uart0-overlay.dts +@@ -1,5 +1,5 @@ + // Overlay for the Qualcomm Atheros QCA7000 on PLC Stamp micro EVK +-// Visit: https://in-tech-smartcharging.com/products/evaluation-tools/plc-stamp-micro-2-evaluation-board for details ++// Visit: https://chargebyte.com -> Controllers & Modules -> Evaluation Tools -> PLC Stamp Micro 2 Evaluation Board for details + + /dts-v1/; + /plugin/; diff --git a/target/linux/bcm27xx/patches-6.6/950-1422-dt-bindings-net-cdns-macb-Add-compatible-for-Raspber.patch b/target/linux/bcm27xx/patches-6.6/950-1422-dt-bindings-net-cdns-macb-Add-compatible-for-Raspber.patch new file mode 100644 index 0000000000..1364b4f713 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1422-dt-bindings-net-cdns-macb-Add-compatible-for-Raspber.patch @@ -0,0 +1,24 @@ +From 178f1c2747c3920723242f26ba290785d45bffae Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 11 Nov 2024 16:38:01 +0000 +Subject: [PATCH] dt-bindings: net: cdns,macb: Add compatible for Raspberry Pi + RP1 + +The Raspberry Pi RP1 chip has the Cadence GEM ethernet +controller, so add a compatible string for it. + +Signed-off-by: Dave Stevenson +--- + Documentation/devicetree/bindings/net/cdns,macb.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/net/cdns,macb.yaml ++++ b/Documentation/devicetree/bindings/net/cdns,macb.yaml +@@ -54,6 +54,7 @@ properties: + - cdns,np4-macb # NP4 SoC devices + - microchip,sama7g5-emac # Microchip SAMA7G5 ethernet interface + - microchip,sama7g5-gem # Microchip SAMA7G5 gigabit ethernet interface ++ - raspberrypi,rp1-gem # Raspberry Pi RP1 gigabit ethernet interface + - sifive,fu540-c000-gem # SiFive FU540-C000 SoC + - cdns,emac # Generic + - cdns,gem # Generic diff --git a/target/linux/bcm27xx/patches-6.6/950-1423-net-macb-Add-support-for-Raspberry-Pi-RP1-ethernet-c.patch b/target/linux/bcm27xx/patches-6.6/950-1423-net-macb-Add-support-for-Raspberry-Pi-RP1-ethernet-c.patch index 3941d69edf..6a9b7b36bd 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1423-net-macb-Add-support-for-Raspberry-Pi-RP1-ethernet-c.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1423-net-macb-Add-support-for-Raspberry-Pi-RP1-ethernet-c.patch @@ -1,8 +1,8 @@ From f9f0024bd9bf04a58b64bae356be4c04022d23bc Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 11 Nov 2024 16:40:07 +0000 -Subject: [PATCH 1423/1482] net: macb: Add support for Raspberry Pi RP1 - ethernet controller +Subject: [PATCH] net: macb: Add support for Raspberry Pi RP1 ethernet + controller The RP1 chip has the Cadence GEM block, but wants the tx_clock to always run at 125MHz, in the same way as sama7g5. diff --git a/target/linux/bcm27xx/patches-6.6/950-1424-rp1-clk-Only-set-PLL_SEC_RST-in-rp1_pll_divider_off.patch b/target/linux/bcm27xx/patches-6.6/950-1424-rp1-clk-Only-set-PLL_SEC_RST-in-rp1_pll_divider_off.patch index d3f216d31d..91d836f71c 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1424-rp1-clk-Only-set-PLL_SEC_RST-in-rp1_pll_divider_off.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1424-rp1-clk-Only-set-PLL_SEC_RST-in-rp1_pll_divider_off.patch @@ -1,8 +1,7 @@ From 33c225f622d596034a9261316666089a92aa6834 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 25 Nov 2024 12:30:06 +0000 -Subject: [PATCH 1424/1482] rp1: clk: Only set PLL_SEC_RST in - rp1_pll_divider_off +Subject: [PATCH] rp1: clk: Only set PLL_SEC_RST in rp1_pll_divider_off Rather than clearing all the bits in rp1_pll_divider_off and setting PLL_SEC_RST, retain the status of all the other diff --git a/target/linux/bcm27xx/patches-6.6/950-1425-rp1-clk-Rationalise-the-use-of-the-CLK_IS_CRITICAL-f.patch b/target/linux/bcm27xx/patches-6.6/950-1425-rp1-clk-Rationalise-the-use-of-the-CLK_IS_CRITICAL-f.patch index 247ae455ac..3f4850c899 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1425-rp1-clk-Rationalise-the-use-of-the-CLK_IS_CRITICAL-f.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1425-rp1-clk-Rationalise-the-use-of-the-CLK_IS_CRITICAL-f.patch @@ -1,8 +1,7 @@ From eb836a6a299322a8e2b9627cccd23c7a76d068ba Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Fri, 8 Nov 2024 17:36:13 +0000 -Subject: [PATCH 1425/1482] rp1: clk: Rationalise the use of the - CLK_IS_CRITICAL flag +Subject: [PATCH] rp1: clk: Rationalise the use of the CLK_IS_CRITICAL flag The clock setup had been copied from clk-bcm2835 which had to cope with the firmware having configured clocks, so there were flags diff --git a/target/linux/bcm27xx/patches-6.6/950-1426-dt-arm64-Fixup-RP1-ethernet-DT-configuration.patch b/target/linux/bcm27xx/patches-6.6/950-1426-dt-arm64-Fixup-RP1-ethernet-DT-configuration.patch index ad6569e99c..f213d8def6 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1426-dt-arm64-Fixup-RP1-ethernet-DT-configuration.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1426-dt-arm64-Fixup-RP1-ethernet-DT-configuration.patch @@ -1,7 +1,7 @@ From 0b4af929b7125abd3a262577b380c7c81ee9b1c5 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 11 Nov 2024 15:18:14 +0000 -Subject: [PATCH 1426/1482] dt: arm64: Fixup RP1 ethernet DT configuration +Subject: [PATCH] dt: arm64: Fixup RP1 ethernet DT configuration Configure RP1's ethernet block to do the correct thing. clk_eth is intended to be fixed at 125MHz, so use a new compatible, @@ -14,7 +14,7 @@ Signed-off-by: Dave Stevenson --- a/arch/arm64/boot/dts/broadcom/rp1.dtsi +++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi -@@ -24,6 +24,7 @@ +@@ -32,6 +32,7 @@ // RP1_PLL_VIDEO_CORE and dividers are now managed by VEC,DPI drivers <&rp1_clocks RP1_PLL_SYS>, <&rp1_clocks RP1_PLL_SYS_SEC>, @@ -22,7 +22,7 @@ Signed-off-by: Dave Stevenson <&rp1_clocks RP1_PLL_AUDIO>, <&rp1_clocks RP1_PLL_AUDIO_SEC>, <&rp1_clocks RP1_CLK_SYS>, -@@ -38,6 +39,7 @@ +@@ -46,6 +47,7 @@ <1536000000>, // RP1_PLL_AUDIO_CORE <200000000>, // RP1_PLL_SYS <125000000>, // RP1_PLL_SYS_SEC @@ -30,7 +30,7 @@ Signed-off-by: Dave Stevenson <61440000>, // RP1_PLL_AUDIO <192000000>, // RP1_PLL_AUDIO_SEC <200000000>, // RP1_CLK_SYS -@@ -968,12 +970,14 @@ +@@ -976,12 +978,14 @@ rp1_eth: ethernet@100000 { reg = <0xc0 0x40100000 0x0 0x4000>; diff --git a/target/linux/bcm27xx/patches-6.6/950-1427-clk-rp1-Add-RP1_CLK_DMA.patch b/target/linux/bcm27xx/patches-6.6/950-1427-clk-rp1-Add-RP1_CLK_DMA.patch index 9026cebaf9..b13becd187 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1427-clk-rp1-Add-RP1_CLK_DMA.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1427-clk-rp1-Add-RP1_CLK_DMA.patch @@ -1,7 +1,7 @@ From d4e41ed9954fa86c4774f98d393aa401c81a68e7 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 13 Nov 2024 13:10:27 +0000 -Subject: [PATCH 1427/1482] clk: rp1: Add RP1_CLK_DMA. +Subject: [PATCH] clk: rp1: Add RP1_CLK_DMA. The DMA block has a clock, but wasn't defined in the driver. This resulted in the parent being disabled as unused, and then DMA diff --git a/target/linux/bcm27xx/patches-6.6/950-1428-rp1-clk-Remove-CLK_IGNORE_UNUSED-flags.patch b/target/linux/bcm27xx/patches-6.6/950-1428-rp1-clk-Remove-CLK_IGNORE_UNUSED-flags.patch index 8fa06045a5..662a2485dd 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1428-rp1-clk-Remove-CLK_IGNORE_UNUSED-flags.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1428-rp1-clk-Remove-CLK_IGNORE_UNUSED-flags.patch @@ -1,7 +1,7 @@ From 9049e4df2c54b5e620f855f66db3a18c9f2e181f Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Fri, 8 Nov 2024 17:37:08 +0000 -Subject: [PATCH 1428/1482] rp1: clk: Remove CLK_IGNORE_UNUSED flags +Subject: [PATCH] rp1: clk: Remove CLK_IGNORE_UNUSED flags There should be no issue in disabling the RP1 clocks as long as the kernel knows about all consumers. diff --git a/target/linux/bcm27xx/patches-6.6/950-1429-dt-rp1-Use-clk_sys-for-ethernet-hclk-and-pclk.patch b/target/linux/bcm27xx/patches-6.6/950-1429-dt-rp1-Use-clk_sys-for-ethernet-hclk-and-pclk.patch index 6d0eb13389..937b125717 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1429-dt-rp1-Use-clk_sys-for-ethernet-hclk-and-pclk.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1429-dt-rp1-Use-clk_sys-for-ethernet-hclk-and-pclk.patch @@ -1,7 +1,7 @@ From 542d0f7f2e9f90fc0f02f8cb141f7c3fbf46081b Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 11 Nov 2024 17:11:18 +0000 -Subject: [PATCH 1429/1482] dt: rp1: Use clk_sys for ethernet hclk and pclk +Subject: [PATCH] dt: rp1: Use clk_sys for ethernet hclk and pclk hclk and pclk of the MAC are connected to clk_sys, so define them as being connected accordingly, rather than having fake @@ -14,7 +14,7 @@ Signed-off-by: Dave Stevenson --- a/arch/arm64/boot/dts/broadcom/rp1.dtsi +++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi -@@ -974,7 +974,8 @@ +@@ -982,7 +982,8 @@ #address-cells = <1>; #size-cells = <0>; interrupts = ; @@ -24,7 +24,7 @@ Signed-off-by: Dave Stevenson &rp1_clocks RP1_CLK_ETH_TSU &rp1_clocks RP1_CLK_ETH>; clock-names = "pclk", "hclk", "tsu_clk", "tx_clk"; -@@ -1195,18 +1196,6 @@ +@@ -1230,18 +1231,6 @@ clock-output-names = "xosc"; clock-frequency = <50000000>; }; diff --git a/target/linux/bcm27xx/patches-6.6/950-1430-dt-rp1-Link-RP1-DMA-to-the-associated-clock.patch b/target/linux/bcm27xx/patches-6.6/950-1430-dt-rp1-Link-RP1-DMA-to-the-associated-clock.patch index 36d4f8b723..623fcc6cc3 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1430-dt-rp1-Link-RP1-DMA-to-the-associated-clock.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1430-dt-rp1-Link-RP1-DMA-to-the-associated-clock.patch @@ -1,7 +1,7 @@ From efecbda4014b490e042c7fd090942b32316f9345 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 13 Nov 2024 13:11:33 +0000 -Subject: [PATCH 1430/1482] dt: rp1: Link RP1 DMA to the associated clock +Subject: [PATCH] dt: rp1: Link RP1 DMA to the associated clock This makes the kernel representation of the clock structure match reality. @@ -13,7 +13,7 @@ Signed-off-by: Dave Stevenson --- a/arch/arm64/boot/dts/broadcom/rp1.dtsi +++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi -@@ -1061,7 +1061,7 @@ +@@ -1081,7 +1081,7 @@ reg = <0xc0 0x40188000 0x0 0x1000>; compatible = "snps,axi-dma-1.01a"; interrupts = ; diff --git a/target/linux/bcm27xx/patches-6.6/950-1431-raspberrypi-firmware-Add-the-RPI-firmware-UART-APIs.patch b/target/linux/bcm27xx/patches-6.6/950-1431-raspberrypi-firmware-Add-the-RPI-firmware-UART-APIs.patch new file mode 100644 index 0000000000..7e518bff1c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1431-raspberrypi-firmware-Add-the-RPI-firmware-UART-APIs.patch @@ -0,0 +1,23 @@ +From eb035f3ad7da1324d310ef83b42398f47d5bafe7 Mon Sep 17 00:00:00 2001 +From: Tim Gover +Date: Fri, 1 Nov 2024 19:42:17 +0000 +Subject: [PATCH] raspberrypi-firmware: Add the RPI firmware UART APIs + +Add VideoCore mailbox definitions for the new RPi firmware UART. + +Signed-off-by: Tim Gover +--- + include/soc/bcm2835/raspberrypi-firmware.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -98,6 +98,8 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_GET_REBOOT_FLAGS = 0x00030064, + RPI_FIRMWARE_SET_REBOOT_FLAGS = 0x00038064, + RPI_FIRMWARE_NOTIFY_DISPLAY_DONE = 0x00030066, ++ RPI_FIRMWARE_GET_SW_UART = 0x0003008a, ++ RPI_FIRMWARE_SET_SW_UART = 0x0003808a, + + /* Dispmanx TAGS */ + RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, diff --git a/target/linux/bcm27xx/patches-6.6/950-1432-serial-core-Add-the-Raspberry-Pi-firmware-UART-id.patch b/target/linux/bcm27xx/patches-6.6/950-1432-serial-core-Add-the-Raspberry-Pi-firmware-UART-id.patch new file mode 100644 index 0000000000..5767f407fe --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1432-serial-core-Add-the-Raspberry-Pi-firmware-UART-id.patch @@ -0,0 +1,22 @@ +From b8a0e563fd181205565a0edaaebc82b1abf0c5be Mon Sep 17 00:00:00 2001 +From: Tim Gover +Date: Fri, 1 Nov 2024 19:43:21 +0000 +Subject: [PATCH] serial: core: Add the Raspberry Pi firmware UART id + +Assign a new serial core number for the RPi firmware UART. + +Signed-off-by: Tim Gover +--- + include/uapi/linux/serial_core.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/uapi/linux/serial_core.h ++++ b/include/uapi/linux/serial_core.h +@@ -245,4 +245,7 @@ + /* Sunplus UART */ + #define PORT_SUNPLUS 123 + ++/* RPi firmware UART */ ++#define PORT_RPI_FW 124 ++ + #endif /* _UAPILINUX_SERIAL_CORE_H */ diff --git a/target/linux/bcm27xx/patches-6.6/950-1433-serial-tty-Add-a-driver-for-the-RPi-firmware-UART.patch b/target/linux/bcm27xx/patches-6.6/950-1433-serial-tty-Add-a-driver-for-the-RPi-firmware-UART.patch new file mode 100644 index 0000000000..f26c1bee86 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1433-serial-tty-Add-a-driver-for-the-RPi-firmware-UART.patch @@ -0,0 +1,630 @@ +From 2548d954d78bca44c5cf430f8ea6de7c771312d7 Mon Sep 17 00:00:00 2001 +From: Tim Gover +Date: Wed, 28 Aug 2024 09:46:50 +0100 +Subject: [PATCH] serial: tty: Add a driver for the RPi firmware UART + +On Raspberry Pi 4 and earlier models the firmware provides +a low speed (up to 115200 baud) bit-bashed UART on arbitrary +GPIOs using the second VPU core. + +The firmware driver is designed to support 19200 baud. Higher +rates up to 115200 seem to work but there may be more jitter. + +This can be useful for debug or managing additional low +speed peripherals if the hardware PL011 and 8250 hardware +UARTs are already used for console / bluetooth. + +The firmware driver requires a fixed core clock frequency +and also requires the VPU PWM audio driver to be disabled +(dtparam=audio=off) + +Runtime configuration is handled via the vc-mailbox APIs +with the FIFO buffers being allocated in uncached VPU +addressable memory. The FIFO pointers are stored in spare +VideoCore multi-core sync registers in order to reduce the number +of uncached SDRAM accesses thereby reducing jitter. + +Signed-off-by: Tim Gover +--- + drivers/tty/serial/Kconfig | 11 + + drivers/tty/serial/Makefile | 1 + + drivers/tty/serial/rpi-fw-uart.c | 563 +++++++++++++++++++++++++++++++ + 3 files changed, 575 insertions(+) + create mode 100644 drivers/tty/serial/rpi-fw-uart.c + +--- a/drivers/tty/serial/Kconfig ++++ b/drivers/tty/serial/Kconfig +@@ -1578,6 +1578,17 @@ config SERIAL_NUVOTON_MA35D1_CONSOLE + but you can alter that using a kernel command line option such as + "console=ttyNVTx". + ++config SERIAL_RPI_FW ++ tristate "Raspberry Pi Firmware software UART support" ++ depends on ARM_AMBA || COMPILE_TEST ++ select SERIAL_CORE ++ help ++ This selects the Raspberry Pi firmware UART. This is a bit-bashed ++ implementation running on the Raspbery Pi VPU core. ++ This is not supported on Raspberry Pi 5 or newer platforms. ++ ++ If unsure, say N. ++ + endmenu + + config SERIAL_MCTRL_GPIO +--- a/drivers/tty/serial/Makefile ++++ b/drivers/tty/serial/Makefile +@@ -88,6 +88,7 @@ obj-$(CONFIG_SERIAL_MILBEAUT_USIO) += mi + obj-$(CONFIG_SERIAL_SIFIVE) += sifive.o + obj-$(CONFIG_SERIAL_LITEUART) += liteuart.o + obj-$(CONFIG_SERIAL_SUNPLUS) += sunplus-uart.o ++obj-$(CONFIG_SERIAL_RPI_FW) += rpi-fw-uart.o + + # GPIOLIB helpers for modem control lines + obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o +--- /dev/null ++++ b/drivers/tty/serial/rpi-fw-uart.c +@@ -0,0 +1,563 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2024, Raspberry Pi Ltd. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RPI_FW_UART_RX_FIFO_RD 0xb0 ++#define RPI_FW_UART_RX_FIFO_WR 0xb4 ++#define RPI_FW_UART_TX_FIFO_RD 0xb8 ++#define RPI_FW_UART_TX_FIFO_WR 0xbc ++ ++#define RPI_FW_UART_FIFO_SIZE 32 ++#define RPI_FW_UART_FIFO_SIZE_MASK (RPI_FW_UART_FIFO_SIZE - 1) ++ ++#define RPI_FW_UART_MIN_VERSION 3 ++ ++struct rpi_fw_uart_params { ++ u32 start; ++ u32 baud; ++ u32 data_bits; ++ u32 stop_bits; ++ u32 gpio_rx; ++ u32 gpio_tx; ++ u32 flags; ++ u32 fifosize; ++ u32 rx_buffer; ++ u32 tx_buffer; ++ u32 version; ++ u32 fifo_reg_base; ++}; ++ ++struct rpi_fw_uart { ++ struct uart_driver driver; ++ struct uart_port port; ++ struct rpi_firmware *firmware; ++ struct gpio_desc *rx_gpiod; ++ struct gpio_desc *tx_gpiod; ++ unsigned int rx_gpio; ++ unsigned int tx_gpio; ++ unsigned int baud; ++ unsigned int data_bits; ++ unsigned int stop_bits; ++ unsigned char __iomem *base; ++ size_t dma_buffer_size; ++ ++ struct hrtimer trigger_start_rx; ++ ktime_t rx_poll_delay; ++ void *rx_buffer; ++ dma_addr_t rx_buffer_dma_addr; ++ int rx_stop; ++ ++ void *tx_buffer; ++ dma_addr_t tx_buffer_dma_addr; ++}; ++ ++static unsigned int rpi_fw_uart_tx_is_full(struct uart_port *port) ++{ ++ struct rpi_fw_uart *rfu = container_of(port, struct rpi_fw_uart, port); ++ u32 rd, wr; ++ ++ rd = readl(rfu->base + RPI_FW_UART_TX_FIFO_RD); ++ wr = readl(rfu->base + RPI_FW_UART_TX_FIFO_WR); ++ return ((wr + 1) & RPI_FW_UART_FIFO_SIZE_MASK) == rd; ++} ++ ++static unsigned int rpi_fw_uart_tx_is_empty(struct uart_port *port) ++{ ++ struct rpi_fw_uart *rfu = container_of(port, struct rpi_fw_uart, port); ++ u32 rd, wr; ++ ++ if (!rfu->tx_buffer) ++ return 1; ++ ++ rd = readl(rfu->base + RPI_FW_UART_TX_FIFO_RD); ++ wr = readl(rfu->base + RPI_FW_UART_TX_FIFO_WR); ++ ++ return rd == wr; ++} ++ ++unsigned int rpi_fw_uart_rx_is_empty(struct uart_port *port) ++{ ++ struct rpi_fw_uart *rfu = container_of(port, struct rpi_fw_uart, port); ++ u32 rd, wr; ++ ++ if (!rfu->rx_buffer) ++ return 1; ++ ++ rd = readl(rfu->base + RPI_FW_UART_RX_FIFO_RD); ++ wr = readl(rfu->base + RPI_FW_UART_RX_FIFO_WR); ++ ++ return rd == wr; ++} ++ ++static unsigned int rpi_fw_uart_tx_empty(struct uart_port *port) ++{ ++ return rpi_fw_uart_tx_is_empty(port) ? TIOCSER_TEMT : 0; ++} ++ ++static void rpi_fw_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) ++{ ++ /* ++ * No hardware flow control, firmware automatically configures ++ * TX to output high and RX to input low. ++ */ ++ dev_dbg(port->dev, "%s mctrl %u\n", __func__, mctrl); ++} ++ ++static unsigned int rpi_fw_uart_get_mctrl(struct uart_port *port) ++{ ++ /* No hardware flow control */ ++ return TIOCM_CTS; ++} ++ ++static void rpi_fw_uart_stop(struct uart_port *port) ++{ ++ struct rpi_fw_uart_params msg = {.start = 0}; ++ struct rpi_fw_uart *rfu = container_of(port, struct rpi_fw_uart, port); ++ ++ hrtimer_cancel(&rfu->trigger_start_rx); ++ ++ if (rpi_firmware_property(rfu->firmware, ++ RPI_FIRMWARE_SET_SW_UART, ++ &msg, sizeof(msg))) ++ dev_warn(port->dev, ++ "Failed to shutdown rpi-fw uart. Firmware not configured?"); ++} ++ ++static void rpi_fw_uart_stop_tx(struct uart_port *port) ++{ ++ /* No supported by the current firmware APIs. */ ++} ++ ++static void rpi_fw_uart_stop_rx(struct uart_port *port) ++{ ++ struct rpi_fw_uart *rfu = container_of(port, struct rpi_fw_uart, port); ++ ++ rfu->rx_stop = 1; ++} ++ ++static unsigned int rpi_fw_write(struct uart_port *port, const char *s, ++ unsigned int count) ++{ ++ struct rpi_fw_uart *rfu = container_of(port, struct rpi_fw_uart, port); ++ u8 *out = rfu->tx_buffer; ++ unsigned int consumed = 0; ++ ++ while (consumed < count && !rpi_fw_uart_tx_is_full(port)) { ++ u32 wp = readl(rfu->base + RPI_FW_UART_TX_FIFO_WR) ++ & RPI_FW_UART_FIFO_SIZE_MASK; ++ out[wp] = s[consumed++]; ++ wp = (wp + 1) & RPI_FW_UART_FIFO_SIZE_MASK; ++ writel(wp, rfu->base + RPI_FW_UART_TX_FIFO_WR); ++ } ++ return consumed; ++} ++ ++/* Called with port.lock taken */ ++static void rpi_fw_uart_start_tx(struct uart_port *port) ++{ ++ struct circ_buf *xmit; ++ ++ xmit = &port->state->xmit; ++ for (;;) { ++ unsigned int consumed; ++ unsigned long count = CIRC_CNT_TO_END(xmit->head, xmit->tail, ++ UART_XMIT_SIZE); ++ if (!count) ++ break; ++ ++ consumed = rpi_fw_write(port, &xmit->buf[xmit->tail], count); ++ uart_xmit_advance(port, consumed); ++ } ++ uart_write_wakeup(port); ++} ++ ++/* Called with port.lock taken */ ++static void rpi_fw_uart_start_rx(struct uart_port *port) ++{ ++ struct tty_port *tty_port = &port->state->port; ++ struct rpi_fw_uart *rfu = container_of(port, struct rpi_fw_uart, port); ++ int count = 0; ++ ++ /* ++ * RX is polled, read up to a full buffer of data before trying again ++ * so that this can be interrupted if the firmware is filling the ++ * buffer too fast ++ */ ++ while (!rpi_fw_uart_rx_is_empty(port) && count < port->fifosize) { ++ const u8 *in = rfu->rx_buffer; ++ u32 rp = readl(rfu->base + RPI_FW_UART_RX_FIFO_RD) ++ & RPI_FW_UART_FIFO_SIZE_MASK; ++ ++ tty_insert_flip_char(tty_port, in[rp], TTY_NORMAL); ++ rp = (rp + 1) & RPI_FW_UART_FIFO_SIZE_MASK; ++ writel(rp, rfu->base + RPI_FW_UART_RX_FIFO_RD); ++ count++; ++ } ++ if (count) ++ tty_flip_buffer_push(tty_port); ++} ++ ++static enum hrtimer_restart rpi_fw_uart_trigger_rx(struct hrtimer *t) ++{ ++ unsigned long flags; ++ struct rpi_fw_uart *rfu = container_of(t, struct rpi_fw_uart, ++ trigger_start_rx); ++ ++ spin_lock_irqsave(&rfu->port.lock, flags); ++ if (rfu->rx_stop) { ++ spin_unlock_irqrestore(&rfu->port.lock, flags); ++ return HRTIMER_NORESTART; ++ } ++ ++ rpi_fw_uart_start_rx(&rfu->port); ++ spin_unlock_irqrestore(&rfu->port.lock, flags); ++ hrtimer_forward_now(t, rfu->rx_poll_delay); ++ return HRTIMER_RESTART; ++} ++ ++static void rpi_fw_uart_break_ctl(struct uart_port *port, int ctl) ++{ ++ dev_dbg(port->dev, "%s ctl %d\n", __func__, ctl); ++} ++ ++static int rpi_fw_uart_configure(struct uart_port *port) ++{ ++ struct rpi_fw_uart *rfu = container_of(port, struct rpi_fw_uart, port); ++ struct rpi_fw_uart_params msg; ++ unsigned long flags; ++ int rc; ++ ++ rpi_fw_uart_stop(port); ++ ++ memset(&msg, 0, sizeof(msg)); ++ msg.start = 1; ++ msg.gpio_rx = rfu->rx_gpio; ++ msg.gpio_tx = rfu->tx_gpio; ++ msg.data_bits = rfu->data_bits; ++ msg.stop_bits = rfu->stop_bits; ++ msg.baud = rfu->baud; ++ msg.fifosize = RPI_FW_UART_FIFO_SIZE; ++ msg.rx_buffer = (u32) rfu->rx_buffer_dma_addr; ++ msg.tx_buffer = (u32) rfu->tx_buffer_dma_addr; ++ ++ rfu->rx_poll_delay = ms_to_ktime(50); ++ ++ /* ++ * Reconfigures the firmware UART with the new settings. On the first ++ * call retrieve the addresses of the FIFO buffers. The buffers are ++ * allocated at startup and are not de-allocated. ++ * NB rpi_firmware_property can block ++ */ ++ rc = rpi_firmware_property(rfu->firmware, ++ RPI_FIRMWARE_SET_SW_UART, ++ &msg, sizeof(msg)); ++ if (rc) ++ goto fail; ++ ++ rc = rpi_firmware_property(rfu->firmware, ++ RPI_FIRMWARE_GET_SW_UART, ++ &msg, sizeof(msg)); ++ if (rc) ++ goto fail; ++ ++ dev_dbg(port->dev, "version %08x, reg addr %x\n", msg.version, ++ msg.fifo_reg_base); ++ ++ dev_info(port->dev, "started %d baud %u data %u stop %u rx %u tx %u flags %u fifosize %u\n", ++ msg.start, msg.baud, msg.data_bits, msg.stop_bits, ++ msg.gpio_rx, msg.gpio_tx, msg.flags, msg.fifosize); ++ ++ if (msg.fifosize != port->fifosize) { ++ dev_err(port->dev, "Expected fifo size %u actual %u", ++ port->fifosize, msg.fifosize); ++ rc = -EINVAL; ++ goto fail; ++ } ++ ++ if (!msg.start) { ++ dev_err(port->dev, "Firmware service not running\n"); ++ rc = -EINVAL; ++ } ++ ++ spin_lock_irqsave(&rfu->port.lock, flags); ++ rfu->rx_stop = 0; ++ hrtimer_start(&rfu->trigger_start_rx, ++ rfu->rx_poll_delay, HRTIMER_MODE_REL); ++ spin_unlock_irqrestore(&rfu->port.lock, flags); ++ return 0; ++fail: ++ dev_err(port->dev, "Failed to configure rpi-fw uart. Firmware not configured?"); ++ return rc; ++} ++ ++static void rpi_fw_uart_free_buffers(struct uart_port *port) ++{ ++ struct rpi_fw_uart *rfu = container_of(port, struct rpi_fw_uart, port); ++ ++ if (rfu->rx_buffer) ++ dma_free_coherent(port->dev, rfu->dma_buffer_size, ++ rfu->rx_buffer, GFP_ATOMIC); ++ ++ if (rfu->tx_buffer) ++ dma_free_coherent(port->dev, rfu->dma_buffer_size, ++ rfu->tx_buffer, GFP_ATOMIC); ++ ++ rfu->rx_buffer = NULL; ++ rfu->tx_buffer = NULL; ++ rfu->rx_buffer_dma_addr = 0; ++ rfu->tx_buffer_dma_addr = 0; ++} ++ ++static int rpi_fw_uart_alloc_buffers(struct uart_port *port) ++{ ++ struct rpi_fw_uart *rfu = container_of(port, struct rpi_fw_uart, port); ++ ++ if (rfu->tx_buffer) ++ return 0; ++ ++ rfu->dma_buffer_size = PAGE_ALIGN(RPI_FW_UART_FIFO_SIZE); ++ ++ rfu->rx_buffer = dma_alloc_coherent(port->dev, rfu->dma_buffer_size, ++ &rfu->rx_buffer_dma_addr, GFP_ATOMIC); ++ ++ if (!rfu->rx_buffer) ++ goto alloc_fail; ++ ++ rfu->tx_buffer = dma_alloc_coherent(port->dev, rfu->dma_buffer_size, ++ &rfu->tx_buffer_dma_addr, GFP_ATOMIC); ++ ++ if (!rfu->tx_buffer) ++ goto alloc_fail; ++ ++ dev_dbg(port->dev, "alloc-buffers %p %x %p %x\n", ++ rfu->rx_buffer, (u32) rfu->rx_buffer_dma_addr, ++ rfu->tx_buffer, (u32) rfu->tx_buffer_dma_addr); ++ return 0; ++ ++alloc_fail: ++ dev_err(port->dev, "%s uart buffer allocation failed\n", __func__); ++ rpi_fw_uart_free_buffers(port); ++ return -ENOMEM; ++} ++ ++static int rpi_fw_uart_startup(struct uart_port *port) ++{ ++ int rc; ++ ++ rc = rpi_fw_uart_alloc_buffers(port); ++ if (rc) ++ dev_err(port->dev, "Failed to start\n"); ++ return rc; ++} ++ ++static void rpi_fw_uart_shutdown(struct uart_port *port) ++{ ++ rpi_fw_uart_stop(port); ++ rpi_fw_uart_free_buffers(port); ++} ++ ++static void rpi_fw_uart_set_termios(struct uart_port *port, ++ struct ktermios *new, ++ const struct ktermios *old) ++{ ++ struct rpi_fw_uart *rfu = ++ container_of(port, struct rpi_fw_uart, port); ++ rfu->baud = uart_get_baud_rate(port, new, old, 50, 115200); ++ rfu->stop_bits = (new->c_cflag & CSTOPB) ? 2 : 1; ++ ++ rpi_fw_uart_configure(port); ++} ++ ++static const struct uart_ops rpi_fw_uart_ops = { ++ .tx_empty = rpi_fw_uart_tx_empty, ++ .set_mctrl = rpi_fw_uart_set_mctrl, ++ .get_mctrl = rpi_fw_uart_get_mctrl, ++ .stop_rx = rpi_fw_uart_stop_rx, ++ .stop_tx = rpi_fw_uart_stop_tx, ++ .start_tx = rpi_fw_uart_start_tx, ++ .break_ctl = rpi_fw_uart_break_ctl, ++ .startup = rpi_fw_uart_startup, ++ .shutdown = rpi_fw_uart_shutdown, ++ .set_termios = rpi_fw_uart_set_termios, ++}; ++ ++static int rpi_fw_uart_get_gpio_offset(struct device *dev, const char *name) ++{ ++ struct of_phandle_args of_args = { 0 }; ++ bool is_bcm28xx; ++ ++ /* This really shouldn't fail, given that we have a gpiod */ ++ if (of_parse_phandle_with_args(dev->of_node, name, "#gpio-cells", 0, &of_args)) ++ return dev_err_probe(dev, -EINVAL, "can't find gpio declaration\n"); ++ ++ is_bcm28xx = of_device_is_compatible(of_args.np, "brcm,bcm2835-gpio") || ++ of_device_is_compatible(of_args.np, "brcm,bcm2711-gpio"); ++ of_node_put(of_args.np); ++ if (!is_bcm28xx || of_args.args_count != 2) ++ return dev_err_probe(dev, -EINVAL, "not a BCM28xx gpio\n"); ++ ++ return of_args.args[0]; ++} ++ ++static int rpi_fw_uart_probe(struct platform_device *pdev) ++{ ++ struct device_node *firmware_node; ++ struct device *dev = &pdev->dev; ++ struct rpi_firmware *firmware; ++ struct uart_port *port; ++ struct rpi_fw_uart *rfu; ++ struct rpi_fw_uart_params msg; ++ int version_major; ++ int err; ++ ++ dev_dbg(dev, "%s of_node %p\n", __func__, dev->of_node); ++ ++ /* ++ * We can be probed either through the an old-fashioned ++ * platform device registration or through a DT node that is a ++ * child of the firmware node. Handle both cases. ++ */ ++ if (dev->of_node) ++ firmware_node = of_parse_phandle(dev->of_node, "firmware", 0); ++ else ++ firmware_node = of_find_compatible_node(NULL, NULL, ++ "raspberrypi,bcm2835-firmware"); ++ if (!firmware_node) { ++ dev_err(dev, "Missing firmware node\n"); ++ return -ENOENT; ++ } ++ ++ firmware = devm_rpi_firmware_get(dev, firmware_node); ++ of_node_put(firmware_node); ++ if (!firmware) ++ return -EPROBE_DEFER; ++ ++ rfu = devm_kzalloc(dev, sizeof(*rfu), GFP_KERNEL); ++ if (!rfu) ++ return -ENOMEM; ++ ++ rfu->firmware = firmware; ++ ++ err = rpi_firmware_property(rfu->firmware, RPI_FIRMWARE_GET_SW_UART, ++ &msg, sizeof(msg)); ++ if (err) { ++ dev_err(dev, "VC firmware does not support rpi-fw-uart\n"); ++ return err; ++ } ++ ++ version_major = msg.version >> 16; ++ if (msg.version < RPI_FW_UART_MIN_VERSION) { ++ dev_err(dev, "rpi-fw-uart fw version %d is too old min version %d\n", ++ version_major, RPI_FW_UART_MIN_VERSION); ++ return -EINVAL; ++ } ++ ++ rfu->rx_gpiod = devm_gpiod_get(dev, "rx", GPIOD_IN); ++ if (IS_ERR(rfu->rx_gpiod)) ++ return PTR_ERR(rfu->rx_gpiod); ++ ++ rfu->tx_gpiod = devm_gpiod_get(dev, "tx", GPIOD_OUT_HIGH); ++ if (IS_ERR(rfu->tx_gpiod)) ++ return PTR_ERR(rfu->tx_gpiod); ++ ++ rfu->rx_gpio = rpi_fw_uart_get_gpio_offset(dev, "rx-gpios"); ++ if (rfu->rx_gpio < 0) ++ return rfu->rx_gpio; ++ rfu->tx_gpio = rpi_fw_uart_get_gpio_offset(dev, "tx-gpios"); ++ if (rfu->tx_gpio < 0) ++ return rfu->tx_gpio; ++ ++ rfu->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(rfu->base)) ++ return PTR_ERR(rfu->base); ++ ++ /* setup the driver */ ++ rfu->driver.owner = THIS_MODULE; ++ rfu->driver.driver_name = "ttyRFU"; ++ rfu->driver.dev_name = "ttyRFU"; ++ rfu->driver.nr = 1; ++ rfu->data_bits = 8; ++ ++ /* RX is polled */ ++ hrtimer_init(&rfu->trigger_start_rx, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ rfu->trigger_start_rx.function = rpi_fw_uart_trigger_rx; ++ ++ err = uart_register_driver(&rfu->driver); ++ if (err) { ++ dev_err(dev, "failed to register UART driver: %d\n", ++ err); ++ return err; ++ } ++ ++ /* setup the port */ ++ port = &rfu->port; ++ spin_lock_init(&port->lock); ++ port->dev = &pdev->dev; ++ port->type = PORT_RPI_FW; ++ port->ops = &rpi_fw_uart_ops; ++ port->fifosize = RPI_FW_UART_FIFO_SIZE; ++ port->iotype = UPIO_MEM; ++ port->flags = UPF_BOOT_AUTOCONF; ++ port->private_data = rfu; ++ ++ err = uart_add_one_port(&rfu->driver, port); ++ if (err) { ++ dev_err(dev, "failed to add UART port: %d\n", err); ++ goto unregister_uart; ++ } ++ platform_set_drvdata(pdev, rfu); ++ ++ dev_info(dev, "version %d.%d gpios tx %u rx %u\n", ++ msg.version >> 16, msg.version & 0xffff, ++ rfu->tx_gpio, rfu->rx_gpio); ++ return 0; ++ ++unregister_uart: ++ uart_unregister_driver(&rfu->driver); ++ ++ return err; ++} ++ ++static int rpi_fw_uart_remove(struct platform_device *pdev) ++{ ++ struct rpi_fw_uart *rfu = platform_get_drvdata(pdev); ++ ++ uart_remove_one_port(&rfu->driver, &rfu->port); ++ uart_unregister_driver(&rfu->driver); ++ ++ return 0; ++} ++ ++static const struct of_device_id rpi_fw_match[] = { ++ { .compatible = "raspberrypi,firmware-uart" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, rpi_fw_match); ++ ++static struct platform_driver rpi_fw_driver = { ++ .driver = { ++ .name = "rpi_fw-uart", ++ .of_match_table = rpi_fw_match, ++ }, ++ .probe = rpi_fw_uart_probe, ++ .remove = rpi_fw_uart_remove, ++}; ++module_platform_driver(rpi_fw_driver); ++ ++MODULE_AUTHOR("Tim Gover "); ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Raspberry Pi Firmware Software UART driver"); diff --git a/target/linux/bcm27xx/patches-6.6/950-1435-dtoverlay-Add-an-overlay-for-the-Raspberry-Pi-firmwa.patch b/target/linux/bcm27xx/patches-6.6/950-1435-dtoverlay-Add-an-overlay-for-the-Raspberry-Pi-firmwa.patch new file mode 100644 index 0000000000..0e4b3e3747 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1435-dtoverlay-Add-an-overlay-for-the-Raspberry-Pi-firmwa.patch @@ -0,0 +1,95 @@ +From b6b126861062020fb50859c5af71d8846ce43d7c Mon Sep 17 00:00:00 2001 +From: Tim Gover +Date: Mon, 4 Nov 2024 13:44:10 +0000 +Subject: [PATCH] dtoverlay: Add an overlay for the Raspberry Pi firmware UART + +Add a device-tree overlay to configure the GPIOs for the +Raspberry Pi firmware UART. + +Example config.txt +dtoverlay=rpi-fw-uart,txd0_pin=20,rxd0_pin=21 + +Signed-off-by: Phil Elwell +Signed-off-by: Tim Gover +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 12 ++++++ + .../boot/dts/overlays/rpi-fw-uart-overlay.dts | 41 +++++++++++++++++++ + 3 files changed, 54 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/rpi-fw-uart-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -233,6 +233,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + rpi-dacpro.dtbo \ + rpi-digiampplus.dtbo \ + rpi-ft5406.dtbo \ ++ rpi-fw-uart.dtbo \ + rpi-poe.dtbo \ + rpi-poe-plus.dtbo \ + rpi-sense.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -4141,6 +4141,18 @@ Params: touchscreen-size-x Touchscr + touchscreen-swapped-x-y Swap X and Y cordinates (default 0); + + ++Name: rpi-fw-uart ++Info: Configures the firmware software UART driver. ++ This driver requires exclusive usage of the second VPU core. The ++ following config.txt entries should be set when this driver is used. ++ dtparam=audio=off ++ isp_use_vpu0=1 ++Load: dtoverlay=rpi-fw-uart,[=] ++Params: txd0_pin GPIO pin for TXD0 (any free - default 20) ++ ++ rxd0_pin GPIO pin for RXD0 (any free - default 21) ++ ++ + Name: rpi-poe + Info: Raspberry Pi PoE HAT fan + Load: dtoverlay=rpi-poe,[=] +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-fw-uart-overlay.dts +@@ -0,0 +1,41 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// Overlay for the Raspberry Pi Firmware UART driver ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2835"; ++ ++ fragment@0 { ++ target = <&gpio>; ++ __overlay__ { ++ rpi_fw_uart_pins: rpi_fw_uart_pins@4 { ++ brcm,pins = <20 21>; ++ brcm,function = <1 0>; /* output input */ ++ brcm,pull = <0 2>; /* none pull-up */ ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&soc>; ++ __overlay__ { ++ rpi_fw_uart: rpi_fw_uart@7e000000 { ++ compatible = "raspberrypi,firmware-uart"; ++ reg = <0x7e000000 0x100>; /* VideoCore MS sync regs */ ++ firmware = <&firmware>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rpi_fw_uart_pins>; ++ tx-gpios = <&gpio 20 0>; ++ rx-gpios = <&gpio 21 0>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ txd0_pin = <&rpi_fw_uart>,"tx-gpios:4", ++ <&rpi_fw_uart_pins>, "brcm,pins:0"; ++ rxd0_pin = <&rpi_fw_uart>,"rx-gpios:4", ++ <&rpi_fw_uart_pins>, "brcm,pins:4"; ++ }; ++}; diff --git a/target/linux/bcm27xx/patches-6.6/950-1436-ARM-dts-Remove-duplicate-tags.patch b/target/linux/bcm27xx/patches-6.6/950-1436-ARM-dts-Remove-duplicate-tags.patch new file mode 100644 index 0000000000..7829a4b753 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1436-ARM-dts-Remove-duplicate-tags.patch @@ -0,0 +1,142 @@ +From 1993b453dc4a62378e90d91e9e0006a6c085f38a Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 18 Sep 2024 10:23:41 +0100 +Subject: [PATCH] ARM: dts: Remove duplicate tags + +A dts file should have exactly one /dts-v1/ tag, and overlays should +also have one /plugin/ tag. Through careless inclusion of other files, +some Device Trees and overlays end up with duplicated tags - this +commit removes them. + +The change is largely cosmetic, unless using an old version of dtc. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/broadcom/bcm2711-rpi-400.dts | 1 - + arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi | 3 --- + arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi | 2 -- + arch/arm/boot/dts/overlays/pisound-pi5-overlay.dts | 3 --- + arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts | 3 --- + arch/arm/boot/dts/overlays/vc4-fkms-v3d-pi4-overlay.dts | 3 --- + arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 3 --- + arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts | 3 --- + arch/arm/boot/dts/overlays/w1-gpio-pi5-overlay.dts | 3 --- + arch/arm/boot/dts/overlays/w1-gpio-pullup-pi5-overlay.dts | 3 --- + arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi | 1 - + 11 files changed, 28 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/bcm2711-rpi-400.dts ++++ b/arch/arm/boot/dts/broadcom/bcm2711-rpi-400.dts +@@ -1,5 +1,4 @@ + // SPDX-License-Identifier: GPL-2.0 +-/dts-v1/; + #include "bcm2711-rpi-4-b.dts" + + / { +--- a/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi ++++ b/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi +@@ -1,7 +1,4 @@ + // Definitions for I2C based sensors using the Industrial IO or HWMON interface. +-/dts-v1/; +-/plugin/; +- + #include + + / { +--- a/arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi ++++ b/arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi +@@ -1,8 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-only + // Partial definitions for IMX290 or IMX327 camera module on VC I2C bus + // The compatible string should be set in an overlay that then includes this one +-/dts-v1/; +-/plugin/; + + #include + +--- a/arch/arm/boot/dts/overlays/pisound-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pisound-pi5-overlay.dts +@@ -17,9 +17,6 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +-/dts-v1/; +-/plugin/; +- + #include "pisound-overlay.dts" + + &pisound_spi { +--- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts +@@ -2,9 +2,6 @@ + * vc4-fkms-v3d-overlay.dts + */ + +-/dts-v1/; +-/plugin/; +- + #include "cma-overlay.dts" + + / { +--- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-pi4-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-pi4-overlay.dts +@@ -2,9 +2,6 @@ + * vc4-fkms-v3d-overlay.dts + */ + +-/dts-v1/; +-/plugin/; +- + #include "cma-overlay.dts" + + &frag0 { +--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts +@@ -2,9 +2,6 @@ + * vc4-kms-v3d-overlay.dts + */ + +-/dts-v1/; +-/plugin/; +- + #include + + #include "cma-overlay.dts" +--- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi4-overlay.dts +@@ -2,9 +2,6 @@ + * vc4-kms-v3d-pi4-overlay.dts + */ + +-/dts-v1/; +-/plugin/; +- + #include + + #include "cma-overlay.dts" +--- a/arch/arm/boot/dts/overlays/w1-gpio-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/w1-gpio-pi5-overlay.dts +@@ -1,6 +1,3 @@ +-/dts-v1/; +-/plugin/; +- + #include "w1-gpio-overlay.dts" + + / { +--- a/arch/arm/boot/dts/overlays/w1-gpio-pullup-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/w1-gpio-pullup-pi5-overlay.dts +@@ -1,6 +1,3 @@ +-/dts-v1/; +-/plugin/; +- + #include "w1-gpio-pullup-overlay.dts" + + / { +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi +@@ -1,5 +1,4 @@ + // SPDX-License-Identifier: GPL-2.0 +-/dts-v1/; + + #include "bcm2712-rpi-cm5.dtsi" + diff --git a/target/linux/bcm27xx/patches-6.6/950-1437-Allow-setting-I-C-clock-frequency-via-i2c_arm_baudra.patch b/target/linux/bcm27xx/patches-6.6/950-1437-Allow-setting-I-C-clock-frequency-via-i2c_arm_baudra.patch new file mode 100644 index 0000000000..1d14a0bfec --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1437-Allow-setting-I-C-clock-frequency-via-i2c_arm_baudra.patch @@ -0,0 +1,25 @@ +From e33702e5e5fe9fef6ec967961e2e5e1c2285ba36 Mon Sep 17 00:00:00 2001 +From: gtrainavicius +Date: Wed, 4 Dec 2024 11:18:14 +0200 +Subject: [PATCH] =?UTF-8?q?Allow=20setting=20I=C2=B2C=20clock=20frequency?= + =?UTF-8?q?=20via=20i2c=5Farm=5Fbaudrate=20dtparam=20when=20using=20pimidi?= + =?UTF-8?q?=20overlay.?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This change removes the forced 1MHz clock frequency, so it can be overridden using `i2c_arm_baudrate`. +--- + arch/arm/boot/dts/overlays/pimidi-overlay.dts | 1 - + 1 file changed, 1 deletion(-) + +--- a/arch/arm/boot/dts/overlays/pimidi-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pimidi-overlay.dts +@@ -26,7 +26,6 @@ + target = <&i2c_arm>; + __overlay__ { + status = "okay"; +- clock-frequency=<1000000>; + + pimidi_ctrl: pimidi_ctrl@20 { + compatible = "blokaslabs,pimidi"; diff --git a/target/linux/bcm27xx/patches-6.6/950-1438-nvme-pci-Disable-Host-Memory-Buffer-usage.patch b/target/linux/bcm27xx/patches-6.6/950-1438-nvme-pci-Disable-Host-Memory-Buffer-usage.patch new file mode 100644 index 0000000000..4f1ea9249c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1438-nvme-pci-Disable-Host-Memory-Buffer-usage.patch @@ -0,0 +1,48 @@ +From fda47c026dee7acd975ee2c0f7a440d4038cfaa3 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 3 Dec 2024 15:57:01 +0000 +Subject: [PATCH] nvme-pci: Disable Host Memory Buffer usage + +Some NVME drives seem to request significant amounts of DMA coherent +memory - enough to exhaust our standard 64MB CMA allocation. + +Try disabling the feature to see what effect it has - drives should +continue to function without it. + +Link: https://github.com/raspberrypi/linux/issues/6504 + +Signed-off-by: Phil Elwell +--- + drivers/nvme/host/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -1932,6 +1932,7 @@ static void nvme_free_host_mem(struct nv + dev->nr_host_mem_descs = 0; + } + ++#if 0 + static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred, + u32 chunk_size) + { +@@ -2000,9 +2001,11 @@ out: + dev->host_mem_descs = NULL; + return -ENOMEM; + } ++#endif + + static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred) + { ++#if 0 + u64 min_chunk = min_t(u64, preferred, PAGE_SIZE * MAX_ORDER_NR_PAGES); + u64 hmminds = max_t(u32, dev->ctrl.hmminds * 4096, PAGE_SIZE * 2); + u64 chunk_size; +@@ -2015,6 +2018,7 @@ static int nvme_alloc_host_mem(struct nv + nvme_free_host_mem(dev); + } + } ++#endif + + return -ENOMEM; + } diff --git a/target/linux/bcm27xx/patches-6.6/950-1439-fixup-serial-tty-Add-a-driver-for-the-RPi-firmware-U.patch b/target/linux/bcm27xx/patches-6.6/950-1439-fixup-serial-tty-Add-a-driver-for-the-RPi-firmware-U.patch new file mode 100644 index 0000000000..0f18dc4a8d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1439-fixup-serial-tty-Add-a-driver-for-the-RPi-firmware-U.patch @@ -0,0 +1,23 @@ +From 0313a0961b685973f7833017479a277e3a4c05a4 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 4 Dec 2024 14:40:59 +0000 +Subject: [PATCH] fixup! serial: tty: Add a driver for the RPi firmware UART + +Make SERIAL_RPI_FW depend on RASPBERRYPI_FIRMWARE. + +Signed-off-by: Phil Elwell +--- + drivers/tty/serial/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/tty/serial/Kconfig ++++ b/drivers/tty/serial/Kconfig +@@ -1580,7 +1580,7 @@ config SERIAL_NUVOTON_MA35D1_CONSOLE + + config SERIAL_RPI_FW + tristate "Raspberry Pi Firmware software UART support" +- depends on ARM_AMBA || COMPILE_TEST ++ depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST + select SERIAL_CORE + help + This selects the Raspberry Pi firmware UART. This is a bit-bashed diff --git a/target/linux/bcm27xx/patches-6.6/950-1440-serial-rpi-fw-uart-Demote-debug-log-messages.patch b/target/linux/bcm27xx/patches-6.6/950-1440-serial-rpi-fw-uart-Demote-debug-log-messages.patch new file mode 100644 index 0000000000..271f743286 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1440-serial-rpi-fw-uart-Demote-debug-log-messages.patch @@ -0,0 +1,28 @@ +From 0a5be0fe6ba3a981508421131def7eab55d6d75c Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 5 Dec 2024 12:08:23 +0000 +Subject: [PATCH] serial: rpi-fw-uart: Demote debug log messages + +A dev_info call in rpi_fw_uart_configure causes kernel log output every +time one opens the UART. Demote it to dev_dbg. + +Signed-off-by: Phil Elwell +--- + drivers/tty/serial/rpi-fw-uart.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/tty/serial/rpi-fw-uart.c ++++ b/drivers/tty/serial/rpi-fw-uart.c +@@ -277,9 +277,9 @@ static int rpi_fw_uart_configure(struct + dev_dbg(port->dev, "version %08x, reg addr %x\n", msg.version, + msg.fifo_reg_base); + +- dev_info(port->dev, "started %d baud %u data %u stop %u rx %u tx %u flags %u fifosize %u\n", +- msg.start, msg.baud, msg.data_bits, msg.stop_bits, +- msg.gpio_rx, msg.gpio_tx, msg.flags, msg.fifosize); ++ dev_dbg(port->dev, "started %d baud %u data %u stop %u rx %u tx %u flags %u fifosize %u\n", ++ msg.start, msg.baud, msg.data_bits, msg.stop_bits, ++ msg.gpio_rx, msg.gpio_tx, msg.flags, msg.fifosize); + + if (msg.fifosize != port->fifosize) { + dev_err(port->dev, "Expected fifo size %u actual %u", diff --git a/target/linux/bcm27xx/patches-6.6/950-1441-dtoverlays-Add-Arducam-override-for-ov9281.patch b/target/linux/bcm27xx/patches-6.6/950-1441-dtoverlays-Add-Arducam-override-for-ov9281.patch new file mode 100644 index 0000000000..354ff961fe --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1441-dtoverlays-Add-Arducam-override-for-ov9281.patch @@ -0,0 +1,55 @@ +From 02dee262a9c7295ea514e9db7b9aa4b239922cb3 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 2 Dec 2024 15:41:21 +0000 +Subject: [PATCH] dtoverlays: Add Arducam override for ov9281 + +The Arducam module is slow starting up, so add an override +to slow the regulator down. +https://forums.raspberrypi.com/viewtopic.php?t=380236 + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/overlays/README | 2 ++ + arch/arm/boot/dts/overlays/ov9281-overlay.dts | 13 ++++++++++++- + 2 files changed, 14 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -3538,6 +3538,8 @@ Params: rotation Mounting + configuring the sensor (default on) + cam0 Adopt the default configuration for CAM0 on a + Compute Module (CSI0, i2c_vc, and cam0_reg). ++ arducam Slow down the regulator for slow Arducam ++ modules. + + + Name: papirus +--- a/arch/arm/boot/dts/overlays/ov9281-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov9281-overlay.dts +@@ -57,6 +57,14 @@ + }; + }; + ++ reg_frag: fragment@5 { ++ target = <&cam1_reg>; ++ __dormant__ { ++ startup-delay-us = <20000>; ++ off-on-delay-us = <30000>; ++ }; ++ }; ++ + __overrides__ { + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; +@@ -65,7 +73,10 @@ + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +- <&cam_node>, "avdd-supply:0=",<&cam0_reg>; ++ <&cam_node>, "avdd-supply:0=",<&cam0_reg>, ++ <®_frag>, "target:0=",<&cam0_reg>; ++ arducam = <0>, "+5"; ++ + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.6/950-1442-drivers-input-touchscreen-Add-support-for-no-irq-to-.patch b/target/linux/bcm27xx/patches-6.6/950-1442-drivers-input-touchscreen-Add-support-for-no-irq-to-.patch new file mode 100644 index 0000000000..d13982e9ba --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1442-drivers-input-touchscreen-Add-support-for-no-irq-to-.patch @@ -0,0 +1,118 @@ +From 97638920f1a40e2e0cab363d1e03837ff50c5478 Mon Sep 17 00:00:00 2001 +From: eng33 +Date: Thu, 5 Dec 2024 17:19:23 +0800 +Subject: [PATCH] drivers:input:touchscreen: Add support for no irq to ili210x + driver + +Signed-off-by: eng33 +--- + drivers/input/touchscreen/ili210x.c | 63 ++++++++++++++++++++++++----- + 1 file changed, 52 insertions(+), 11 deletions(-) + +--- a/drivers/input/touchscreen/ili210x.c ++++ b/drivers/input/touchscreen/ili210x.c +@@ -67,6 +67,8 @@ struct ili210x { + u8 version_proto[2]; + u8 ic_mode[2]; + bool stop; ++ struct timer_list poll_timer; ++ struct work_struct poll_work; + }; + + static int ili210x_read_reg(struct i2c_client *client, +@@ -360,6 +362,34 @@ static irqreturn_t ili210x_irq(int irq, + return IRQ_HANDLED; + } + ++static void ili210x_poll_work(struct work_struct *work) ++{ ++ struct ili210x *priv = container_of(work, struct ili210x, poll_work); ++ struct i2c_client *client = priv->client; ++ const struct ili2xxx_chip *chip = priv->chip; ++ u8 touchdata[ILI210X_DATA_SIZE] = { 0 }; ++ bool touch; ++ int error; ++ ++ error = chip->get_touch_data(client, touchdata); ++ if (error) { ++ dev_err(&client->dev, "Unable to get touch data: %d\n", error); ++ return; ++ } ++ ++ touch = ili210x_report_events(priv, touchdata); ++} ++ ++static void ili210x_poll_timer_callback(struct timer_list *t) ++{ ++ struct ili210x *priv = from_timer(priv, t, poll_timer); ++ ++ schedule_work(&priv->poll_work); ++ ++ if (!priv->stop) ++ mod_timer(&priv->poll_timer, jiffies + msecs_to_jiffies(ILI2XXX_POLL_PERIOD)); ++} ++ + static int ili251x_firmware_update_resolution(struct device *dev) + { + struct i2c_client *client = to_i2c_client(dev); +@@ -945,11 +975,6 @@ static int ili210x_i2c_probe(struct i2c_ + return -ENODEV; + } + +- if (client->irq <= 0) { +- dev_err(dev, "No IRQ!\n"); +- return -EINVAL; +- } +- + reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpio)) + return PTR_ERR(reset_gpio); +@@ -1001,12 +1026,17 @@ static int ili210x_i2c_probe(struct i2c_ + return error; + } + +- error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq, +- IRQF_ONESHOT, client->name, priv); +- if (error) { +- dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n", +- error); +- return error; ++ if (client->irq) { ++ error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq, ++ IRQF_ONESHOT, client->name, priv); ++ if (error) { ++ dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n", error); ++ return error; ++ } ++ } else { ++ timer_setup(&priv->poll_timer, ili210x_poll_timer_callback, 0); ++ mod_timer(&priv->poll_timer, jiffies + msecs_to_jiffies(ILI2XXX_POLL_PERIOD)); ++ INIT_WORK(&priv->poll_work, ili210x_poll_work); + } + + error = devm_add_action_or_reset(dev, ili210x_stop, priv); +@@ -1029,6 +1059,16 @@ static int ili210x_i2c_probe(struct i2c_ + return 0; + } + ++static void ili210x_i2c_remove(struct i2c_client *client) ++{ ++ struct ili210x *tsdata = i2c_get_clientdata(client); ++ ++ if (!client->irq) { ++ del_timer(&tsdata->poll_timer); ++ cancel_work_sync(&tsdata->poll_work); ++ } ++} ++ + static const struct i2c_device_id ili210x_i2c_id[] = { + { "ili210x", (long)&ili210x_chip }, + { "ili2117", (long)&ili211x_chip }, +@@ -1054,6 +1094,7 @@ static struct i2c_driver ili210x_ts_driv + }, + .id_table = ili210x_i2c_id, + .probe = ili210x_i2c_probe, ++ .remove = ili210x_i2c_remove, + }; + + module_i2c_driver(ili210x_ts_driver); diff --git a/target/linux/bcm27xx/patches-6.6/950-1443-drivers-gpu-drm-panel-Added-waveshare-13.3inch-panel.patch b/target/linux/bcm27xx/patches-6.6/950-1443-drivers-gpu-drm-panel-Added-waveshare-13.3inch-panel.patch new file mode 100644 index 0000000000..c6861c6a54 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1443-drivers-gpu-drm-panel-Added-waveshare-13.3inch-panel.patch @@ -0,0 +1,309 @@ +From 4a89fda8f73df89e009a6188ef07ab97b1d03c7f Mon Sep 17 00:00:00 2001 +From: eng33 +Date: Thu, 5 Dec 2024 17:20:22 +0800 +Subject: [PATCH] drivers:gpu:drm:panel: Added waveshare 13.3inch panel(support + 2/4lane) + +Signed-off-by: eng33 +--- + drivers/gpu/drm/panel/panel-waveshare-dsi.c | 155 +++++++++++++++++--- + 1 file changed, 138 insertions(+), 17 deletions(-) + +--- a/drivers/gpu/drm/panel/panel-waveshare-dsi.c ++++ b/drivers/gpu/drm/panel/panel-waveshare-dsi.c +@@ -32,6 +32,12 @@ struct ws_panel { + enum drm_panel_orientation orientation; + }; + ++struct ws_panel_data { ++ const struct drm_display_mode *mode; ++ int lanes; ++ unsigned long mode_flags; ++}; ++ + /* 2.8inch 480x640 + * https://www.waveshare.com/product/raspberry-pi/displays/2.8inch-dsi-lcd.htm + */ +@@ -47,6 +53,12 @@ static const struct drm_display_mode ws_ + .vtotal = 640 + 150 + 50 + 150, + }; + ++static const struct ws_panel_data ws_panel_2_8_data = { ++ .mode = &ws_panel_2_8_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, ++}; ++ + /* 3.4inch 800x800 Round + * https://www.waveshare.com/product/displays/lcd-oled/3.4inch-dsi-lcd-c.htm + */ +@@ -62,6 +74,12 @@ static const struct drm_display_mode ws_ + .vtotal = 800 + 8 + 4 + 16, + }; + ++static const struct ws_panel_data ws_panel_3_4_data = { ++ .mode = &ws_panel_3_4_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, ++}; ++ + /* 4.0inch 480x800 + * https://www.waveshare.com/product/raspberry-pi/displays/4inch-dsi-lcd.htm + */ +@@ -77,6 +95,12 @@ static const struct drm_display_mode ws_ + .vtotal = 800 + 20 + 100 + 20, + }; + ++static const struct ws_panel_data ws_panel_4_0_data = { ++ .mode = &ws_panel_4_0_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, ++}; ++ + /* 7.0inch C 1024x600 + * https://www.waveshare.com/product/raspberry-pi/displays/lcd-oled/7inch-dsi-lcd-c-with-case-a.htm + */ +@@ -92,6 +116,12 @@ static const struct drm_display_mode ws_ + .vtotal = 600 + 10 + 10 + 10, + }; + ++static const struct ws_panel_data ws_panel_7_0_c_data = { ++ .mode = &ws_panel_7_0_c_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, ++}; ++ + /* 7.9inch 400x1280 + * https://www.waveshare.com/product/raspberry-pi/displays/7.9inch-dsi-lcd.htm + */ +@@ -107,6 +137,12 @@ static const struct drm_display_mode ws_ + .vtotal = 1280 + 20 + 10 + 20, + }; + ++static const struct ws_panel_data ws_panel_7_9_data = { ++ .mode = &ws_panel_7_9_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, ++}; ++ + /* 8.0inch or 10.1inch 1280x800 + * https://www.waveshare.com/product/raspberry-pi/displays/8inch-dsi-lcd-c.htm + * https://www.waveshare.com/product/raspberry-pi/displays/10.1inch-dsi-lcd-c.htm +@@ -123,6 +159,12 @@ static const struct drm_display_mode ws_ + .vtotal = 800 + 40 + 48 + 40, + }; + ++static const struct ws_panel_data ws_panel_10_1_data = { ++ .mode = &ws_panel_10_1_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, ++}; ++ + /* 11.9inch 320x1480 + * https://www.waveshare.com/product/raspberry-pi/displays/11.9inch-dsi-lcd.htm + */ +@@ -138,6 +180,12 @@ static const struct drm_display_mode ws_ + .vtotal = 1480 + 60 + 60 + 60, + }; + ++static const struct ws_panel_data ws_panel_11_9_data = { ++ .mode = &ws_panel_11_9_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, ++}; ++ + static const struct drm_display_mode ws_panel_4_mode = { + .clock = 50000, + .hdisplay = 720, +@@ -150,6 +198,12 @@ static const struct drm_display_mode ws_ + .vtotal = 720 + 8 + 4 + 16, + }; + ++static const struct ws_panel_data ws_panel_4_data = { ++ .mode = &ws_panel_4_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, ++}; ++ + /* 5.0inch 720x1280 + * https://www.waveshare.com/5inch-dsi-lcd-d.htm + */ +@@ -165,6 +219,12 @@ static const struct drm_display_mode ws_ + .vtotal = 1280 + 20 + 20 + 20, + }; + ++static const struct ws_panel_data ws_panel_5_0_data = { ++ .mode = &ws_panel_5_0_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, ++}; ++ + /* 6.25inch 720x1560 + * https://www.waveshare.com/6.25inch-dsi-lcd.htm + */ +@@ -180,6 +240,12 @@ static const struct drm_display_mode ws_ + .vtotal = 1560 + 20 + 20 + 20, + }; + ++static const struct ws_panel_data ws_panel_6_25_data = { ++ .mode = &ws_panel_6_25_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, ++}; ++ + /* 8.8inch 480x1920 + * https://www.waveshare.com/8.8inch-dsi-lcd.htm + */ +@@ -195,6 +261,48 @@ static const struct drm_display_mode ws_ + .vtotal = 1920 + 20 + 20 + 20, + }; + ++static const struct ws_panel_data ws_panel_8_8_data = { ++ .mode = &ws_panel_8_8_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, ++}; ++ ++static const struct drm_display_mode ws_panel_13_3_4lane_mode = { ++ .clock = 148500, ++ .hdisplay = 1920, ++ .hsync_start = 1920 + 88, ++ .hsync_end = 1920 + 88 + 44, ++ .htotal = 1920 + 88 + 44 + 148, ++ .vdisplay = 1080, ++ .vsync_start = 1080 + 4, ++ .vsync_end = 1080 + 4 + 5, ++ .vtotal = 1080 + 4 + 5 + 36, ++}; ++ ++static const struct ws_panel_data ws_panel_13_3_4lane_data = { ++ .mode = &ws_panel_13_3_4lane_mode, ++ .lanes = 4, ++ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM, ++}; ++ ++static const struct drm_display_mode ws_panel_13_3_2lane_mode = { ++ .clock = 83333, ++ .hdisplay = 1920, ++ .hsync_start = 1920 + 88, ++ .hsync_end = 1920 + 88 + 44, ++ .htotal = 1920 + 88 + 44 + 148, ++ .vdisplay = 1080, ++ .vsync_start = 1080 + 4, ++ .vsync_end = 1080 + 4 + 5, ++ .vtotal = 1080 + 4 + 5 + 36, ++}; ++ ++static const struct ws_panel_data ws_panel_13_3_2lane_data = { ++ .mode = &ws_panel_13_3_2lane_mode, ++ .lanes = 2, ++ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM, ++}; ++ + static struct ws_panel *panel_to_ts(struct drm_panel *panel) + { + return container_of(panel, struct ws_panel, base); +@@ -232,7 +340,10 @@ static int ws_panel_enable(struct drm_pa + { + struct ws_panel *ts = panel_to_ts(panel); + +- ws_panel_i2c_write(ts, 0xad, 0x01); ++ if (ts->mode == &ws_panel_13_3_2lane_mode) ++ ws_panel_i2c_write(ts, 0xad, 0x02); ++ else ++ ws_panel_i2c_write(ts, 0xad, 0x01); + + return 0; + } +@@ -328,13 +439,18 @@ static int ws_panel_probe(struct i2c_cli + .channel = 0, + .node = NULL, + }; ++ const struct ws_panel_data *_ws_panel_data; + int ret; + + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + +- ts->mode = of_device_get_match_data(dev); ++ _ws_panel_data = of_device_get_match_data(dev); ++ if (!_ws_panel_data) ++ return -EINVAL; ++ ++ ts->mode = _ws_panel_data->mode; + if (!ts->mode) + return -EINVAL; + +@@ -396,10 +512,9 @@ static int ws_panel_probe(struct i2c_cli + */ + drm_panel_add(&ts->base); + +- ts->dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | +- MIPI_DSI_CLOCK_NON_CONTINUOUS; ++ ts->dsi->mode_flags = _ws_panel_data->mode_flags; + ts->dsi->format = MIPI_DSI_FMT_RGB888; +- ts->dsi->lanes = 2; ++ ts->dsi->lanes = _ws_panel_data->lanes; + + ret = devm_mipi_dsi_attach(dev, ts->dsi); + +@@ -432,40 +547,46 @@ static void ws_panel_shutdown(struct i2c + static const struct of_device_id ws_panel_of_ids[] = { + { + .compatible = "waveshare,2.8inch-panel", +- .data = &ws_panel_2_8_mode, ++ .data = &ws_panel_2_8_data, + }, { + .compatible = "waveshare,3.4inch-panel", +- .data = &ws_panel_3_4_mode, ++ .data = &ws_panel_3_4_data, + }, { + .compatible = "waveshare,4.0inch-panel", +- .data = &ws_panel_4_0_mode, ++ .data = &ws_panel_4_0_data, + }, { + .compatible = "waveshare,7.0inch-c-panel", +- .data = &ws_panel_7_0_c_mode, ++ .data = &ws_panel_7_0_c_data, + }, { + .compatible = "waveshare,7.9inch-panel", +- .data = &ws_panel_7_9_mode, ++ .data = &ws_panel_7_9_data, + }, { + .compatible = "waveshare,8.0inch-panel", +- .data = &ws_panel_10_1_mode, ++ .data = &ws_panel_10_1_data, + }, { + .compatible = "waveshare,10.1inch-panel", +- .data = &ws_panel_10_1_mode, ++ .data = &ws_panel_10_1_data, + }, { + .compatible = "waveshare,11.9inch-panel", +- .data = &ws_panel_11_9_mode, ++ .data = &ws_panel_11_9_data, + }, { + .compatible = "waveshare,4inch-panel", +- .data = &ws_panel_4_mode, ++ .data = &ws_panel_4_data, + }, { + .compatible = "waveshare,5.0inch-panel", +- .data = &ws_panel_5_0_mode, ++ .data = &ws_panel_5_0_data, + }, { + .compatible = "waveshare,6.25inch-panel", +- .data = &ws_panel_6_25_mode, ++ .data = &ws_panel_6_25_data, + }, { + .compatible = "waveshare,8.8inch-panel", +- .data = &ws_panel_8_8_mode, ++ .data = &ws_panel_8_8_data, ++ }, { ++ .compatible = "waveshare,13.3inch-4lane-panel", ++ .data = &ws_panel_13_3_4lane_data, ++ }, { ++ .compatible = "waveshare,13.3inch-2lane-panel", ++ .data = &ws_panel_13_3_2lane_data, + }, { + /* sentinel */ + } diff --git a/target/linux/bcm27xx/patches-6.6/950-1444-arch-arm-boot-dts-overlays-Added-waveshare-13.3inch-.patch b/target/linux/bcm27xx/patches-6.6/950-1444-arch-arm-boot-dts-overlays-Added-waveshare-13.3inch-.patch new file mode 100644 index 0000000000..1d144bf2ca --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1444-arch-arm-boot-dts-overlays-Added-waveshare-13.3inch-.patch @@ -0,0 +1,46 @@ +From e442e5c1ab6bff5b5460b4fc949beb72aaf77970 Mon Sep 17 00:00:00 2001 +From: eng33 +Date: Thu, 5 Dec 2024 18:11:26 +0800 +Subject: [PATCH] arch:arm:boot:dts:overlays: Added waveshare 13.3inch panel + support + +Signed-off-by: eng33 +--- + arch/arm/boot/dts/overlays/README | 2 ++ + .../dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts | 7 +++++++ + 2 files changed, 9 insertions(+) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -5338,6 +5338,8 @@ Params: 2_8_inch 2.8" 480 + 8_0_inch 8.0" 1280x800 + 10_1_inch 10.1" 1280x800 + 11_9_inch 11.9" 320x1480 ++ 13_3_inch_4lane 13.3" 1920x1080 4lane ++ 13_3_inch_2lane 13.3" 1920x1080 2lane + i2c1 Use i2c-1 with jumper wires from GPIOs 2&3 + disable_touch Disable the touch controller + rotation Set the panel orientation property +--- a/arch/arm/boot/dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts +@@ -51,6 +51,11 @@ + reg = <0x14>; + compatible = "goodix,gt911"; + }; ++ ++ touch2: ilitek@41 { ++ compatible = "ilitek,ili251x"; ++ reg = <0x41>; ++ }; + }; + }; + +@@ -120,6 +125,8 @@ + <&touch>, "touchscreen-inverted-x?", + <&touch>, "touchscreen-inverted-y?"; + 8_8_inch = <&panel>, "compatible=waveshare,8.8inch-panel"; ++ 13_3_inch_4lane = <&panel>, "compatible=waveshare,13.3inch-4lane-panel"; ++ 13_3_inch_2lane = <&panel>, "compatible=waveshare,13.3inch-2lane-panel"; + i2c1 = <&i2c_frag>, "target:0=",<&i2c1>, + <0>, "-3-4+5"; + disable_touch = <&touch>, "status=disabled"; diff --git a/target/linux/bcm27xx/patches-6.6/950-1445-fixup-cgroup-Use-kernel-command-line-to-disable-memo.patch b/target/linux/bcm27xx/patches-6.6/950-1445-fixup-cgroup-Use-kernel-command-line-to-disable-memo.patch new file mode 100644 index 0000000000..8c4a1c3a3e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1445-fixup-cgroup-Use-kernel-command-line-to-disable-memo.patch @@ -0,0 +1,37 @@ +From 166dfc4399643681f2e4277bf7b7407e926861e5 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 9 Dec 2024 14:58:16 +0000 +Subject: [PATCH] fixup! cgroup: Use kernel command line to disable memory + cgroup + +cgroup features are distinct from cgroup subsystems - handle them +correctly. + +Signed-off-by: Phil Elwell +--- + kernel/cgroup/cgroup.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -6769,11 +6769,19 @@ static int __init cgroup_enable(char *st + strcmp(token, ss->legacy_name)) + continue; + +- cgroup_feature_disable_mask &= ~(1 << i); + static_branch_enable(cgroup_subsys_enabled_key[i]); + pr_info("Enabling %s control group subsystem\n", + ss->name); + } ++ ++ for (i = 0; i < OPT_FEATURE_COUNT; i++) { ++ if (strcmp(token, cgroup_opt_feature_names[i])) ++ continue; ++ cgroup_feature_disable_mask &= ~(1 << i); ++ pr_info("Enabling %s control group feature\n", ++ cgroup_opt_feature_names[i]); ++ break; ++ } + } + return 1; + } diff --git a/target/linux/bcm27xx/patches-6.6/950-1446-media-i2c-ov9282-Correct-the-exposure-offset.patch b/target/linux/bcm27xx/patches-6.6/950-1446-media-i2c-ov9282-Correct-the-exposure-offset.patch new file mode 100644 index 0000000000..f673f547dd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1446-media-i2c-ov9282-Correct-the-exposure-offset.patch @@ -0,0 +1,31 @@ +From e23afbf2c7aae9264322eee8e5c72ca1887606df Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 9 Dec 2024 10:43:18 +0000 +Subject: [PATCH] media: i2c: ov9282: Correct the exposure offset + +The datasheet lists that "Maximum exposure time is frame +length -25 row periods, where frame length is set by +registers {0x380E, 0x380F}". +However this driver had OV9282_EXPOSURE_OFFSET set to 12 +which allowed that restriction to be violated, and would +result in very under-exposed images. + +Correct the offset. + +Fixes: 14ea315bbeb7 ("media: i2c: Add ov9282 camera sensor driver") +Signed-off-by: Dave Stevenson +--- + drivers/media/i2c/ov9282.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/i2c/ov9282.c ++++ b/drivers/media/i2c/ov9282.c +@@ -40,7 +40,7 @@ + /* Exposure control */ + #define OV9282_REG_EXPOSURE 0x3500 + #define OV9282_EXPOSURE_MIN 1 +-#define OV9282_EXPOSURE_OFFSET 12 ++#define OV9282_EXPOSURE_OFFSET 25 + #define OV9282_EXPOSURE_STEP 1 + #define OV9282_EXPOSURE_DEFAULT 0x0282 + diff --git a/target/linux/bcm27xx/patches-6.6/950-1451-Revert-drm-vc4-hvs-Don-t-write-gamma-luts-on-2711.patch b/target/linux/bcm27xx/patches-6.6/950-1451-Revert-drm-vc4-hvs-Don-t-write-gamma-luts-on-2711.patch new file mode 100644 index 0000000000..e222ea886a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1451-Revert-drm-vc4-hvs-Don-t-write-gamma-luts-on-2711.patch @@ -0,0 +1,22 @@ +From 448a2db3990534810b45d3e4202df96ab2dc5815 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Tue, 10 Dec 2024 15:28:28 +0000 +Subject: [PATCH] Revert "drm/vc4: hvs: Don't write gamma luts on 2711" + +This reverts commit 40c77e93cfdda320f47fc1a00a76ce466d20e976. +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -521,9 +521,6 @@ static void vc4_hvs_lut_load(struct vc4_ + if (!drm_dev_enter(drm, &idx)) + return; + +- if (hvs->vc4->gen == VC4_GEN_5) +- return; +- + /* The LUT memory is laid out with each HVS channel in order, + * each of which takes 256 writes for R, 256 for G, then 256 + * for B. diff --git a/target/linux/bcm27xx/patches-6.6/950-1452-Revert-PCI-Warn-if-no-host-bridge-NUMA-node-info.patch b/target/linux/bcm27xx/patches-6.6/950-1452-Revert-PCI-Warn-if-no-host-bridge-NUMA-node-info.patch new file mode 100644 index 0000000000..5aa88661c3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1452-Revert-PCI-Warn-if-no-host-bridge-NUMA-node-info.patch @@ -0,0 +1,29 @@ +From 746662562995125ef7fb2c294300b0bd061b1251 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Tue, 10 Dec 2024 16:39:31 +0000 +Subject: [PATCH] Revert "PCI: Warn if no host bridge NUMA node info" + +This warning doesn't mean anyting on our platform and +the warning causes confusion. + +See: https://forums.raspberrypi.com/viewtopic.php?p=2276125#p2276125 + +This reverts commit ad5086108b9f0361929aa9a79cf959ab5681d249. + +Signed-off-by: Dom Cobley +--- + drivers/pci/probe.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -968,9 +968,6 @@ static int pci_register_host_bridge(stru + else + pr_info("PCI host bridge to bus %s\n", name); + +- if (nr_node_ids > 1 && pcibus_to_node(bus) == NUMA_NO_NODE) +- dev_warn(&bus->dev, "Unknown NUMA node; performance will be reduced\n"); +- + /* Coalesce contiguous windows */ + resource_list_for_each_entry_safe(window, n, &resources) { + if (list_is_last(&window->node, &resources)) diff --git a/target/linux/bcm27xx/patches-6.6/950-1454-drm-bridge-panel-Connector-to-allow-interlaced-modes.patch b/target/linux/bcm27xx/patches-6.6/950-1454-drm-bridge-panel-Connector-to-allow-interlaced-modes.patch new file mode 100644 index 0000000000..9e4ba2a75a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1454-drm-bridge-panel-Connector-to-allow-interlaced-modes.patch @@ -0,0 +1,25 @@ +From 7d294fbff4863e53a64685335b30aed9604cae49 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Tue, 19 Nov 2024 16:11:32 +0000 +Subject: [PATCH] drm: bridge: panel: Connector to allow interlaced modes + +When initialized from panel_bridge_attach(), connector should +allow interlaced modes rather than invariably rejecting them, +so that other components can validate them. + +Signed-off-by: Nick Hollinghurst +--- + drivers/gpu/drm/bridge/panel.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/gpu/drm/bridge/panel.c ++++ b/drivers/gpu/drm/bridge/panel.c +@@ -82,6 +82,8 @@ static int panel_bridge_attach(struct dr + return ret; + } + ++ connector->interlace_allowed = true; ++ + drm_panel_bridge_set_orientation(connector, bridge); + + drm_connector_attach_encoder(&panel_bridge->connector, diff --git a/target/linux/bcm27xx/patches-6.6/950-1455-dts-overlays-vc4-kms-dpi-generic-overlay-Add-interla.patch b/target/linux/bcm27xx/patches-6.6/950-1455-dts-overlays-vc4-kms-dpi-generic-overlay-Add-interla.patch new file mode 100644 index 0000000000..1d9792305c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1455-dts-overlays-vc4-kms-dpi-generic-overlay-Add-interla.patch @@ -0,0 +1,34 @@ +From 2b0acbe8fd008e09a904b7a3c796a2dc79bf10ea Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Tue, 19 Nov 2024 16:17:40 +0000 +Subject: [PATCH] dts: overlays: vc4-kms-dpi-generic-overlay: Add "interlaced" + property + +Almost no DPI hardware supports it, but it's useful for RP1 video out. + +Signed-off-by: Nick Hollinghurst +--- + arch/arm/boot/dts/overlays/README | 1 + + arch/arm/boot/dts/overlays/vc4-kms-dpi-generic-overlay.dts | 1 + + 2 files changed, 2 insertions(+) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -5099,6 +5099,7 @@ Params: clock-frequency Display + vsync-invert Vertical sync active low + de-invert Data Enable active low + pixclk-invert Negative edge pixel clock ++ interlaced Use an interlaced mode (where supported) + width-mm Define the screen width in mm + height-mm Define the screen height in mm + rgb565 Change to RGB565 output on GPIOs 0-19 +--- a/arch/arm/boot/dts/overlays/vc4-kms-dpi-generic-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dpi-generic-overlay.dts +@@ -59,6 +59,7 @@ + vsync-invert = <&timing>, "vsync-active:0=0"; + de-invert = <&timing>, "de-active:0=0"; + pixclk-invert = <&timing>, "pixelclk-active:0=0"; ++ interlaced = <&timing>, "interlaced?"; + + width-mm = <&panel_generic>, "width-mm:0"; + height-mm = <&panel_generic>, "height-mm:0"; diff --git a/target/linux/bcm27xx/patches-6.6/950-1456-drm-rp1-rp1-dpi-Add-interlaced-modes-and-PIO-program.patch b/target/linux/bcm27xx/patches-6.6/950-1456-drm-rp1-rp1-dpi-Add-interlaced-modes-and-PIO-program.patch index bbaee270c5..e78ee378a4 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1456-drm-rp1-rp1-dpi-Add-interlaced-modes-and-PIO-program.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1456-drm-rp1-rp1-dpi-Add-interlaced-modes-and-PIO-program.patch @@ -1,8 +1,8 @@ From 7735dd0736322cff23aff95490bae1d69937a9bf Mon Sep 17 00:00:00 2001 From: Nick Hollinghurst Date: Tue, 10 Dec 2024 13:23:09 +0000 -Subject: [PATCH 1456/1482] drm: rp1: rp1-dpi: Add interlaced modes and PIO - program to fix VSYNC +Subject: [PATCH] drm: rp1: rp1-dpi: Add interlaced modes and PIO program to + fix VSYNC Implement interlaced modes by wobbling the base pointer and VFP width for every field. This results in correct pixels but incorrect VSYNC. diff --git a/target/linux/bcm27xx/patches-6.6/950-1457-pwm-Improve-PWM_PIO_RP1-dependencies.patch b/target/linux/bcm27xx/patches-6.6/950-1457-pwm-Improve-PWM_PIO_RP1-dependencies.patch deleted file mode 100644 index 357cd05dc8..0000000000 --- a/target/linux/bcm27xx/patches-6.6/950-1457-pwm-Improve-PWM_PIO_RP1-dependencies.patch +++ /dev/null @@ -1,22 +0,0 @@ -From f85f3509692f966ec32e4db499f7e64dc6b6b952 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 12 Dec 2024 10:09:13 +0000 -Subject: [PATCH 1457/1482] pwm: Improve PWM_PIO_RP1 dependencies - -PWM_PIO_RP1 should select RP1_PIO, as it is useless without it. - -Signed-off-by: Phil Elwell ---- - drivers/pwm/Kconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/pwm/Kconfig -+++ b/drivers/pwm/Kconfig -@@ -457,6 +457,7 @@ config PWM_PCA9685 - config PWM_PIO_RP1 - tristate "RP1 PIO PWM support" - depends on FIRMWARE_RP1 || COMPILE_TEST -+ select RP1_PIO - help - This is a PWM framework driver for Raspberry Pi 5, using the PIO - hardware of RP1 to provide PWM functionality. Supports up to 4 diff --git a/target/linux/bcm27xx/patches-6.6/950-1458-Revert-pwm-Improve-PWM_PIO_RP1-dependencies.patch b/target/linux/bcm27xx/patches-6.6/950-1458-Revert-pwm-Improve-PWM_PIO_RP1-dependencies.patch deleted file mode 100644 index eabf3887d1..0000000000 --- a/target/linux/bcm27xx/patches-6.6/950-1458-Revert-pwm-Improve-PWM_PIO_RP1-dependencies.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 73fb1e979a210094935f4af4c3d6e700fba30c5f Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 12 Dec 2024 10:28:54 +0000 -Subject: [PATCH 1458/1482] Revert "pwm: Improve PWM_PIO_RP1 dependencies" - -This reverts commit f85f3509692f966ec32e4db499f7e64dc6b6b952. ---- - drivers/pwm/Kconfig | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/pwm/Kconfig -+++ b/drivers/pwm/Kconfig -@@ -457,7 +457,6 @@ config PWM_PCA9685 - config PWM_PIO_RP1 - tristate "RP1 PIO PWM support" - depends on FIRMWARE_RP1 || COMPILE_TEST -- select RP1_PIO - help - This is a PWM framework driver for Raspberry Pi 5, using the PIO - hardware of RP1 to provide PWM functionality. Supports up to 4 diff --git a/target/linux/bcm27xx/patches-6.6/950-1459-ASoC-allo-piano-dac-plus-Fix-volume-limit-locking.patch b/target/linux/bcm27xx/patches-6.6/950-1459-ASoC-allo-piano-dac-plus-Fix-volume-limit-locking.patch new file mode 100644 index 0000000000..8e279df688 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1459-ASoC-allo-piano-dac-plus-Fix-volume-limit-locking.patch @@ -0,0 +1,79 @@ +From ac0cd73932aa1e371ffaf0b974855ed3cd22937f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 11 Dec 2024 13:47:30 +0000 +Subject: [PATCH] ASoC: allo-piano-dac-plus: Fix volume limit locking + +Calling snd_soc_limit_volume from within a kcontrol put handler seems +to cause a deadlock as it attempts to claim a write lock that is already +held. Call snd_soc_limit_volume from the main initialisation code +instead, to avoid the recursive locking. + +See: https://github.com/raspberrypi/linux/issues/6527 + +Signed-off-by: Phil Elwell +--- + sound/soc/bcm/allo-piano-dac-plus.c | 32 +++++++++++++---------------- + 1 file changed, 14 insertions(+), 18 deletions(-) + +--- a/sound/soc/bcm/allo-piano-dac-plus.c ++++ b/sound/soc/bcm/allo-piano-dac-plus.c +@@ -452,14 +452,6 @@ static int pcm512x_set_reg_sub(struct sn + + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]); + +- if (digital_gain_0db_limit) { +- ret = snd_soc_limit_volume(card, "Subwoofer Playback Volume", +- 207); +- if (ret < 0) +- dev_warn(card->dev, "Failed to set volume limit: %d\n", +- ret); +- } +- + // When in Dual Mono, Sub vol control should not set anything. + if (glb_ptr->dual_mode != 1) { //Not in Dual Mono mode + +@@ -562,14 +554,6 @@ static int pcm512x_set_reg_master(struct + + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]); + +- if (digital_gain_0db_limit) { +- ret = snd_soc_limit_volume(card, "Master Playback Volume", +- 207); +- if (ret < 0) +- dev_warn(card->dev, "Failed to set volume limit: %d\n", +- ret); +- } +- + if (glb_ptr->dual_mode == 1) { //in Dual Mono Mode + + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component, +@@ -750,6 +734,18 @@ static int snd_allo_piano_dac_init(struc + if (digital_gain_0db_limit) { + int ret; + ++ ret = snd_soc_limit_volume(card, "Master Playback Volume", ++ 207); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set master volume limit: %d\n", ++ ret); ++ ++ ret = snd_soc_limit_volume(card, "Subwoofer Playback Volume", ++ 207); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set subwoofer volume limit: %d\n", ++ ret); ++ + //Set volume limit on both dacs + for (i = 0; i < ARRAY_SIZE(codec_ctl_pfx); i++) { + char cname[256]; +@@ -757,8 +753,8 @@ static int snd_allo_piano_dac_init(struc + sprintf(cname, "%s %s", codec_ctl_pfx[i], codec_ctl_name[0]); + ret = snd_soc_limit_volume(card, cname, 207); + if (ret < 0) +- dev_warn(card->dev, "Failed to set volume limit: %d\n", +- ret); ++ dev_warn(card->dev, "Failed to set %s volume limit: %d\n", ++ cname, ret); + } + } + diff --git a/target/linux/bcm27xx/patches-6.6/950-1460-drm-vc4-txp-Do-not-allow-24bpp-formats-when-transpos.patch b/target/linux/bcm27xx/patches-6.6/950-1460-drm-vc4-txp-Do-not-allow-24bpp-formats-when-transpos.patch new file mode 100644 index 0000000000..93de0f99a4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1460-drm-vc4-txp-Do-not-allow-24bpp-formats-when-transpos.patch @@ -0,0 +1,30 @@ +From af4ab4fb77dfc697c8ae068b18f27de1ee5d609f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 11 Dec 2024 16:30:43 +0000 +Subject: [PATCH] drm: vc4: txp: Do not allow 24bpp formats when transposing + +The hardware doesn't support transposing to 24bpp (RGB888/BGR888) +formats. There's no way to advertise this through DRM, so block +it from atomic_check instead. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_txp.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -272,6 +272,13 @@ static int vc4_txp_connector_atomic_chec + return -EINVAL; + } + ++ if (conn_state->rotation & DRM_MODE_TRANSPOSE && ++ (fb->format->format == DRM_FORMAT_RGB888 || ++ fb->format->format == DRM_FORMAT_BGR888)) { ++ DRM_DEBUG_KMS("24bpp formats not supported when transposing\n"); ++ return -EINVAL; ++ } ++ + for (i = 0; i < ARRAY_SIZE(drm_fmts); i++) { + if (fb->format->format == drm_fmts[i]) + break; diff --git a/target/linux/bcm27xx/patches-6.6/950-1461-drm-Validate-connector-rotation-has-one-bit-set-in-t.patch b/target/linux/bcm27xx/patches-6.6/950-1461-drm-Validate-connector-rotation-has-one-bit-set-in-t.patch new file mode 100644 index 0000000000..2a6115981a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1461-drm-Validate-connector-rotation-has-one-bit-set-in-t.patch @@ -0,0 +1,29 @@ +From 0b216b3988e5b7035cd5ed8a9910eacbb3420ce0 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 12 Dec 2024 11:59:52 +0000 +Subject: [PATCH] drm: Validate connector rotation has one bit set in the + rotation property + +Copy the same validation logic as from the plane rotation property. + +Fixes: 8fec3ff87049 ("drm: Add a rotation parameter to connectors.") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_atomic_uapi.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/gpu/drm/drm_atomic_uapi.c ++++ b/drivers/gpu/drm/drm_atomic_uapi.c +@@ -812,6 +812,12 @@ static int drm_atomic_connector_set_prop + } else if (property == connector->privacy_screen_sw_state_property) { + state->privacy_screen_sw_state = val; + } else if (property == connector->rotation_property) { ++ if (!is_power_of_2(val & DRM_MODE_ROTATE_MASK)) { ++ drm_dbg_atomic(connector->dev, ++ "[CONNECTOR:%d:%s] bad rotation bitmask: 0x%llx\n", ++ connector->base.id, connector->name, val); ++ return -EINVAL; ++ } + state->rotation = val; + } else if (connector->funcs->atomic_set_property) { + return connector->funcs->atomic_set_property(connector, diff --git a/target/linux/bcm27xx/patches-6.6/950-1462-ASoC-allo-piano-dac-plus-Suppress-517-errors.patch b/target/linux/bcm27xx/patches-6.6/950-1462-ASoC-allo-piano-dac-plus-Suppress-517-errors.patch new file mode 100644 index 0000000000..67bce02817 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1462-ASoC-allo-piano-dac-plus-Suppress-517-errors.patch @@ -0,0 +1,73 @@ +From 61494a7aa2ea887fa1cd1399a8db1317c87f661b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 12 Dec 2024 13:05:41 +0000 +Subject: [PATCH] ASoC: allo-piano-dac-plus: Suppress -517 errors + +Use dev_err_probe to simplify the code and suppress EPROBE_DEFER errors. + +Signed-off-by: Phil Elwell +--- + sound/soc/bcm/allo-piano-dac-plus.c | 37 ++++++++--------------------- + 1 file changed, 10 insertions(+), 27 deletions(-) + +--- a/sound/soc/bcm/allo-piano-dac-plus.c ++++ b/sound/soc/bcm/allo-piano-dac-plus.c +@@ -974,48 +974,31 @@ static int snd_allo_piano_dac_probe(stru + + allo_piano_2_1_codecs[0].of_node = + of_parse_phandle(pdev->dev.of_node, "audio-codec", 0); +- if (!allo_piano_2_1_codecs[0].of_node) { +- dev_err(&pdev->dev, +- "Property 'audio-codec' missing or invalid\n"); +- return -EINVAL; +- } +- + allo_piano_2_1_codecs[1].of_node = + of_parse_phandle(pdev->dev.of_node, "audio-codec", 1); +- if (!allo_piano_2_1_codecs[1].of_node) { +- dev_err(&pdev->dev, ++ if (!allo_piano_2_1_codecs[0].of_node || !allo_piano_2_1_codecs[1].of_node) ++ return dev_err_probe(&pdev->dev, -EINVAL, + "Property 'audio-codec' missing or invalid\n"); +- return -EINVAL; +- } + + mute_gpio[0] = devm_gpiod_get_optional(&pdev->dev, "mute1", + GPIOD_OUT_LOW); +- if (IS_ERR(mute_gpio[0])) { +- ret = PTR_ERR(mute_gpio[0]); +- dev_err(&pdev->dev, +- "failed to get mute1 gpio6: %d\n", ret); +- return ret; +- } ++ if (IS_ERR(mute_gpio[0])) ++ return dev_err_probe(&pdev->dev, PTR_ERR(mute_gpio[0]), ++ "failed to get mute1 gpio\n"); + + mute_gpio[1] = devm_gpiod_get_optional(&pdev->dev, "mute2", + GPIOD_OUT_LOW); +- if (IS_ERR(mute_gpio[1])) { +- ret = PTR_ERR(mute_gpio[1]); +- dev_err(&pdev->dev, +- "failed to get mute2 gpio25: %d\n", ret); +- return ret; +- } ++ if (IS_ERR(mute_gpio[1])) ++ return dev_err_probe(&pdev->dev, PTR_ERR(mute_gpio[1]), ++ "failed to get mute2 gpio\n"); + + if (mute_gpio[0] && mute_gpio[1]) + snd_allo_piano_dac.set_bias_level = + snd_allo_piano_set_bias_level; + + ret = snd_soc_register_card(&snd_allo_piano_dac); +- if (ret < 0) { +- dev_err(&pdev->dev, +- "snd_soc_register_card() failed: %d\n", ret); +- return ret; +- } ++ if (ret < 0) ++ return dev_err_probe(&pdev->dev, ret, "snd_soc_register_card() failed\n"); + + if ((mute_gpio[0]) && (mute_gpio[1])) + snd_allo_piano_gpio_mute(&snd_allo_piano_dac); diff --git a/target/linux/bcm27xx/patches-6.6/950-1463-drm-rp1-rp1-dpi-Fix-optional-dependency-on-RP1_PIO.patch b/target/linux/bcm27xx/patches-6.6/950-1463-drm-rp1-rp1-dpi-Fix-optional-dependency-on-RP1_PIO.patch index 52e87daa38..13c735eb4e 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1463-drm-rp1-rp1-dpi-Fix-optional-dependency-on-RP1_PIO.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1463-drm-rp1-rp1-dpi-Fix-optional-dependency-on-RP1_PIO.patch @@ -1,8 +1,7 @@ From 80533a952218696c0ef1b346bab50dc401e6b74c Mon Sep 17 00:00:00 2001 From: Nick Hollinghurst Date: Thu, 12 Dec 2024 11:58:12 +0000 -Subject: [PATCH 1463/1482] drm: rp1: rp1-dpi: Fix optional dependency on - RP1_PIO +Subject: [PATCH] drm: rp1: rp1-dpi: Fix optional dependency on RP1_PIO Add optional dependency to Kconfig, and conditionally compile PIO-dependent code. Add a mode validation function to reject diff --git a/target/linux/bcm27xx/patches-6.6/950-1464-serial-sc16is7xx-announce-support-for-SER_RS485_RTS_.patch b/target/linux/bcm27xx/patches-6.6/950-1464-serial-sc16is7xx-announce-support-for-SER_RS485_RTS_.patch new file mode 100644 index 0000000000..f78402d0c5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1464-serial-sc16is7xx-announce-support-for-SER_RS485_RTS_.patch @@ -0,0 +1,42 @@ +From 694247173f2e136196d7cb3a392c84cda65674d2 Mon Sep 17 00:00:00 2001 +From: Hugo Villeneuve +Date: Mon, 7 Oct 2024 12:27:15 -0400 +Subject: [PATCH] serial: sc16is7xx: announce support for SER_RS485_RTS_ON_SEND + +commit 068d35a7be65fa3bca4bba21c269bfe0b39158a6 upstream. + +When specifying flag SER_RS485_RTS_ON_SEND in RS485 configuration, +we get the following warning after commit 4afeced55baa ("serial: core: +fix sanitizing check for RTS settings"): + + invalid RTS setting, using RTS_AFTER_SEND instead + +This results in SER_RS485_RTS_AFTER_SEND being set and the +driver always write to the register field SC16IS7XX_EFCR_RTS_INVERT_BIT, +which breaks some hardware using these chips. + +The hardware supports both RTS_ON_SEND and RTS_AFTER_SEND modes, so fix +this by announcing support for RTS_ON_SEND. + +Signed-off-by: Hugo Villeneuve +Suggested-by: Konstantin Pugin +Link: https://lore.kernel.org/lkml/20240422133219.2710061-2-ria.freelander@gmail.com +Reviewed-by: Andy Shevchenko +Tested-by: Hugo Villeneuve +Link: https://lore.kernel.org/r/20241007162716.3122912-1-hugo@hugovil.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/sc16is7xx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/tty/serial/sc16is7xx.c ++++ b/drivers/tty/serial/sc16is7xx.c +@@ -1457,7 +1457,7 @@ static int sc16is7xx_setup_mctrl_ports(s + } + + static const struct serial_rs485 sc16is7xx_rs485_supported = { +- .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND, ++ .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND, + .delay_rts_before_send = 1, + .delay_rts_after_send = 1, /* Not supported but keep returning -EINVAL */ + }; diff --git a/target/linux/bcm27xx/patches-6.6/950-1467-dtoverlays-Add-override-for-target-path-on-I2C-overl.patch b/target/linux/bcm27xx/patches-6.6/950-1467-dtoverlays-Add-override-for-target-path-on-I2C-overl.patch new file mode 100644 index 0000000000..d5f72d1c92 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1467-dtoverlays-Add-override-for-target-path-on-I2C-overl.patch @@ -0,0 +1,550 @@ +From b75fd2a9385e1358fa82218184e73513f9a5e57f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 16 Dec 2024 15:11:08 +0000 +Subject: [PATCH] dtoverlays: Add override for target-path on I2C overlays + +To allow for attaching any of the standard overlays to a +bitbashed i2c-gpio bus, allow specifying the target path for +the overlay. + +Suggested by: +https://forums.raspberrypi.com/viewtopic.php?t=381059 + +Example: +dtoverlay=i2c-gpio,i2c_gpio_sda=10,i2c_gpio_scl=11 +dtoverlay=mcp23017,i2c-path=/i2c@0 +dtoverlay=i2c-gpio,i2c_gpio_sda=12,i2c_gpio_scl=13,bus=3 +dtoverlay=mcp23017,i2c-path=/i2c@3 + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/overlays/README | 59 +++++++++++++++++++ + .../arm/boot/dts/overlays/ads1115-overlay.dts | 2 + + .../boot/dts/overlays/edt-ft5406-overlay.dts | 3 + + arch/arm/boot/dts/overlays/goodix-overlay.dts | 4 +- + .../dts/overlays/hd44780-i2c-lcd-overlay.dts | 4 +- + .../arm/boot/dts/overlays/i2c-fan-overlay.dts | 2 + + .../arm/boot/dts/overlays/i2c-mux-overlay.dts | 2 + + .../dts/overlays/i2c-pwm-pca9685a-overlay.dts | 2 + + .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 2 + + .../boot/dts/overlays/i2c-sensor-overlay.dts | 2 + + .../boot/dts/overlays/ilitek251x-overlay.dts | 4 +- + .../boot/dts/overlays/mcp23017-overlay.dts | 2 + + .../arm/boot/dts/overlays/pca953x-overlay.dts | 30 +++++++++- + .../arm/boot/dts/overlays/pcf857x-overlay.dts | 30 +++++++++- + .../dts/overlays/sc16is750-i2c-overlay.dts | 30 +++++++++- + .../dts/overlays/sc16is752-i2c-overlay.dts | 30 +++++++++- + 16 files changed, 201 insertions(+), 7 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -555,6 +555,7 @@ Params: addr I2C bus + overlay - BCM2711 only) + i2c6 Choose the I2C6 bus (configure with the i2c6 + overlay - BCM2711 only) ++ i2c-path Override I2C path to allow for i2c-gpio buses + + Channel parameters can be set for each enabled channel. + A maximum of 4 channels can be enabled (letters a thru d). +@@ -1238,6 +1239,7 @@ Params: sizex Touchscr + addr Sets the address for the touch controller. Note + that the device must be configured to use the + specified address. ++ i2c-path Override I2C path to allow for i2c-gpio buses + + + Name: enc28j60 +@@ -1439,6 +1441,7 @@ Info: Enables I2C connected Goodix gt9 + Load: dtoverlay=goodix,= + Params: interrupt GPIO used for interrupt (default 4) + reset GPIO used for reset (default 17) ++ i2c-path Override I2C path to allow for i2c-gpio buses + + + Name: googlevoicehat-soundcard +@@ -1730,6 +1733,7 @@ Params: addr I2C addr + display_height Height of the display in characters (default 2) + + display_width Width of the display in characters (default 16) ++ i2c-path Override I2C path to allow for i2c-gpio buses + + + Name: hd44780-lcd +@@ -2095,6 +2099,8 @@ Params: addr Sets the + i2c6 Choose the I2C6 bus (configure with the i2c6 + overlay - BCM2711 only) + ++ i2c-path Override I2C path to allow for i2c-gpio buses ++ + minpwm PWM setting for the fan when the SoC is below + mintemp (range 0-255. default 0) + maxpwm PWM setting for the fan when the SoC is above +@@ -2165,6 +2171,8 @@ Params: pca9542 Select t + i2c6 Choose the I2C6 bus (configure with the i2c6 + overlay - BCM2711 only) + ++ i2c-path Override I2C path to allow for i2c-gpio buses ++ + disconnect_on_idle Force the mux to disconnect all child buses + after every transaction. + +@@ -2186,6 +2194,7 @@ Params: addr I2C addr + overlay - BCM2711 only) + i2c6 Choose the I2C6 bus (configure with the i2c6 + overlay - BCM2711 only) ++ i2c-path Override I2C path to allow for i2c-gpio buses + + + Name: i2c-rtc +@@ -2255,6 +2264,8 @@ Params: abx80x Select o + i2c6 Choose the I2C6 bus (configure with the i2c6 + overlay - BCM2711 only) + ++ i2c-path Override I2C path to allow for i2c-gpio buses ++ + addr Sets the address for the RTC. Note that the + device must be configured to use the specified + address. +@@ -2519,6 +2530,8 @@ Params: addr Set the + i2c6 Choose the I2C6 bus (configure with the i2c6 + overlay - BCM2711 only) + ++ i2c-path Override I2C path to allow for i2c-gpio buses ++ + + Name: i2c0 + Info: Change i2c0 pin usage. Not all pin combinations are usable on all +@@ -2661,6 +2674,7 @@ Params: interrupt GPIO use + touchscreen (in pixels) + sizey Touchscreen size y, vertical resolution of + touchscreen (in pixels) ++ i2c-path Override I2C path to allow for i2c-gpio buses + + + Name: imx219 +@@ -3138,6 +3152,7 @@ Params: gpiopin Gpio pin + overlay - BCM2711 only) + i2c6 Choose the I2C6 bus (configure with the i2c6 + overlay - BCM2711 only) ++ i2c-path Override I2C path to allow for i2c-gpio buses + + + Name: mcp23s17 +@@ -3587,6 +3602,17 @@ Params: addr I2C addr + cat9554 Select the Onnn CAT9554 (8 bit) + pca9654 Select the Onnn PCA9654 (8 bit) + xra1202 Select the Exar XRA1202 (8 bit) ++ i2c0 Choose the I2C0 bus on GPIOs 0&1 ++ i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c3 Choose the I2C3 bus (configure with the i2c3 ++ overlay - BCM2711 only) ++ i2c4 Choose the I2C3 bus (configure with the i2c3 ++ overlay - BCM2711 only) ++ i2c5 Choose the I2C5 bus (configure with the i2c4 ++ overlay - BCM2711 only) ++ i2c6 Choose the I2C6 bus (configure with the i2c6 ++ overlay - BCM2711 only) ++ i2c-path Override I2C path to allow for i2c-gpio buses + + + Name: pcf857x +@@ -3598,6 +3624,17 @@ Params: addr I2C addr + pcf8574a Select the NXP PCF8574A (8 bit) + pcf8575 Select the NXP PCF8575 (16 bit) + pca8574 Select the NXP PCA8574 (8 bit) ++ i2c0 Choose the I2C0 bus on GPIOs 0&1 ++ i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c3 Choose the I2C3 bus (configure with the i2c3 ++ overlay - BCM2711 only) ++ i2c4 Choose the I2C3 bus (configure with the i2c3 ++ overlay - BCM2711 only) ++ i2c5 Choose the I2C5 bus (configure with the i2c4 ++ overlay - BCM2711 only) ++ i2c6 Choose the I2C6 bus (configure with the i2c6 ++ overlay - BCM2711 only) ++ i2c-path Override I2C path to allow for i2c-gpio buses + + + Name: pcie-32bit-dma +@@ -4257,6 +4294,17 @@ Load: dtoverlay=sc16is750-i2c,= + Params: int_pin GPIO used for IRQ (default 24) + addr Address (default 0x48) + xtal On-board crystal frequency (default 14745600) ++ i2c0 Choose the I2C0 bus on GPIOs 0&1 ++ i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c3 Choose the I2C3 bus (configure with the i2c3 ++ overlay - BCM2711 only) ++ i2c4 Choose the I2C4 bus (configure with the i2c4 ++ overlay - BCM2711 only) ++ i2c5 Choose the I2C5 bus (configure with the i2c5 ++ overlay - BCM2711 only) ++ i2c6 Choose the I2C6 bus (configure with the i2c6 ++ overlay - BCM2711 only) ++ i2c-path Override I2C path to allow for i2c-gpio buses + + + Name: sc16is750-spi0 +@@ -4275,6 +4323,17 @@ Load: dtoverlay=sc16is752-i2c,= + Params: int_pin GPIO used for IRQ (default 24) + addr Address (default 0x48) + xtal On-board crystal frequency (default 14745600) ++ i2c0 Choose the I2C0 bus on GPIOs 0&1 ++ i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c3 Choose the I2C3 bus (configure with the i2c3 ++ overlay - BCM2711 only) ++ i2c4 Choose the I2C4 bus (configure with the i2c4 ++ overlay - BCM2711 only) ++ i2c5 Choose the I2C5 bus (configure with the i2c5 ++ overlay - BCM2711 only) ++ i2c6 Choose the I2C6 bus (configure with the i2c6 ++ overlay - BCM2711 only) ++ i2c-path Override I2C path to allow for i2c-gpio buses + + + Name: sc16is752-spi0 +--- a/arch/arm/boot/dts/overlays/ads1115-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts +@@ -131,5 +131,7 @@ + <&frag100>, "target-path=i2c5"; + i2c6 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c6"; ++ i2c-path = <&frag100>, "target?=0", ++ <&frag100>, "target-path"; + }; + }; +--- a/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts ++++ b/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts +@@ -41,6 +41,9 @@ + i2c6 = <&ts_i2c_frag>, "target?=0", + <&ts_i2c_frag>, "target-path=i2c6", + <0>,"-0-1"; ++ i2c-path = <&ts_i2c_frag>, "target?=0", ++ <&ts_i2c_frag>, "target-path", ++ <0>,"-0-1"; + addr = <&ft5406>,"reg:0"; + }; + }; +--- a/arch/arm/boot/dts/overlays/goodix-overlay.dts ++++ b/arch/arm/boot/dts/overlays/goodix-overlay.dts +@@ -16,7 +16,7 @@ + }; + }; + +- fragment@1 { ++ i2c_frag: fragment@1 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; +@@ -42,5 +42,7 @@ + <>9271>,"irq-gpios:4"; + reset = <&goodix_pins>,"brcm,pins:4", + <>9271>,"reset-gpios:4"; ++ i2c-path = <&i2c_frag>, "target?=0", ++ <&i2c_frag>, "target-path"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hd44780-i2c-lcd-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hd44780-i2c-lcd-overlay.dts +@@ -4,7 +4,7 @@ + / { + compatible = "brcm,bcm2835"; + +- fragment@0 { ++ i2c_frag: fragment@0 { + target = <&i2c_arm>; + __overlay__ { + status = "okay"; +@@ -52,6 +52,8 @@ + display_height = <&lcd_screen>,"display-height-chars:0"; + display_width = <&lcd_screen>,"display-width-chars:0"; + addr = <&pcf857x>,"reg:0"; ++ i2c-path = <&i2c_frag>, "target?=0", ++ <&i2c_frag>, "target-path"; + }; + + }; +--- a/arch/arm/boot/dts/overlays/i2c-fan-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-fan-overlay.dts +@@ -93,6 +93,8 @@ + <&frag100>, "target-path=i2c5"; + i2c6 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c6"; ++ i2c-path = <&frag100>, "target?=0", ++ <&frag100>, "target-path"; + addr = <&emc2301>,"reg:0"; + minpwm = <&emc2301>,"emc2305,pwm-min.0"; + maxpwm = <&emc2301>,"emc2305,pwm-max.0"; +--- a/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts +@@ -175,6 +175,8 @@ + <&frag100>, "target-path=i2c5"; + i2c6 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c6"; ++ i2c-path = <&frag100>, "target?=0", ++ <&frag100>, "target-path"; + disconnect_on_idle = + <&pca9542>,"idle-state:0=", , + <&pca9545>,"idle-state:0=", , +--- a/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts +@@ -57,5 +57,7 @@ + <&frag100>, "target-path=i2c5"; + i2c6 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c6"; ++ i2c-path = <&frag100>, "target?=0", ++ <&frag100>, "target-path"; + }; + }; +--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts +@@ -38,5 +38,7 @@ + <&frag100>, "target-path=i2c5"; + i2c6 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c6"; ++ i2c-path = <&frag100>, "target?=0", ++ <&frag100>, "target-path"; + }; + }; +--- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts +@@ -38,5 +38,7 @@ + <&frag100>, "target-path=i2c5"; + i2c6 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c6"; ++ i2c-path = <&frag100>, "target?=0", ++ <&frag100>, "target-path"; + }; + }; +--- a/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ilitek251x-overlay.dts +@@ -16,7 +16,7 @@ + }; + }; + +- fragment@1 { ++ frag1: fragment@1 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; +@@ -41,5 +41,7 @@ + <&ili251x>,"interrupts:0"; + sizex = <&ili251x>,"touchscreen-size-x:0"; + sizey = <&ili251x>,"touchscreen-size-y:0"; ++ i2c-path = <&frag1>, "target?=0", ++ <&frag1>, "target-path"; + }; + }; +--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts ++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts +@@ -98,6 +98,8 @@ + <&frag100>, "target-path=i2c5"; + i2c6 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c6"; ++ i2c-path = <&frag100>, "target?=0", ++ <&frag100>, "target-path"; + }; + }; + +--- a/arch/arm/boot/dts/overlays/pca953x-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pca953x-overlay.dts +@@ -5,7 +5,7 @@ + /{ + compatible = "brcm,bcm2835"; + +- fragment@0 { ++ frag0: fragment@0 { + target = <&i2c_arm>; + __overlay__ { + #address-cells = <1>; +@@ -204,6 +204,20 @@ + }; + }; + ++ fragment@100 { ++ target = <&i2c0if>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@101 { ++ target = <&i2c0mux>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { + addr = <&pca>,"reg:0"; + pca6416 = <0>, "+1"; +@@ -236,5 +250,19 @@ + cat9554 = <0>, "+28"; + pca9654 = <0>, "+29"; + xra1202 = <0>, "+30"; ++ i2c0 = <&frag0>, "target:0=",<&i2c0>, ++ <0>,"+100+101"; ++ i2c_csi_dsi = <&frag0>, "target:0=",<&i2c_csi_dsi>, ++ <0>,"+100+101"; ++ i2c3 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c3"; ++ i2c4 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c4"; ++ i2c5 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c5"; ++ i2c6 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c6"; ++ i2c-path = <&frag0>, "target?=0", ++ <&frag0>, "target-path"; + }; + }; +--- a/arch/arm/boot/dts/overlays/pcf857x-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pcf857x-overlay.dts +@@ -6,7 +6,7 @@ + / { + compatible = "brcm,bcm2835"; + +- fragment@0 { ++ frag0: fragment@0 { + target = <&i2c_arm>; + __overlay__ { + #address-cells = <1>; +@@ -22,11 +22,39 @@ + }; + }; + ++ fragment@100 { ++ target = <&i2c0if>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@101 { ++ target = <&i2c0mux>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { + pcf8574 = <&pcf857x>,"compatible=nxp,pcf8574", <&pcf857x>,"reg:0=0x20"; + pcf8574a = <&pcf857x>,"compatible=nxp,pcf8574a", <&pcf857x>,"reg:0=0x38"; + pcf8575 = <&pcf857x>,"compatible=nxp,pcf8575", <&pcf857x>,"reg:0=0x20"; + pca8574 = <&pcf857x>,"compatible=nxp,pca8574", <&pcf857x>,"reg:0=0x20"; + addr = <&pcf857x>,"reg:0"; ++ i2c0 = <&frag0>, "target:0=",<&i2c0>, ++ <0>,"+100+101"; ++ i2c_csi_dsi = <&frag0>, "target:0=",<&i2c_csi_dsi>, ++ <0>,"+100+101"; ++ i2c3 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c3"; ++ i2c4 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c4"; ++ i2c5 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c5"; ++ i2c6 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c6"; ++ i2c-path = <&frag0>, "target?=0", ++ <&frag0>, "target-path"; + }; + }; +--- a/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts ++++ b/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts +@@ -4,7 +4,7 @@ + / { + compatible = "brcm,bcm2835"; + +- fragment@0 { ++ frag0: fragment@0 { + target = <&i2c_arm>; + __overlay__ { + #address-cells = <1>; +@@ -48,10 +48,38 @@ + }; + }; + ++ fragment@100 { ++ target = <&i2c0if>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@101 { ++ target = <&i2c0mux>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { + int_pin = <&sc16is750>,"interrupts:0", <&int_pins>,"brcm,pins:0", + <&int_pins>,"reg:0"; + addr = <&sc16is750>,"reg:0", <&sc16is750_clk>,"name"; + xtal = <&sc16is750_clk>,"clock-frequency:0"; ++ i2c0 = <&frag0>, "target:0=",<&i2c0>, ++ <0>,"+100+101"; ++ i2c_csi_dsi = <&frag0>, "target:0=",<&i2c_csi_dsi>, ++ <0>,"+100+101"; ++ i2c3 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c3"; ++ i2c4 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c4"; ++ i2c5 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c5"; ++ i2c6 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c6"; ++ i2c-path = <&frag0>, "target?=0", ++ <&frag0>, "target-path"; + }; + }; +--- a/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts ++++ b/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts +@@ -4,7 +4,7 @@ + / { + compatible = "brcm,bcm2835"; + +- fragment@0 { ++ frag0: fragment@0 { + target = <&i2c_arm>; + __overlay__ { + #address-cells = <1>; +@@ -48,10 +48,38 @@ + }; + }; + ++ fragment@100 { ++ target = <&i2c0if>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@101 { ++ target = <&i2c0mux>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { + int_pin = <&sc16is752>,"interrupts:0", <&int_pins>,"brcm,pins:0", + <&int_pins>,"reg:0"; + addr = <&sc16is752>,"reg:0",<&sc16is752_clk>,"name"; + xtal = <&sc16is752_clk>,"clock-frequency:0"; ++ i2c0 = <&frag0>, "target:0=",<&i2c0>, ++ <0>,"+100+101"; ++ i2c_csi_dsi = <&frag0>, "target:0=",<&i2c_csi_dsi>, ++ <0>,"+100+101"; ++ i2c3 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c3"; ++ i2c4 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c4"; ++ i2c5 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c5"; ++ i2c6 = <&frag0>, "target?=0", ++ <&frag0>, "target-path=i2c6"; ++ i2c-path = <&frag0>, "target?=0", ++ <&frag0>, "target-path"; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.6/950-1468-misc-rp1-pio-Support-larger-data-transfers.patch b/target/linux/bcm27xx/patches-6.6/950-1468-misc-rp1-pio-Support-larger-data-transfers.patch index 828efdb79b..3183fb580e 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1468-misc-rp1-pio-Support-larger-data-transfers.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1468-misc-rp1-pio-Support-larger-data-transfers.patch @@ -1,7 +1,7 @@ From 4b0ca96738bb937529655a0062d60775f47b0f5e Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 16 Dec 2024 23:01:41 +0000 -Subject: [PATCH 1468/1482] misc: rp1-pio: Support larger data transfers +Subject: [PATCH] misc: rp1-pio: Support larger data transfers Add a separate IOCTL for larger transfer with a 32-bit data_bytes field. diff --git a/target/linux/bcm27xx/patches-6.6/950-1469-dtoverlays-Use-continuous-clock-mode-for-ov9281.patch b/target/linux/bcm27xx/patches-6.6/950-1469-dtoverlays-Use-continuous-clock-mode-for-ov9281.patch new file mode 100644 index 0000000000..c59e72eb13 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1469-dtoverlays-Use-continuous-clock-mode-for-ov9281.patch @@ -0,0 +1,34 @@ +From a4a4d7f9183bae11d81616346038e9efaba2fce1 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 16 Dec 2024 19:15:52 +0000 +Subject: [PATCH] dtoverlays: Use continuous clock mode for ov9281 + +This increases the maximum frame rate from 247 to 260fps in +10-bit mode. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/overlays/ov9281-overlay.dts | 1 - + arch/arm/boot/dts/overlays/ov9281.dtsi | 1 - + 2 files changed, 2 deletions(-) + +--- a/arch/arm/boot/dts/overlays/ov9281-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov9281-overlay.dts +@@ -29,7 +29,6 @@ + csi_ep: endpoint { + remote-endpoint = <&cam_endpoint>; + data-lanes = <1 2>; +- clock-noncontinuous; + }; + }; + }; +--- a/arch/arm/boot/dts/overlays/ov9281.dtsi ++++ b/arch/arm/boot/dts/overlays/ov9281.dtsi +@@ -19,7 +19,6 @@ cam_node: ov9281@60 { + cam_endpoint: endpoint { + clock-lanes = <0>; + data-lanes = <1 2>; +- clock-noncontinuous; + link-frequencies = + /bits/ 64 <400000000>; + }; diff --git a/target/linux/bcm27xx/patches-6.6/950-1470-overlays-goodix-Allow-override-i2c-address.patch b/target/linux/bcm27xx/patches-6.6/950-1470-overlays-goodix-Allow-override-i2c-address.patch new file mode 100644 index 0000000000..508896b3bd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1470-overlays-goodix-Allow-override-i2c-address.patch @@ -0,0 +1,36 @@ +From 62085522016ee2dadbe8668a6a97919770020817 Mon Sep 17 00:00:00 2001 +From: Renjaya Raga Zenta +Date: Wed, 18 Dec 2024 16:44:32 +0700 +Subject: [PATCH] overlays: goodix: Allow override i2c address + +Some Goodix devices e.g. gt911 use address 0x5d instead of 0x14. +So, make the address overridable. + +Signed-off-by: Renjaya Raga Zenta +--- + arch/arm/boot/dts/overlays/README | 3 ++- + arch/arm/boot/dts/overlays/goodix-overlay.dts | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -1439,7 +1439,8 @@ Name: goodix + Info: Enables I2C connected Goodix gt9271 multiple touch controller using + GPIOs 4 and 17 (pins 7 and 11 on GPIO header) for interrupt and reset. + Load: dtoverlay=goodix,= +-Params: interrupt GPIO used for interrupt (default 4) ++Params: addr I2C address (default 0x14) ++ interrupt GPIO used for interrupt (default 4) + reset GPIO used for reset (default 17) + i2c-path Override I2C path to allow for i2c-gpio buses + +--- a/arch/arm/boot/dts/overlays/goodix-overlay.dts ++++ b/arch/arm/boot/dts/overlays/goodix-overlay.dts +@@ -37,6 +37,7 @@ + }; + + __overrides__ { ++ addr = <>9271>,"reg:0"; + interrupt = <&goodix_pins>,"brcm,pins:0", + <>9271>,"interrupts:0", + <>9271>,"irq-gpios:4"; diff --git a/target/linux/bcm27xx/patches-6.6/950-1471-fixup-misc-Add-RP1-PIO-driver.patch b/target/linux/bcm27xx/patches-6.6/950-1471-fixup-misc-Add-RP1-PIO-driver.patch index 696c0d9186..5adc2a69c7 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1471-fixup-misc-Add-RP1-PIO-driver.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1471-fixup-misc-Add-RP1-PIO-driver.patch @@ -1,7 +1,7 @@ From cd26850713088942ca4f9a248a8bed1f0504a58f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 19 Dec 2024 15:11:40 +0000 -Subject: [PATCH 1471/1482] fixup! misc: Add RP1 PIO driver +Subject: [PATCH] fixup! misc: Add RP1 PIO driver Change the Kconfig dependencies so that RP1_PIO depends on FIRMWARE_RP1, rather than selecting it. diff --git a/target/linux/bcm27xx/patches-6.6/950-1473-misc-rp1-pio-More-logical-probe-sequence.patch b/target/linux/bcm27xx/patches-6.6/950-1473-misc-rp1-pio-More-logical-probe-sequence.patch index 3204997b6e..b67b029010 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1473-misc-rp1-pio-More-logical-probe-sequence.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1473-misc-rp1-pio-More-logical-probe-sequence.patch @@ -1,7 +1,7 @@ From 468b525d45a726e4ba704b33c4eba53de47ac684 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 5 Dec 2024 16:03:39 +0000 -Subject: [PATCH 1473/1482] misc: rp1-pio: More logical probe sequence +Subject: [PATCH] misc: rp1-pio: More logical probe sequence Sort the probe function initialisation into a more logical order. diff --git a/target/linux/bcm27xx/patches-6.6/950-1474-misc-rp1-pio-Convert-floats-to-24.8-fixed-point.patch b/target/linux/bcm27xx/patches-6.6/950-1474-misc-rp1-pio-Convert-floats-to-24.8-fixed-point.patch index ba997136bd..d843f1f913 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1474-misc-rp1-pio-Convert-floats-to-24.8-fixed-point.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1474-misc-rp1-pio-Convert-floats-to-24.8-fixed-point.patch @@ -1,7 +1,7 @@ From 5c07ba20630a629399eaa6583457aca93ff74606 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 9 Dec 2024 09:58:29 +0000 -Subject: [PATCH 1474/1482] misc: rp1-pio: Convert floats to 24.8 fixed point +Subject: [PATCH] misc: rp1-pio: Convert floats to 24.8 fixed point Floating point arithmetic is not supported in the kernel, so use fixed point instead. diff --git a/target/linux/bcm27xx/patches-6.6/950-1475-misc-rp1-pio-Minor-cosmetic-tweaks.patch b/target/linux/bcm27xx/patches-6.6/950-1475-misc-rp1-pio-Minor-cosmetic-tweaks.patch index 73cbacb328..439698d3ef 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1475-misc-rp1-pio-Minor-cosmetic-tweaks.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1475-misc-rp1-pio-Minor-cosmetic-tweaks.patch @@ -1,7 +1,7 @@ From 75203c6641cfe47dfb817b095430021b0981ff47 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 10 Dec 2024 12:06:14 +0000 -Subject: [PATCH 1475/1482] misc: rp1-pio: Minor cosmetic tweaks +Subject: [PATCH] misc: rp1-pio: Minor cosmetic tweaks No functional change. diff --git a/target/linux/bcm27xx/patches-6.6/950-1476-misc-rp1-pio-Add-in-kernel-DMA-support.patch b/target/linux/bcm27xx/patches-6.6/950-1476-misc-rp1-pio-Add-in-kernel-DMA-support.patch index 05c6de2b01..facfb23c95 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1476-misc-rp1-pio-Add-in-kernel-DMA-support.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1476-misc-rp1-pio-Add-in-kernel-DMA-support.patch @@ -1,7 +1,7 @@ From fddd3e9318dbf01fb763b6880021abc558fce8e6 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 12 Dec 2024 17:09:27 +0000 -Subject: [PATCH 1476/1482] misc: rp1-pio: Add in-kernel DMA support +Subject: [PATCH] misc: rp1-pio: Add in-kernel DMA support Add kernel-facing implementations of pio_sm_config_xfer and pio_xm_xfer_data. diff --git a/target/linux/bcm27xx/patches-6.6/950-1477-misc-Add-ws2812-pio-rp1-driver.patch b/target/linux/bcm27xx/patches-6.6/950-1477-misc-Add-ws2812-pio-rp1-driver.patch index 469a8a9b91..b50bdea197 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1477-misc-Add-ws2812-pio-rp1-driver.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1477-misc-Add-ws2812-pio-rp1-driver.patch @@ -1,7 +1,7 @@ From d6d83ad3d9a3a594909a1ad1c82b735ab711cd12 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 3 Dec 2024 16:09:30 +0000 -Subject: [PATCH 1477/1482] misc: Add ws2812-pio-rp1 driver +Subject: [PATCH] misc: Add ws2812-pio-rp1 driver ws2812-pio-rp1 is a PIO-based driver for WS2812 LEDS. It creates a character device in /dev, the default name of which is /dev/leds, diff --git a/target/linux/bcm27xx/patches-6.6/950-1478-overlays-Add-ws2812-pio-overlay.patch b/target/linux/bcm27xx/patches-6.6/950-1478-overlays-Add-ws2812-pio-overlay.patch index 8e5051f385..ab98fa139f 100644 --- a/target/linux/bcm27xx/patches-6.6/950-1478-overlays-Add-ws2812-pio-overlay.patch +++ b/target/linux/bcm27xx/patches-6.6/950-1478-overlays-Add-ws2812-pio-overlay.patch @@ -1,7 +1,7 @@ From 4a8f2b39157825fefc505fe4b94f3a9ce101e170 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 12 Dec 2024 23:23:39 +0000 -Subject: [PATCH 1478/1482] overlays: Add ws2812-pio overlay +Subject: [PATCH] overlays: Add ws2812-pio overlay Add an overlay to enable a WS2812 LED driver on a given GPIO. @@ -15,7 +15,7 @@ Signed-off-by: Phil Elwell --- a/arch/arm/boot/dts/overlays/Makefile +++ b/arch/arm/boot/dts/overlays/Makefile -@@ -337,7 +337,8 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ +@@ -342,7 +342,8 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ waveshare-can-fd-hat-mode-a.dtbo \ waveshare-can-fd-hat-mode-b.dtbo \ wittypi.dtbo \ @@ -27,7 +27,7 @@ Signed-off-by: Phil Elwell targets += $(dtbo-y) --- a/arch/arm/boot/dts/overlays/README +++ b/arch/arm/boot/dts/overlays/README -@@ -5487,6 +5487,28 @@ Params: alsaname Changes +@@ -5599,6 +5599,28 @@ Params: alsaname Changes compatible Changes the codec compatibility diff --git a/target/linux/bcm27xx/patches-6.6/950-1480-overlays-Add-and-document-i2c_csi_dsi0-parameters.patch b/target/linux/bcm27xx/patches-6.6/950-1480-overlays-Add-and-document-i2c_csi_dsi0-parameters.patch new file mode 100644 index 0000000000..ab0f051136 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1480-overlays-Add-and-document-i2c_csi_dsi0-parameters.patch @@ -0,0 +1,342 @@ +From 489570796a5789f849683fc3fb034c55cb13e4c6 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 19 Dec 2024 17:13:17 +0000 +Subject: [PATCH] overlays: Add and document i2c_csi_dsi0 parameters + +Add "i2c_csi_dsi0" parameters to overlays that already have an +"i2c_csi_dsi" parameter. + +The I2C bus and GPIO mapping of i2c_csi_dsi and i2c_csi_dsi0 varies +between platforms. Document the associations against the dtparams +"i2c_csi_dsi" and "i2c_csi_dsi0" - run "dtparam -h i2c_csi_dsi" +and "dtparam -h i2c_csi_dsi0" to read it. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/README | 103 ++++++++++++++++-- + .../arm/boot/dts/overlays/ads1115-overlay.dts | 2 + + .../arm/boot/dts/overlays/i2c-fan-overlay.dts | 2 + + .../arm/boot/dts/overlays/i2c-mux-overlay.dts | 2 + + .../dts/overlays/i2c-pwm-pca9685a-overlay.dts | 2 + + .../arm/boot/dts/overlays/i2c-rtc-overlay.dts | 2 + + .../boot/dts/overlays/i2c-sensor-overlay.dts | 2 + + .../boot/dts/overlays/mcp23017-overlay.dts | 2 + + .../arm/boot/dts/overlays/pca953x-overlay.dts | 2 + + .../arm/boot/dts/overlays/pcf857x-overlay.dts | 2 + + .../dts/overlays/sc16is750-i2c-overlay.dts | 2 + + .../dts/overlays/sc16is752-i2c-overlay.dts | 2 + + 12 files changed, 113 insertions(+), 12 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -301,10 +301,31 @@ Params: + i2c_baudrate An alias for i2c_arm_baudrate + + i2c_csi_dsi Set to "on" to enable the i2c_csi_dsi interface ++ The I2C bus and GPIOs are platform specific: ++ B rev 1: ++ i2c-1 on 2 & 3 ++ B rev 2, B+, CM, Zero, Zero W, 2B, CM2, CM3, ++ CM4S: ++ i2c-0 on 28 & 29 ++ 3B, 3B+, Zero 2W, 4B, 400, CM4: ++ i2c-0 on 44 & 45 ++ 5, 500: ++ i2c-11/i2c-4 on 40 & 41 ++ CM5 on CM5IO: ++ i2c-0 on 0 & 1 ++ CM5 on CM4IO: ++ i2c-10/i2c-6 on 38 & 39 + + i2c_csi_dsi0 Set to "on" to enable the i2c_csi_dsi0 interface ++ The I2C bus and GPIOs are platform specific: ++ B rev 1 & 2, B+, CM, Zero, Zero W, 2B, CM2, ++ CM3, CM4S, 3B, 3B+, Zero 2W, 4B, 400, CM4, ++ CM5 on CM4IO: ++ i2c-0 on 0 & 1 ++ 5, 500, CM5 on CM5IO: ++ i2c-10/i2c-6 on 38 & 39 + +- i2c_csi_dsi1 Set to "on" to enable the i2c_csi_dsi1 interface ++ i2c_csi_dsi1 A Pi 5 family-specific alias for i2c_csi_dsi. + + i2c_vc Set to "on" to enable the i2c interface + usually reserved for the VideoCore processor +@@ -546,7 +567,12 @@ Params: addr I2C bus + Amplifier for this channel. (Default 1 sets the + full scale of the channel to 4.096 Volts) + i2c0 Choose the I2C0 bus on GPIOs 0&1 +- i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c_csi_dsi Choose the I2C bus connected to the main ++ camera/display connector. ++ See "dtparam -h i2c_csi_dsi" for details. ++ i2c_csi_dsi0 Choose the I2C bus connected to the second ++ camera/display connector, if present. ++ See "dtparam -h i2c_csi_dsi0" for details. + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) + i2c4 Choose the I2C4 bus (configure with the i2c4 +@@ -2086,7 +2112,13 @@ Params: addr Sets the + + i2c0 Choose the I2C0 bus on GPIOs 0&1 + +- i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c_csi_dsi Choose the I2C bus connected to the main ++ camera/display connector. ++ See "dtparam -h i2c_csi_dsi" for details. ++ ++ i2c_csi_dsi0 Choose the I2C bus connected to the second ++ camera/display connector, if present. ++ See "dtparam -h i2c_csi_dsi0" for details. + + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) +@@ -2158,7 +2190,13 @@ Params: pca9542 Select t + + i2c0 Choose the I2C0 bus on GPIOs 0&1 + +- i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c_csi_dsi Choose the I2C bus connected to the main ++ camera/display connector. ++ See "dtparam -h i2c_csi_dsi" for details. ++ ++ i2c_csi_dsi0 Choose the I2C bus connected to the second ++ camera/display connector, if present. ++ See "dtparam -h i2c_csi_dsi0" for details. + + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) +@@ -2186,7 +2224,12 @@ Info: Adds support for an NXP PCA9685A + Load: dtoverlay=i2c-pwm-pca9685a,= + Params: addr I2C address of PCA9685A (default 0x40) + i2c0 Choose the I2C0 bus on GPIOs 0&1 +- i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c_csi_dsi Choose the I2C bus connected to the main ++ camera/display connector. ++ See "dtparam -h i2c_csi_dsi" for details. ++ i2c_csi_dsi0 Choose the I2C bus connected to the second ++ camera/display connector, if present. ++ See "dtparam -h i2c_csi_dsi0" for details. + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) + i2c4 Choose the I2C3 bus (configure with the i2c3 +@@ -2251,7 +2294,13 @@ Params: abx80x Select o + + i2c0 Choose the I2C0 bus on GPIOs 0&1 + +- i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c_csi_dsi Choose the I2C bus connected to the main ++ camera/display connector. ++ See "dtparam -h i2c_csi_dsi" for details. ++ ++ i2c_csi_dsi0 Choose the I2C bus connected to the second ++ camera/display connector, if present. ++ See "dtparam -h i2c_csi_dsi0" for details. + + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) +@@ -2517,7 +2566,12 @@ Params: addr Set the + + i2c0 Choose the I2C0 bus on GPIOs 0&1 + +- i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c_csi_dsi Choose the I2C bus connected to the main ++ camera/display connector. ++ See "dtparam -h i2c_csi_dsi" for details. ++ i2c_csi_dsi0 Choose the I2C bus connected to the second ++ camera/display connector, if present. ++ See "dtparam -h i2c_csi_dsi0" for details. + + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) +@@ -3144,7 +3198,12 @@ Params: gpiopin Gpio pin + mcp23008 Configure an MCP23008 instead. + noints Disable the interrupt GPIO line. + i2c0 Choose the I2C0 bus on GPIOs 0&1 +- i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c_csi_dsi Choose the I2C bus connected to the main ++ camera/display connector. ++ See "dtparam -h i2c_csi_dsi" for details. ++ i2c_csi_dsi0 Choose the I2C bus connected to the second ++ camera/display connector, if present. ++ See "dtparam -h i2c_csi_dsi0" for details. + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) + i2c4 Choose the I2C4 bus (configure with the i2c4 +@@ -3604,7 +3663,12 @@ Params: addr I2C addr + pca9654 Select the Onnn PCA9654 (8 bit) + xra1202 Select the Exar XRA1202 (8 bit) + i2c0 Choose the I2C0 bus on GPIOs 0&1 +- i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c_csi_dsi Choose the I2C bus connected to the main ++ camera/display connector. ++ See "dtparam -h i2c_csi_dsi" for details. ++ i2c_csi_dsi0 Choose the I2C bus connected to the second ++ camera/display connector, if present. ++ See "dtparam -h i2c_csi_dsi0" for details. + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) + i2c4 Choose the I2C3 bus (configure with the i2c3 +@@ -3626,7 +3690,12 @@ Params: addr I2C addr + pcf8575 Select the NXP PCF8575 (16 bit) + pca8574 Select the NXP PCA8574 (8 bit) + i2c0 Choose the I2C0 bus on GPIOs 0&1 +- i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c_csi_dsi Choose the I2C bus connected to the main ++ camera/display connector. ++ See "dtparam -h i2c_csi_dsi" for details. ++ i2c_csi_dsi0 Choose the I2C bus connected to the second ++ camera/display connector, if present. ++ See "dtparam -h i2c_csi_dsi0" for details. + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) + i2c4 Choose the I2C3 bus (configure with the i2c3 +@@ -4296,7 +4365,12 @@ Params: int_pin GPIO use + addr Address (default 0x48) + xtal On-board crystal frequency (default 14745600) + i2c0 Choose the I2C0 bus on GPIOs 0&1 +- i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c_csi_dsi Choose the I2C bus connected to the main ++ camera/display connector. ++ See "dtparam -h i2c_csi_dsi" for details. ++ i2c_csi_dsi0 Choose the I2C bus connected to the second ++ camera/display connector, if present. ++ See "dtparam -h i2c_csi_dsi0" for details. + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) + i2c4 Choose the I2C4 bus (configure with the i2c4 +@@ -4325,7 +4399,12 @@ Params: int_pin GPIO use + addr Address (default 0x48) + xtal On-board crystal frequency (default 14745600) + i2c0 Choose the I2C0 bus on GPIOs 0&1 +- i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ i2c_csi_dsi Choose the I2C bus connected to the main ++ camera/display connector. ++ See "dtparam -h i2c_csi_dsi" for details. ++ i2c_csi_dsi0 Choose the I2C bus connected to the second ++ camera/display connector, if present. ++ See "dtparam -h i2c_csi_dsi0" for details. + i2c3 Choose the I2C3 bus (configure with the i2c3 + overlay - BCM2711 only) + i2c4 Choose the I2C4 bus (configure with the i2c4 +--- a/arch/arm/boot/dts/overlays/ads1115-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts +@@ -123,6 +123,8 @@ + i2c0 = <&frag100>, "target:0=",<&i2c0>; + i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, + <0>,"+101+102"; ++ i2c_csi_dsi0 = <&frag100>, "target:0=",<&i2c_csi_dsi0>, ++ <0>,"+101+102"; + i2c3 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c3"; + i2c4 = <&frag100>, "target?=0", +--- a/arch/arm/boot/dts/overlays/i2c-fan-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-fan-overlay.dts +@@ -85,6 +85,8 @@ + i2c0 = <&frag100>,"target:0=",<&i2c0>; + i2c_csi_dsi = <&frag100>,"target:0=",<&i2c_csi_dsi>, + <0>,"+101+102"; ++ i2c_csi_dsi0 = <&frag100>, "target:0=",<&i2c_csi_dsi0>, ++ <0>,"+101+102"; + i2c3 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c3"; + i2c4 = <&frag100>, "target?=0", +--- a/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-mux-overlay.dts +@@ -167,6 +167,8 @@ + <0>,"+101+102"; + i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, + <0>,"+101+102"; ++ i2c_csi_dsi0 = <&frag100>, "target:0=",<&i2c_csi_dsi0>, ++ <0>,"+101+102"; + i2c3 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c3"; + i2c4 = <&frag100>, "target?=0", +--- a/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts +@@ -49,6 +49,8 @@ + <0>,"+101+102"; + i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, + <0>,"+101+102"; ++ i2c_csi_dsi0 = <&frag100>, "target:0=",<&i2c_csi_dsi0>, ++ <0>,"+101+102"; + i2c3 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c3"; + i2c4 = <&frag100>, "target?=0", +--- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts +@@ -30,6 +30,8 @@ + i2c0 = <&frag100>, "target:0=",<&i2c0>; + i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, + <0>,"+101+102"; ++ i2c_csi_dsi0 = <&frag100>, "target:0=",<&i2c_csi_dsi0>, ++ <0>,"+101+102"; + i2c3 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c3"; + i2c4 = <&frag100>, "target?=0", +--- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts +@@ -30,6 +30,8 @@ + i2c0 = <&frag100>, "target:0=",<&i2c0>; + i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, + <0>,"+101+102"; ++ i2c_csi_dsi0 = <&frag100>, "target:0=",<&i2c_csi_dsi0>, ++ <0>,"+101+102"; + i2c3 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c3"; + i2c4 = <&frag100>, "target?=0", +--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts ++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts +@@ -90,6 +90,8 @@ + i2c0 = <&frag100>, "target:0=",<&i2c0>; + i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, + <0>,"+101+102"; ++ i2c_csi_dsi0 = <&frag100>, "target:0=",<&i2c_csi_dsi0>, ++ <0>,"+101+102"; + i2c3 = <&frag100>, "target?=0", + <&frag100>, "target-path=i2c3"; + i2c4 = <&frag100>, "target?=0", +--- a/arch/arm/boot/dts/overlays/pca953x-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pca953x-overlay.dts +@@ -254,6 +254,8 @@ + <0>,"+100+101"; + i2c_csi_dsi = <&frag0>, "target:0=",<&i2c_csi_dsi>, + <0>,"+100+101"; ++ i2c_csi_dsi0 = <&frag0>, "target:0=",<&i2c_csi_dsi0>, ++ <0>,"+100+101"; + i2c3 = <&frag0>, "target?=0", + <&frag0>, "target-path=i2c3"; + i2c4 = <&frag0>, "target?=0", +--- a/arch/arm/boot/dts/overlays/pcf857x-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pcf857x-overlay.dts +@@ -46,6 +46,8 @@ + <0>,"+100+101"; + i2c_csi_dsi = <&frag0>, "target:0=",<&i2c_csi_dsi>, + <0>,"+100+101"; ++ i2c_csi_dsi0 = <&frag0>, "target:0=",<&i2c_csi_dsi0>, ++ <0>,"+100+101"; + i2c3 = <&frag0>, "target?=0", + <&frag0>, "target-path=i2c3"; + i2c4 = <&frag0>, "target?=0", +--- a/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts ++++ b/arch/arm/boot/dts/overlays/sc16is750-i2c-overlay.dts +@@ -71,6 +71,8 @@ + <0>,"+100+101"; + i2c_csi_dsi = <&frag0>, "target:0=",<&i2c_csi_dsi>, + <0>,"+100+101"; ++ i2c_csi_dsi0 = <&frag0>, "target:0=",<&i2c_csi_dsi0>, ++ <0>,"+100+101"; + i2c3 = <&frag0>, "target?=0", + <&frag0>, "target-path=i2c3"; + i2c4 = <&frag0>, "target?=0", +--- a/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts ++++ b/arch/arm/boot/dts/overlays/sc16is752-i2c-overlay.dts +@@ -71,6 +71,8 @@ + <0>,"+100+101"; + i2c_csi_dsi = <&frag0>, "target:0=",<&i2c_csi_dsi>, + <0>,"+100+101"; ++ i2c_csi_dsi0 = <&frag0>, "target:0=",<&i2c_csi_dsi0>, ++ <0>,"+100+101"; + i2c3 = <&frag0>, "target?=0", + <&frag0>, "target-path=i2c3"; + i2c4 = <&frag0>, "target?=0", diff --git a/target/linux/bcm27xx/patches-6.6/950-1481-dts-Add-noanthogs-parameter-to-CM4-and-CM5.patch b/target/linux/bcm27xx/patches-6.6/950-1481-dts-Add-noanthogs-parameter-to-CM4-and-CM5.patch new file mode 100644 index 0000000000..483031057c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1481-dts-Add-noanthogs-parameter-to-CM4-and-CM5.patch @@ -0,0 +1,56 @@ +From 147ddfdaf626fe5484596235bba8bdc6dcfde501 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 20 Dec 2024 15:08:52 +0000 +Subject: [PATCH] dts: Add noanthogs parameter to CM4 and CM5 + +By default, the antenna selection on CM4 and CM5 is fixed at boot time, +with the dtparams ant1, ant2 and noant selecting which should be +enabled. Add a new dtparam - noanthogs - which leaves the GPIOs free +to be controlled at runtime by the OS. + +N.B. Using this parameter without suitable OS support will leave both +antennae disabled, resulting in attenuated WiFi and Bluetooth signals. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4.dts | 2 ++ + arch/arm/boot/dts/overlays/README | 6 ++++++ + arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi | 2 ++ + 3 files changed, 10 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4.dts ++++ b/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4.dts +@@ -493,6 +493,8 @@ i2c_csi_dsi0: &i2c0 { + <&ant1>, "output-low?=on", + <&ant2>, "output-high?=off", + <&ant2>, "output-low?=on"; ++ noanthogs = <&ant1>,"status=disabled", ++ <&ant2>, "status=disabled"; + + pcie_tperst_clk_ms = <&pcie0>,"brcm,tperst-clk-ms:0"; + }; +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -153,6 +153,12 @@ Params: + + noant Disable both antennas. CM4/5 only. + ++ noanthogs Disable the GPIO hogs on the antenna controls ++ so they can be controlled at runtime. Note that ++ using this parameter without suitable OS ++ support will result in attenuated WiFi and ++ Bluetooth signals. CM4/5 only. ++ + audio Set to "on" to enable the onboard ALSA audio + interface (default "off") + +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi +@@ -750,5 +750,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + <&ant1>, "output-low?=on", + <&ant2>, "output-high?=off", + <&ant2>, "output-low?=on"; ++ noanthogs = <&ant1>,"status=disabled", ++ <&ant2>, "status=disabled"; + }; + }; -- 2.30.2