mirror of
https://github.com/openwrt/openwrt.git
synced 2025-04-15 06:57:08 +00:00
bcm27xx: update 6.1 patches to latest version
Add support for BCM2712 (Raspberry Pi 5).
3bb5880ab3
Patches were generated from the diff between linux kernel branch linux-6.1.y
and rpi-6.1.y from raspberry pi kernel source:
- git format-patch linux-6.1.y...rpi-6.1.y
Build system: x86_64
Build-tested: bcm2708, bcm2709, bcm2710, bcm2711
Run-tested: bcm2710/RPi3B, bcm2711/RPi4B
Signed-off-by: Marty Jones <mj8263788@gmail.com>
[Remove applied and reverted patches, squash patches and config commits]
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
This commit is contained in:
parent
65f599223d
commit
2e715fb4fc
target/linux/bcm27xx
bcm2708
bcm2709
bcm2710
bcm2711
patches-6.1
950-0699-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch950-0790-media-i2c-imx219-fix-binning-and-rate_factor-for-480.patch950-0791-serial-sc16is7xx-Read-modem-line-state-at-startup.patch950-0792-drivers-media-bcm2835_unicam-Improve-frame-sequence-.patch950-0793-dtoverlays-Fix-pitft-28-35-overlays-for-6.1-driver-c.patch950-0795-driver-media-i2c-imx477-Re-enable-temperature-sensor.patch950-0796-overlays-allo-katana-dac-audio-Reduce-I2C-clock.patch950-0797-overlays-jedec-spi-nor-Add-speed-parameter.patch950-0798-ALSA-pcm-fix-ELD-constraints-for-E-AC3-DTS-HD-and-ML.patch950-0799-ASoC-hdmi-codec-fix-channel-info-for-compressed-form.patch950-0800-media-i2c-arducam_64mp-Modify-the-line-length-of-128.patch950-0801-media-i2c-arducam_64mp-Add-8000x6000-resolution.patch950-0802-media-i2c-arducam_64mp-Add-PDAF-support.patch950-0803-overlays-audremap-Document-CM4-40-41-restriction.patch950-0804-fixup-Allow-mac-address-to-be-set-in-smsc95xx.patch950-0809-cfg80211-ship-debian-certificates-as-hex-files.patch950-0810-fixup-Add-support-for-all-the-downstream-rpi-sound-c.patch950-0815-fixup-drm-tc358762-Set-the-pre_enable_upstream_first.patch950-0816-rpi-sound-cards-Fix-Codec-Zero-rate-switching.patch950-0818-overlays-Add-trickle-voltage-mv-parameter-to-RTCs.patch950-0819-drivers-media-imx296-Add-standby-delay-during-probe.patch950-0820-overlays-Add-bmp380-to-i2c-sensor-overlay.patch950-0821-can-isotp-add-module-parameter-for-maximum-pdu-size.patch950-0822-drivers-media-imx296-Updated-imx296-driver-for-exter.patch950-0823-media-dt-bindings-imx258-Fix-alternate-compatible-st.patch950-0825-char-broadcom-vc_mem-Fix-preprocessor-conditional.patch950-0826-drivers-dwc_otg-Fix-fallthrough-warnings.patch950-0827-vc04_services-vc-sm-cma-Switch-one-bit-bitfields-to-.patch950-0828-media-i2c-ov2311-Fix-uninitialized-variable-usage.patch950-0830-drm-panel-Fix-default-values-for-Waveshare-7.9-inch-.patch950-0831-dtoverlays-Add-i2c-bus-overrides-to-edt-ft5406-overl.patch950-0832-dtoverlays-Fix-README-text-for-i2c-fan.patch950-0833-drivers-irqchip-irq-bcm2835-Concurrency-fix.patch950-0835-dtoverlays-Add-drm-option-to-piscreen-overlay.patch950-0836-drm-ili9486-Resolve-clash-in-spi_device_id-names.patch950-0837-input-ads7846-Add-missing-spi_device_id-strings.patch950-0838-staging-bcm2835-codec-Downgrade-the-level-for-a-debu.patch950-0840-gpio-fsm-Sort-functions-into-a-more-logical-order.patch950-0841-gpio_fsm-Rework-the-atomic-vs-non-atomic-split.patch950-0842-f2fs-fix-to-avoid-NULL-pointer-dereference-in-f2fs_i.patch950-0846-hwrng-iproc-rng200-Add-BCM2838-support.patch950-0847-PCI-brcmstb-Wait-for-100ms-following-PERST-deassert.patch950-0850-overlays-Add-a-sample-hat_map.patch950-0851-Revert-usb-phy-generic-Get-the-vbus-supply.patch950-0853-dts-2712-Update-for-device-tree.patch950-0855-gpio_brcmstb-Allow-to-build-for-ARCH_BCM2835.patch950-0856-Allow-RESET_BRCMSTB-on-ARCH_BCM2835.patch950-0857-pinctrl-bcm2712-pinctrl-pinconf-driver.patch950-0859-mmc-brcmstb-add-support-for-BCM2712.patch950-0860-sdhci-Add-SD-Express-hook.patch950-0861-Add-new-pispbe-driver-though-not-yet-the-Makesfiles-.patch950-0862-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch950-0863-reset-reset-brcmstb-rescal-Support-shared-use.patch950-0864-net-macb-Also-set-DMA-coherent-mask.patch950-0865-usb-dwc3-Set-DMA-and-coherent-masks-early.patch950-0866-drm-panel-raspberrypi-touchscreen-Insert-more-delays.patch950-0867-PCI-brcmstb-Add-BCM2712-support.patch950-0868-V4L2-Add-PiSP-opaque-formats-to-V4L2.patch950-0869-V4L2-Add-PiSP-compressed-formats-to-V4L2.patch950-0871-dt-binding-mfd-Add-binding-for-Raspberry-Pi-RP1.patch950-0872-mfd-Add-rp1-driver.patch950-0873-dt-bindings-clock-Add-bindings-for-Raspberry-Pi-RP1.patch950-0874-clk-Add-rp1-clock-driver.patch950-0875-dt-bindings-pinctrl-Add-bindings-for-Raspberry-Pi-RP.patch950-0876-pinctrl-Add-rp1-driver.patch950-0877-serial-pl011-rp1-uart-support.patch950-0878-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch950-0879-mmc-sdhci-of-dwcmshc-rp1-sdio-changes.patch950-0880-clk-rp1-Add-sdio-clk-driver.patch950-0881-i2c-designware-Add-SMBUS-quick-command-support.patch950-0882-dmaengine-dw-axi-dmac-Fixes-for-RP1.patch950-0883-spi-dw-Handle-combined-tx-and-rx-messages.patch950-0884-pwm-Add-support-for-RP1-PWM.patch950-0885-drm-Add-RP1-DSI-driver.patch950-0886-drm-Add-RP1-DPI-driver.patch950-0887-drm-Add-RP1-VEC-driver.patch950-0888-v4l2-Add-pisp-compression-format-support-to-v4l2.patch950-0889-media-rp1-Add-CFE-Camera-Front-End-support.patch950-0890-dt-bindings-net-cdns-macb-AXI-tuning-properties.patch950-0891-ASoC-dwc-list-all-supported-sample-sizes.patch950-0892-ASoC-dwc-Support-set_bclk_ratio.patch950-0893-ASoC-dwc-Add-DMACR-handling.patch950-0894-ASOC-dwc-Improve-DMA-shutdown.patch950-0895-ASOC-dwc-Fix-16-bit-audio-handling.patch950-0896-ASoC-bcm-Remove-dependency-on-BCM2835-I2S.patch950-0897-hwmon-Add-RP1-ADC-and-temperature-driver.patch950-0898-mfd-bcm2835-pm-Add-support-for-BCM2712.patch950-0899-soc-bcm-bcm2835-power-Add-support-for-BCM2712.patch950-0900-drivers-spi-Fix-spi-gpio-to-correctly-implement-sck-.patch950-0901-spi-spi-gpio-Implement-spidelay-when-requested-bit-r.patch950-0902-drm-v3d-fix-up-register-addresses-for-V3D-7.x.patch950-0903-drm-v3d-update-UAPI-to-match-user-space-for-V3D-7.x.patch950-0904-drm-v3d-add-brcm-2712-v3d-as-a-compatible-V3D-device.patch950-0905-drm-v3d-Improve-MMU-support-for-larger-pages.patch950-0906-dt-bindings-gpu-v3d-Add-BCM2712-to-compatibility-lis.patch950-0907-drivers-char-add-generic-gpiomem-driver.patch
@ -30,7 +30,6 @@ CONFIG_ARM_UNWIND=y
|
||||
CONFIG_AUTO_ZRELADDR=y
|
||||
CONFIG_BCM2708_VCMEM=y
|
||||
# CONFIG_BCM2711_THERMAL is not set
|
||||
CONFIG_BCM2835_DEVGPIOMEM=y
|
||||
CONFIG_BCM2835_FAST_MEMCPY=y
|
||||
CONFIG_BCM2835_MBOX=y
|
||||
CONFIG_BCM2835_POWER=y
|
||||
@ -151,7 +150,6 @@ CONFIG_FB_CFB_COPYAREA=y
|
||||
CONFIG_FB_CFB_FILLRECT=y
|
||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||
CONFIG_FB_CMDLINE=y
|
||||
# CONFIG_FB_RPISENSE is not set
|
||||
CONFIG_FB_SIMPLE=y
|
||||
CONFIG_FIQ=y
|
||||
CONFIG_FIXED_PHY=y
|
||||
@ -239,8 +237,6 @@ CONFIG_MDIO_DEVRES=y
|
||||
CONFIG_MEMFD_CREATE=y
|
||||
CONFIG_MEMORY_ISOLATION=y
|
||||
CONFIG_MFD_CORE=y
|
||||
# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set
|
||||
# CONFIG_MFD_RPISENSE_CORE is not set
|
||||
CONFIG_MFD_SYSCON=y
|
||||
CONFIG_MIGHT_HAVE_CACHE_L2X0=y
|
||||
CONFIG_MIGRATION=y
|
||||
@ -266,6 +262,7 @@ CONFIG_NO_HZ=y
|
||||
CONFIG_NO_HZ_COMMON=y
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_NVMEM_LAYOUTS=y
|
||||
CONFIG_OF=y
|
||||
CONFIG_OF_ADDRESS=y
|
||||
CONFIG_OF_CONFIGFS=y
|
||||
@ -296,7 +293,6 @@ CONFIG_PM_GENERIC_DOMAINS_OF=y
|
||||
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
|
||||
CONFIG_PM_OPP=y
|
||||
CONFIG_PM_SLEEP=y
|
||||
# CONFIG_PM_USERSPACE_AUTOSLEEP is not set
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
CONFIG_PREEMPT_NONE_BUILD=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
@ -306,6 +302,7 @@ CONFIG_PWM_BCM2835=y
|
||||
CONFIG_PWM_SYSFS=y
|
||||
CONFIG_RANDSTRUCT_NONE=y
|
||||
CONFIG_RASPBERRYPI_FIRMWARE=y
|
||||
CONFIG_RASPBERRYPI_GPIOMEM=y
|
||||
CONFIG_RASPBERRYPI_POWER=y
|
||||
CONFIG_RATIONAL=y
|
||||
# CONFIG_RAVE_SP_CORE is not set
|
||||
|
@ -39,7 +39,6 @@ CONFIG_ASSOCIATIVE_ARRAY=y
|
||||
CONFIG_AUTO_ZRELADDR=y
|
||||
CONFIG_BCM2708_VCMEM=y
|
||||
CONFIG_BCM2711_THERMAL=y
|
||||
CONFIG_BCM2835_DEVGPIOMEM=y
|
||||
CONFIG_BCM2835_MBOX=y
|
||||
CONFIG_BCM2835_POWER=y
|
||||
# CONFIG_BCM2835_SMI is not set
|
||||
@ -186,7 +185,6 @@ CONFIG_FB_CFB_COPYAREA=y
|
||||
CONFIG_FB_CFB_FILLRECT=y
|
||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||
CONFIG_FB_CMDLINE=y
|
||||
# CONFIG_FB_RPISENSE is not set
|
||||
CONFIG_FB_SIMPLE=y
|
||||
CONFIG_FIQ=y
|
||||
CONFIG_FIXED_PHY=y
|
||||
@ -297,8 +295,6 @@ CONFIG_MDIO_DEVRES=y
|
||||
CONFIG_MEMFD_CREATE=y
|
||||
CONFIG_MEMORY_ISOLATION=y
|
||||
CONFIG_MFD_CORE=y
|
||||
# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set
|
||||
# CONFIG_MFD_RPISENSE_CORE is not set
|
||||
CONFIG_MFD_SYSCON=y
|
||||
CONFIG_MICROCHIP_PHY=y
|
||||
CONFIG_MIGHT_HAVE_CACHE_L2X0=y
|
||||
@ -332,6 +328,7 @@ CONFIG_NO_HZ_COMMON=y
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_NVMEM_LAYOUTS=y
|
||||
CONFIG_OF=y
|
||||
CONFIG_OF_ADDRESS=y
|
||||
CONFIG_OF_CONFIGFS=y
|
||||
@ -374,7 +371,6 @@ CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
|
||||
CONFIG_PM_OPP=y
|
||||
CONFIG_PM_SLEEP=y
|
||||
CONFIG_PM_SLEEP_SMP=y
|
||||
# CONFIG_PM_USERSPACE_AUTOSLEEP is not set
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
CONFIG_PPS=y
|
||||
CONFIG_PREEMPT_NONE_BUILD=y
|
||||
@ -387,6 +383,7 @@ CONFIG_PWM_SYSFS=y
|
||||
CONFIG_RANDSTRUCT_NONE=y
|
||||
CONFIG_RAS=y
|
||||
CONFIG_RASPBERRYPI_FIRMWARE=y
|
||||
CONFIG_RASPBERRYPI_GPIOMEM=y
|
||||
CONFIG_RASPBERRYPI_POWER=y
|
||||
CONFIG_RATIONAL=y
|
||||
# CONFIG_RAVE_SP_CORE is not set
|
||||
|
@ -60,7 +60,6 @@ CONFIG_ASSOCIATIVE_ARRAY=y
|
||||
CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
|
||||
CONFIG_BCM2708_VCMEM=y
|
||||
# CONFIG_BCM2711_THERMAL is not set
|
||||
CONFIG_BCM2835_DEVGPIOMEM=y
|
||||
CONFIG_BCM2835_MBOX=y
|
||||
CONFIG_BCM2835_POWER=y
|
||||
# CONFIG_BCM2835_SMI is not set
|
||||
@ -152,7 +151,6 @@ CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
|
||||
CONFIG_CRYPTO_LIB_SHA1=y
|
||||
CONFIG_CRYPTO_LIB_SHA256=y
|
||||
CONFIG_CRYPTO_LIB_UTILS=y
|
||||
# CONFIG_CRYPTO_POLYVAL_ARM64_CE is not set
|
||||
CONFIG_CRYPTO_RNG=y
|
||||
CONFIG_CRYPTO_RNG2=y
|
||||
CONFIG_CRYPTO_RNG_DEFAULT=y
|
||||
@ -161,8 +159,6 @@ CONFIG_CRYPTO_SHA256=y
|
||||
CONFIG_CRYPTO_SHA256_ARM64=y
|
||||
CONFIG_CRYPTO_SHA512=y
|
||||
CONFIG_CRYPTO_SHA512_ARM64=y
|
||||
# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set
|
||||
# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set
|
||||
CONFIG_CRYPTO_XTS=y
|
||||
CONFIG_DCACHE_WORD_ACCESS=y
|
||||
CONFIG_DEBUG_BUGVERBOSE=y
|
||||
@ -195,7 +191,6 @@ CONFIG_FB_CFB_COPYAREA=y
|
||||
CONFIG_FB_CFB_FILLRECT=y
|
||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||
CONFIG_FB_CMDLINE=y
|
||||
# CONFIG_FB_RPISENSE is not set
|
||||
CONFIG_FB_SIMPLE=y
|
||||
CONFIG_FIXED_PHY=y
|
||||
CONFIG_FIX_EARLYCON_MEM=y
|
||||
@ -299,8 +294,6 @@ CONFIG_MDIO_DEVRES=y
|
||||
CONFIG_MEMFD_CREATE=y
|
||||
CONFIG_MEMORY_ISOLATION=y
|
||||
CONFIG_MFD_CORE=y
|
||||
# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set
|
||||
# CONFIG_MFD_RPISENSE_CORE is not set
|
||||
CONFIG_MFD_SYSCON=y
|
||||
CONFIG_MICROCHIP_PHY=y
|
||||
CONFIG_MIGRATION=y
|
||||
@ -332,6 +325,7 @@ CONFIG_NO_HZ_COMMON=y
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_NVMEM_LAYOUTS=y
|
||||
CONFIG_OF=y
|
||||
CONFIG_OF_ADDRESS=y
|
||||
CONFIG_OF_CONFIGFS=y
|
||||
@ -368,7 +362,6 @@ CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
|
||||
CONFIG_PM_OPP=y
|
||||
CONFIG_PM_SLEEP=y
|
||||
CONFIG_PM_SLEEP_SMP=y
|
||||
# CONFIG_PM_USERSPACE_AUTOSLEEP is not set
|
||||
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
|
||||
CONFIG_POWER_RESET=y
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
@ -382,6 +375,7 @@ CONFIG_QUEUED_RWLOCKS=y
|
||||
CONFIG_QUEUED_SPINLOCKS=y
|
||||
CONFIG_RANDSTRUCT_NONE=y
|
||||
CONFIG_RASPBERRYPI_FIRMWARE=y
|
||||
CONFIG_RASPBERRYPI_GPIOMEM=y
|
||||
CONFIG_RASPBERRYPI_POWER=y
|
||||
CONFIG_RATIONAL=y
|
||||
# CONFIG_RAVE_SP_CORE is not set
|
||||
|
@ -54,7 +54,6 @@ CONFIG_ASSOCIATIVE_ARRAY=y
|
||||
CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
|
||||
CONFIG_BCM2708_VCMEM=y
|
||||
CONFIG_BCM2711_THERMAL=y
|
||||
CONFIG_BCM2835_DEVGPIOMEM=y
|
||||
CONFIG_BCM2835_MBOX=y
|
||||
CONFIG_BCM2835_POWER=y
|
||||
# CONFIG_BCM2835_SMI is not set
|
||||
@ -150,7 +149,6 @@ CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
|
||||
CONFIG_CRYPTO_LIB_SHA1=y
|
||||
CONFIG_CRYPTO_LIB_SHA256=y
|
||||
CONFIG_CRYPTO_LIB_UTILS=y
|
||||
# CONFIG_CRYPTO_POLYVAL_ARM64_CE is not set
|
||||
CONFIG_CRYPTO_RNG=y
|
||||
CONFIG_CRYPTO_RNG2=y
|
||||
CONFIG_CRYPTO_RNG_DEFAULT=y
|
||||
@ -159,8 +157,6 @@ CONFIG_CRYPTO_SHA256=y
|
||||
CONFIG_CRYPTO_SHA256_ARM64=y
|
||||
CONFIG_CRYPTO_SHA512=y
|
||||
CONFIG_CRYPTO_SHA512_ARM64=y
|
||||
# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set
|
||||
# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set
|
||||
CONFIG_CRYPTO_XTS=y
|
||||
CONFIG_DCACHE_WORD_ACCESS=y
|
||||
CONFIG_DEBUG_BUGVERBOSE=y
|
||||
@ -194,7 +190,6 @@ CONFIG_FB_CFB_COPYAREA=y
|
||||
CONFIG_FB_CFB_FILLRECT=y
|
||||
CONFIG_FB_CFB_IMAGEBLIT=y
|
||||
CONFIG_FB_CMDLINE=y
|
||||
# CONFIG_FB_RPISENSE is not set
|
||||
CONFIG_FB_SIMPLE=y
|
||||
CONFIG_FIXED_PHY=y
|
||||
CONFIG_FIX_EARLYCON_MEM=y
|
||||
@ -300,8 +295,6 @@ CONFIG_MDIO_DEVRES=y
|
||||
CONFIG_MEMFD_CREATE=y
|
||||
CONFIG_MEMORY_ISOLATION=y
|
||||
CONFIG_MFD_CORE=y
|
||||
# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set
|
||||
# CONFIG_MFD_RPISENSE_CORE is not set
|
||||
CONFIG_MFD_SYSCON=y
|
||||
CONFIG_MIGRATION=y
|
||||
CONFIG_MMC=y
|
||||
@ -333,6 +326,7 @@ CONFIG_NO_HZ_COMMON=y
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_NVMEM_LAYOUTS=y
|
||||
CONFIG_OF=y
|
||||
CONFIG_OF_ADDRESS=y
|
||||
CONFIG_OF_CONFIGFS=y
|
||||
@ -372,7 +366,6 @@ CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
|
||||
CONFIG_PM_OPP=y
|
||||
CONFIG_PM_SLEEP=y
|
||||
CONFIG_PM_SLEEP_SMP=y
|
||||
# CONFIG_PM_USERSPACE_AUTOSLEEP is not set
|
||||
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
|
||||
CONFIG_POWER_RESET=y
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
@ -389,6 +382,7 @@ CONFIG_QUEUED_SPINLOCKS=y
|
||||
CONFIG_RANDSTRUCT_NONE=y
|
||||
CONFIG_RAS=y
|
||||
CONFIG_RASPBERRYPI_FIRMWARE=y
|
||||
CONFIG_RASPBERRYPI_GPIOMEM=y
|
||||
CONFIG_RASPBERRYPI_POWER=y
|
||||
CONFIG_RATIONAL=y
|
||||
# CONFIG_RAVE_SP_CORE is not set
|
||||
|
@ -1,41 +0,0 @@
|
||||
From dffb648dffeab7246040a30b7d1669387d1e767e Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Tue, 25 Apr 2023 11:49:41 +0100
|
||||
Subject: [PATCH] Bluetooth: hci_sync: Add fallback-bd-address prop
|
||||
|
||||
The kernel Bluetooth framework understands that devices may not
|
||||
be programmed with valid Bluetooth addresses. It also has the ability
|
||||
to override a Bluetooth address with the value of the local-bd-address
|
||||
DT property, but it ignores the validity of the existing address when
|
||||
doing so.
|
||||
|
||||
Add a new boolean property, fallback-bd-address, which indicates that
|
||||
the given local-bd-address property should only be used if the device
|
||||
does not already have a valid BDADDR.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
net/bluetooth/hci_sync.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/net/bluetooth/hci_sync.c
|
||||
+++ b/net/bluetooth/hci_sync.c
|
||||
@@ -4630,6 +4630,7 @@ static const struct {
|
||||
*/
|
||||
static int hci_dev_setup_sync(struct hci_dev *hdev)
|
||||
{
|
||||
+ struct fwnode_handle *fwnode = dev_fwnode(hdev->dev.parent);
|
||||
int ret = 0;
|
||||
bool invalid_bdaddr;
|
||||
size_t i;
|
||||
@@ -4658,7 +4659,9 @@ static int hci_dev_setup_sync(struct hci
|
||||
|
||||
if (!ret) {
|
||||
if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks) &&
|
||||
- !bacmp(&hdev->public_addr, BDADDR_ANY))
|
||||
+ !bacmp(&hdev->public_addr, BDADDR_ANY) &&
|
||||
+ (invalid_bdaddr ||
|
||||
+ !fwnode_property_present(fwnode, "fallback-bd-address")))
|
||||
hci_dev_get_bd_addr_from_property(hdev);
|
||||
|
||||
if ((invalid_bdaddr ||
|
306
target/linux/bcm27xx/patches-6.1/950-0790-media-i2c-imx219-fix-binning-and-rate_factor-for-480.patch
Normal file
306
target/linux/bcm27xx/patches-6.1/950-0790-media-i2c-imx219-fix-binning-and-rate_factor-for-480.patch
Normal file
@ -0,0 +1,306 @@
|
||||
From 3ad8e28669e0058e3cec482a47215e50e33f2574 Mon Sep 17 00:00:00 2001
|
||||
From: Vinay Varma <varmavinaym@gmail.com>
|
||||
Date: Sun, 11 Jun 2023 23:45:03 +0800
|
||||
Subject: [PATCH] media: i2c: imx219: fix binning and rate_factor for 480p and
|
||||
1232p
|
||||
|
||||
At a high FPS with RAW10, there is frame corruption for 480p because the
|
||||
rate_factor of 2 is used with the normal 2x2 bining [1]. This commit
|
||||
ties the rate_factor to the selected binning mode. For the 480p mode,
|
||||
analog 2x2 binning mode with a rate_factor of 2 is always used. For the
|
||||
1232p mode the normal 2x2 binning mode is used for RAW10 while analog
|
||||
2x2 binning mode is used for RAW8.
|
||||
|
||||
[1] https://github.com/raspberrypi/linux/issues/5493
|
||||
|
||||
Signed-off-by: Vinay Varma <varmavinaym@gmail.com>
|
||||
---
|
||||
drivers/media/i2c/imx219.c | 143 ++++++++++++++++++++++++++-----------
|
||||
1 file changed, 100 insertions(+), 43 deletions(-)
|
||||
|
||||
--- a/drivers/media/i2c/imx219.c
|
||||
+++ b/drivers/media/i2c/imx219.c
|
||||
@@ -136,6 +136,18 @@ enum pad_types {
|
||||
NUM_PADS
|
||||
};
|
||||
|
||||
+enum binning_mode {
|
||||
+ BINNING_NONE,
|
||||
+ BINNING_DIGITAL_2x2,
|
||||
+ BINNING_ANALOG_2x2,
|
||||
+};
|
||||
+
|
||||
+enum binning_bit_depths {
|
||||
+ BINNING_IDX_8_BIT,
|
||||
+ BINNING_IDX_10_BIT,
|
||||
+ BINNING_IDX_MAX
|
||||
+};
|
||||
+
|
||||
struct imx219_reg {
|
||||
u16 address;
|
||||
u8 val;
|
||||
@@ -162,11 +174,8 @@ struct imx219_mode {
|
||||
/* Default register values */
|
||||
struct imx219_reg_list reg_list;
|
||||
|
||||
- /* 2x2 binning is used */
|
||||
- bool binning;
|
||||
-
|
||||
- /* Relative pixel clock rate factor for the mode. */
|
||||
- unsigned int rate_factor;
|
||||
+ /* binning mode based on format code */
|
||||
+ enum binning_mode binning[BINNING_IDX_MAX];
|
||||
};
|
||||
|
||||
static const struct imx219_reg imx219_common_regs[] = {
|
||||
@@ -404,8 +413,10 @@ static const struct imx219_mode supporte
|
||||
.num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
|
||||
.regs = mode_3280x2464_regs,
|
||||
},
|
||||
- .binning = false,
|
||||
- .rate_factor = 1,
|
||||
+ .binning = {
|
||||
+ [BINNING_IDX_8_BIT] = BINNING_NONE,
|
||||
+ [BINNING_IDX_10_BIT] = BINNING_NONE,
|
||||
+ },
|
||||
},
|
||||
{
|
||||
/* 1080P 30fps cropped */
|
||||
@@ -422,8 +433,10 @@ static const struct imx219_mode supporte
|
||||
.num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
|
||||
.regs = mode_1920_1080_regs,
|
||||
},
|
||||
- .binning = false,
|
||||
- .rate_factor = 1,
|
||||
+ .binning = {
|
||||
+ [BINNING_IDX_8_BIT] = BINNING_NONE,
|
||||
+ [BINNING_IDX_10_BIT] = BINNING_NONE,
|
||||
+ },
|
||||
},
|
||||
{
|
||||
/* 2x2 binned 30fps mode */
|
||||
@@ -440,8 +453,10 @@ static const struct imx219_mode supporte
|
||||
.num_of_regs = ARRAY_SIZE(mode_1640_1232_regs),
|
||||
.regs = mode_1640_1232_regs,
|
||||
},
|
||||
- .binning = true,
|
||||
- .rate_factor = 1,
|
||||
+ .binning = {
|
||||
+ [BINNING_IDX_8_BIT] = BINNING_ANALOG_2x2,
|
||||
+ [BINNING_IDX_10_BIT] = BINNING_DIGITAL_2x2,
|
||||
+ },
|
||||
},
|
||||
{
|
||||
/* 640x480 30fps mode */
|
||||
@@ -458,12 +473,10 @@ static const struct imx219_mode supporte
|
||||
.num_of_regs = ARRAY_SIZE(mode_640_480_regs),
|
||||
.regs = mode_640_480_regs,
|
||||
},
|
||||
- .binning = true,
|
||||
- /*
|
||||
- * This mode uses a special 2x2 binning that doubles the
|
||||
- * internal pixel clock rate.
|
||||
- */
|
||||
- .rate_factor = 2,
|
||||
+ .binning = {
|
||||
+ [BINNING_IDX_8_BIT] = BINNING_ANALOG_2x2,
|
||||
+ [BINNING_IDX_10_BIT] = BINNING_ANALOG_2x2,
|
||||
+ },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -652,12 +665,51 @@ static int imx219_open(struct v4l2_subde
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int imx219_resolve_binning(struct imx219 *imx219,
|
||||
+ enum binning_mode *binning)
|
||||
+{
|
||||
+ switch (imx219->fmt.code) {
|
||||
+ case MEDIA_BUS_FMT_SRGGB8_1X8:
|
||||
+ case MEDIA_BUS_FMT_SGRBG8_1X8:
|
||||
+ case MEDIA_BUS_FMT_SGBRG8_1X8:
|
||||
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
|
||||
+ *binning = imx219->mode->binning[BINNING_IDX_8_BIT];
|
||||
+ return 0;
|
||||
+
|
||||
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
|
||||
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
|
||||
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
|
||||
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
|
||||
+ *binning = imx219->mode->binning[BINNING_IDX_10_BIT];
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int imx219_get_rate_factor(struct imx219 *imx219)
|
||||
+{
|
||||
+ enum binning_mode binning = BINNING_NONE;
|
||||
+ int ret = imx219_resolve_binning(imx219, &binning);
|
||||
+
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ switch (binning) {
|
||||
+ case BINNING_NONE:
|
||||
+ case BINNING_DIGITAL_2x2:
|
||||
+ return 1;
|
||||
+ case BINNING_ANALOG_2x2:
|
||||
+ return 2;
|
||||
+ }
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct imx219 *imx219 =
|
||||
container_of(ctrl->handler, struct imx219, ctrl_handler);
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
|
||||
int ret;
|
||||
+ int rate_factor;
|
||||
|
||||
if (ctrl->id == V4L2_CID_VBLANK) {
|
||||
int exposure_max, exposure_def;
|
||||
@@ -679,6 +731,10 @@ static int imx219_set_ctrl(struct v4l2_c
|
||||
if (pm_runtime_get_if_in_use(&client->dev) == 0)
|
||||
return 0;
|
||||
|
||||
+ rate_factor = imx219_get_rate_factor(imx219);
|
||||
+ if (rate_factor < 0)
|
||||
+ return rate_factor;
|
||||
+
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_ANALOGUE_GAIN:
|
||||
ret = imx219_write_reg(imx219, IMX219_REG_ANALOG_GAIN,
|
||||
@@ -687,7 +743,7 @@ static int imx219_set_ctrl(struct v4l2_c
|
||||
case V4L2_CID_EXPOSURE:
|
||||
ret = imx219_write_reg(imx219, IMX219_REG_EXPOSURE,
|
||||
IMX219_REG_VALUE_16BIT,
|
||||
- ctrl->val / imx219->mode->rate_factor);
|
||||
+ ctrl->val / rate_factor);
|
||||
break;
|
||||
case V4L2_CID_DIGITAL_GAIN:
|
||||
ret = imx219_write_reg(imx219, IMX219_REG_DIGITAL_GAIN,
|
||||
@@ -708,7 +764,7 @@ static int imx219_set_ctrl(struct v4l2_c
|
||||
ret = imx219_write_reg(imx219, IMX219_REG_VTS,
|
||||
IMX219_REG_VALUE_16BIT,
|
||||
(imx219->mode->height + ctrl->val) /
|
||||
- imx219->mode->rate_factor);
|
||||
+ rate_factor);
|
||||
break;
|
||||
case V4L2_CID_HBLANK:
|
||||
ret = imx219_write_reg(imx219, IMX219_REG_HTS,
|
||||
@@ -890,7 +946,7 @@ static int imx219_set_pad_format(struct
|
||||
struct imx219 *imx219 = to_imx219(sd);
|
||||
const struct imx219_mode *mode;
|
||||
struct v4l2_mbus_framefmt *framefmt;
|
||||
- int exposure_max, exposure_def, hblank, pixel_rate;
|
||||
+ int exposure_max, exposure_def, hblank, pixel_rate, rate_factor;
|
||||
unsigned int i;
|
||||
|
||||
if (fmt->pad >= NUM_PADS)
|
||||
@@ -924,6 +980,9 @@ static int imx219_set_pad_format(struct
|
||||
|
||||
imx219->fmt = fmt->format;
|
||||
imx219->mode = mode;
|
||||
+ rate_factor = imx219_get_rate_factor(imx219);
|
||||
+ if (rate_factor < 0)
|
||||
+ return rate_factor;
|
||||
/* Update limits and set FPS to default */
|
||||
__v4l2_ctrl_modify_range(imx219->vblank,
|
||||
IMX219_VBLANK_MIN,
|
||||
@@ -957,8 +1016,7 @@ static int imx219_set_pad_format(struct
|
||||
__v4l2_ctrl_s_ctrl(imx219->hblank, hblank);
|
||||
|
||||
/* Scale the pixel rate based on the mode specific factor */
|
||||
- pixel_rate =
|
||||
- IMX219_PIXEL_RATE * imx219->mode->rate_factor;
|
||||
+ pixel_rate = IMX219_PIXEL_RATE * rate_factor;
|
||||
__v4l2_ctrl_modify_range(imx219->pixel_rate, pixel_rate,
|
||||
pixel_rate, 1, pixel_rate);
|
||||
}
|
||||
@@ -1001,30 +1059,25 @@ static int imx219_set_framefmt(struct im
|
||||
|
||||
static int imx219_set_binning(struct imx219 *imx219)
|
||||
{
|
||||
- if (!imx219->mode->binning) {
|
||||
+ enum binning_mode binning = BINNING_NONE;
|
||||
+ int ret = imx219_resolve_binning(imx219, &binning);
|
||||
+
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ switch (binning) {
|
||||
+ case BINNING_NONE:
|
||||
return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE,
|
||||
IMX219_REG_VALUE_16BIT,
|
||||
IMX219_BINNING_NONE);
|
||||
- }
|
||||
-
|
||||
- switch (imx219->fmt.code) {
|
||||
- case MEDIA_BUS_FMT_SRGGB8_1X8:
|
||||
- case MEDIA_BUS_FMT_SGRBG8_1X8:
|
||||
- case MEDIA_BUS_FMT_SGBRG8_1X8:
|
||||
- case MEDIA_BUS_FMT_SBGGR8_1X8:
|
||||
+ case BINNING_DIGITAL_2x2:
|
||||
return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE,
|
||||
IMX219_REG_VALUE_16BIT,
|
||||
- IMX219_BINNING_2X2_ANALOG);
|
||||
-
|
||||
- case MEDIA_BUS_FMT_SRGGB10_1X10:
|
||||
- case MEDIA_BUS_FMT_SGRBG10_1X10:
|
||||
- case MEDIA_BUS_FMT_SGBRG10_1X10:
|
||||
- case MEDIA_BUS_FMT_SBGGR10_1X10:
|
||||
+ IMX219_BINNING_2X2);
|
||||
+ case BINNING_ANALOG_2x2:
|
||||
return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE,
|
||||
IMX219_REG_VALUE_16BIT,
|
||||
- IMX219_BINNING_2X2);
|
||||
+ IMX219_BINNING_2X2_ANALOG);
|
||||
}
|
||||
-
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1342,7 +1395,7 @@ static int imx219_init_controls(struct i
|
||||
struct v4l2_ctrl_handler *ctrl_hdlr;
|
||||
unsigned int height = imx219->mode->height;
|
||||
struct v4l2_fwnode_device_properties props;
|
||||
- int exposure_max, exposure_def, hblank, pixel_rate;
|
||||
+ int exposure_max, exposure_def, hblank, pixel_rate, rate_factor;
|
||||
int i, ret;
|
||||
|
||||
ctrl_hdlr = &imx219->ctrl_handler;
|
||||
@@ -1353,8 +1406,12 @@ static int imx219_init_controls(struct i
|
||||
mutex_init(&imx219->mutex);
|
||||
ctrl_hdlr->lock = &imx219->mutex;
|
||||
|
||||
+ rate_factor = imx219_get_rate_factor(imx219);
|
||||
+ if (rate_factor < 0)
|
||||
+ return rate_factor;
|
||||
+
|
||||
/* By default, PIXEL_RATE is read only */
|
||||
- pixel_rate = IMX219_PIXEL_RATE * imx219->mode->rate_factor;
|
||||
+ pixel_rate = IMX219_PIXEL_RATE * rate_factor;
|
||||
imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
|
||||
V4L2_CID_PIXEL_RATE,
|
||||
pixel_rate, pixel_rate,
|
||||
@@ -1576,6 +1633,9 @@ static int imx219_probe(struct i2c_clien
|
||||
goto error_power_off;
|
||||
usleep_range(100, 110);
|
||||
|
||||
+ /* Initialize default format */
|
||||
+ imx219_set_default_format(imx219);
|
||||
+
|
||||
ret = imx219_init_controls(imx219);
|
||||
if (ret)
|
||||
goto error_power_off;
|
||||
@@ -1590,9 +1650,6 @@ static int imx219_probe(struct i2c_clien
|
||||
imx219->pad[IMAGE_PAD].flags = MEDIA_PAD_FL_SOURCE;
|
||||
imx219->pad[METADATA_PAD].flags = MEDIA_PAD_FL_SOURCE;
|
||||
|
||||
- /* Initialize default format */
|
||||
- imx219_set_default_format(imx219);
|
||||
-
|
||||
ret = media_entity_pads_init(&imx219->sd.entity, NUM_PADS, imx219->pad);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to init entity pads: %d\n", ret);
|
28
target/linux/bcm27xx/patches-6.1/950-0791-serial-sc16is7xx-Read-modem-line-state-at-startup.patch
Normal file
28
target/linux/bcm27xx/patches-6.1/950-0791-serial-sc16is7xx-Read-modem-line-state-at-startup.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 52039b6ffb6e78c2f77319b167dceab9aa51d13f Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Tue, 13 Jun 2023 16:12:54 +0100
|
||||
Subject: [PATCH] serial: sc16is7xx: Read modem line state at startup
|
||||
|
||||
This patch sets the driver modem line state to the actual line state
|
||||
at driver startup.
|
||||
|
||||
See: https://github.com/raspberrypi/linux/issues/5501
|
||||
|
||||
Signed-off-by: Earl Schmidt <schmidt.earl.f@gmail.com>
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/tty/serial/sc16is7xx.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/drivers/tty/serial/sc16is7xx.c
|
||||
+++ b/drivers/tty/serial/sc16is7xx.c
|
||||
@@ -1221,6 +1221,9 @@ static int sc16is7xx_startup(struct uart
|
||||
SC16IS7XX_IER_MSI_BIT;
|
||||
sc16is7xx_port_write(port, SC16IS7XX_IER_REG, val);
|
||||
|
||||
+ /* Initialize the Modem Control signals to current status */
|
||||
+ one->old_mctrl = sc16is7xx_get_hwmctrl(port);
|
||||
+
|
||||
/* Enable modem status polling */
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
sc16is7xx_enable_ms(port);
|
79
target/linux/bcm27xx/patches-6.1/950-0792-drivers-media-bcm2835_unicam-Improve-frame-sequence-.patch
Normal file
79
target/linux/bcm27xx/patches-6.1/950-0792-drivers-media-bcm2835_unicam-Improve-frame-sequence-.patch
Normal file
@ -0,0 +1,79 @@
|
||||
From 6ef818eed60db70e9caf6bdf74cc1f9943994226 Mon Sep 17 00:00:00 2001
|
||||
From: Naushir Patuck <naush@raspberrypi.com>
|
||||
Date: Fri, 16 Jun 2023 16:24:19 +0100
|
||||
Subject: [PATCH] drivers: media: bcm2835_unicam: Improve frame sequence count
|
||||
handling
|
||||
|
||||
Ensure that the frame sequence counter is incremented only if a previous
|
||||
frame start interrupt has occurred, or a frame start + frame end has
|
||||
occurred simultaneously.
|
||||
|
||||
This corresponds the sequence number with the actual number of frames
|
||||
produced by the sensor, not the number of frame buffers dequeued back
|
||||
to userland.
|
||||
|
||||
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
|
||||
---
|
||||
.../media/platform/bcm2835/bcm2835-unicam.c | 19 ++++++++++++++++++-
|
||||
1 file changed, 18 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
|
||||
+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
|
||||
@@ -522,6 +522,7 @@ struct unicam_device {
|
||||
/* subdevice async Notifier */
|
||||
struct v4l2_async_notifier notifier;
|
||||
unsigned int sequence;
|
||||
+ bool frame_started;
|
||||
|
||||
/* ptr to sub device */
|
||||
struct v4l2_subdev *sensor;
|
||||
@@ -914,6 +915,8 @@ static irqreturn_t unicam_isr(int irq, v
|
||||
* buffer forever.
|
||||
*/
|
||||
if (fe) {
|
||||
+ bool inc_seq = unicam->frame_started;
|
||||
+
|
||||
/*
|
||||
* Ensure we have swapped buffers already as we can't
|
||||
* stop the peripheral. If no buffer is available, use a
|
||||
@@ -949,11 +952,23 @@ static irqreturn_t unicam_isr(int irq, v
|
||||
unicam_process_buffer_complete(node, sequence);
|
||||
node->cur_frm = node->next_frm;
|
||||
node->next_frm = NULL;
|
||||
+ inc_seq = true;
|
||||
} else {
|
||||
node->cur_frm = node->next_frm;
|
||||
}
|
||||
}
|
||||
- unicam->sequence++;
|
||||
+
|
||||
+ /*
|
||||
+ * Increment the sequence number conditionally on either a FS
|
||||
+ * having already occurred, or in the FE + FS condition as
|
||||
+ * caught in the FE handler above. This ensures the sequence
|
||||
+ * number corresponds to the frames generated by the sensor, not
|
||||
+ * the frames dequeued to userland.
|
||||
+ */
|
||||
+ if (inc_seq) {
|
||||
+ unicam->sequence++;
|
||||
+ unicam->frame_started = false;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (ista & UNICAM_FSI) {
|
||||
@@ -996,6 +1011,7 @@ static irqreturn_t unicam_isr(int irq, v
|
||||
}
|
||||
|
||||
unicam_queue_event_sof(unicam);
|
||||
+ unicam->frame_started = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2600,6 +2616,7 @@ static int unicam_start_streaming(struct
|
||||
vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
|
||||
}
|
||||
|
||||
+ dev->frame_started = false;
|
||||
unicam_start_rx(dev, buffer_addr);
|
||||
|
||||
ret = v4l2_subdev_call(dev->sensor, video, s_stream, 1);
|
41
target/linux/bcm27xx/patches-6.1/950-0793-dtoverlays-Fix-pitft-28-35-overlays-for-6.1-driver-c.patch
Normal file
41
target/linux/bcm27xx/patches-6.1/950-0793-dtoverlays-Fix-pitft-28-35-overlays-for-6.1-driver-c.patch
Normal file
@ -0,0 +1,41 @@
|
||||
From bd8e59b0456870997fb917bcd3b3b696e78d4ac2 Mon Sep 17 00:00:00 2001
|
||||
From: 6by9 <6by9@users.noreply.github.com>
|
||||
Date: Mon, 19 Jun 2023 16:02:36 +0100
|
||||
Subject: [PATCH] dtoverlays: Fix pitft[28|35] overlays for 6.1 driver change.
|
||||
(#5508)
|
||||
|
||||
The overlays configured both irq-gpio and an interrupts/
|
||||
interrupt-parent configuration for the stmpe MFD device.
|
||||
|
||||
irq-gpio was reworked in 6.1 and has issues with the configuration
|
||||
as provided. Removing it and using the interrupts/interrupt-parent
|
||||
configuration works fine, so do that.
|
||||
|
||||
See: https://forums.raspberrypi.com/viewtopic.php?t=351394
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts | 1 -
|
||||
arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts | 1 -
|
||||
2 files changed, 2 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/pitft28-resistive-overlay.dts
|
||||
@@ -68,7 +68,6 @@
|
||||
reg = <1>;
|
||||
|
||||
spi-max-frequency = <500000>;
|
||||
- irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */
|
||||
interrupts = <24 2>; /* high-to-low edge triggered */
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupt-controller;
|
||||
--- a/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/pitft35-resistive-overlay.dts
|
||||
@@ -68,7 +68,6 @@
|
||||
reg = <1>;
|
||||
|
||||
spi-max-frequency = <500000>;
|
||||
- irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */
|
||||
interrupts = <24 2>; /* high-to-low edge triggered */
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupt-controller;
|
23
target/linux/bcm27xx/patches-6.1/950-0795-driver-media-i2c-imx477-Re-enable-temperature-sensor.patch
Normal file
23
target/linux/bcm27xx/patches-6.1/950-0795-driver-media-i2c-imx477-Re-enable-temperature-sensor.patch
Normal file
@ -0,0 +1,23 @@
|
||||
From 713a7ef9d73fca0f7fed122cb854d930b7a6ba5a Mon Sep 17 00:00:00 2001
|
||||
From: Naushir Patuck <naush@raspberrypi.com>
|
||||
Date: Wed, 21 Jun 2023 08:45:02 +0100
|
||||
Subject: [PATCH] driver: media: i2c: imx477: Re-enable temperature sensor
|
||||
|
||||
The temperature sensor enable register write got lost at some point.
|
||||
Re-enable it.
|
||||
|
||||
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
|
||||
---
|
||||
drivers/media/i2c/imx477.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/media/i2c/imx477.c
|
||||
+++ b/drivers/media/i2c/imx477.c
|
||||
@@ -167,6 +167,7 @@ struct imx477_mode {
|
||||
static const struct imx477_reg mode_common_regs[] = {
|
||||
{0x0136, 0x18},
|
||||
{0x0137, 0x00},
|
||||
+ {0x0138, 0x01},
|
||||
{0xe000, 0x00},
|
||||
{0xe07a, 0x01},
|
||||
{0x0808, 0x02},
|
25
target/linux/bcm27xx/patches-6.1/950-0796-overlays-allo-katana-dac-audio-Reduce-I2C-clock.patch
Normal file
25
target/linux/bcm27xx/patches-6.1/950-0796-overlays-allo-katana-dac-audio-Reduce-I2C-clock.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From d4c3133378b377ee519ea50247339cd61221fc47 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Wed, 21 Jun 2023 09:20:36 +0100
|
||||
Subject: [PATCH] overlays: allo-katana-dac-audio: Reduce I2C clock
|
||||
|
||||
Higher speeds have been shown to cause data corruption on a Pi 4,
|
||||
possibly due to clock-stretching.
|
||||
|
||||
See: https://github.com/raspberrypi/linux/issues/5511
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts
|
||||
@@ -30,6 +30,7 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
+ clock-frequency = <50000>;
|
||||
|
||||
allo-katana-codec@30 {
|
||||
#sound-dai-cells = <0>;
|
308
target/linux/bcm27xx/patches-6.1/950-0797-overlays-jedec-spi-nor-Add-speed-parameter.patch
Normal file
308
target/linux/bcm27xx/patches-6.1/950-0797-overlays-jedec-spi-nor-Add-speed-parameter.patch
Normal file
@ -0,0 +1,308 @@
|
||||
From 76c457e7e2920342637b1955fbaadf2aae282f05 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Fri, 23 Jun 2023 09:48:59 +0100
|
||||
Subject: [PATCH] overlays: jedec-spi-nor: Add speed parameter
|
||||
|
||||
Add a speed parameter to the jedec-spi-nor overlay to allow much
|
||||
faster accesses, taking the opportunity to simplify the internals.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/README | 8 +-
|
||||
.../dts/overlays/jedec-spi-nor-overlay.dts | 245 +++---------------
|
||||
2 files changed, 41 insertions(+), 212 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/README
|
||||
+++ b/arch/arm/boot/dts/overlays/README
|
||||
@@ -2557,9 +2557,11 @@ Name: jedec-spi-nor
|
||||
Info: Adds support for JEDEC-compliant SPI NOR flash devices. (Note: The
|
||||
"jedec,spi-nor" kernel driver was formerly known as "m25p80".)
|
||||
Load: dtoverlay=jedec-spi-nor,<param>=<val>
|
||||
-Params: flash-spi<n>-<m> Enables flash device on SPI<n>, CS#<m>.
|
||||
- flash-fastr-spi<n>-<m> Enables flash device with fast read capability
|
||||
- on SPI<n>, CS#<m>.
|
||||
+Params: spi<n>-<m> Enable flash device on SPI<n>, CS#<m>
|
||||
+ fastr Add fast read capability to the flash device
|
||||
+ speed Maximum SPI frequency (Hz)
|
||||
+ flash-spi<n>-<m> Same as spi<n>-<m> (deprecated)
|
||||
+ flash-fastr-spi<n>-<m> Same as spi<n>->m>,fastr (deprecated)
|
||||
|
||||
|
||||
Name: justboom-both
|
||||
--- a/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/jedec-spi-nor-overlay.dts
|
||||
@@ -3,6 +3,7 @@
|
||||
// dtparams:
|
||||
// flash-spi<n>-<m> - Enables flash device on SPI<n>, CS#<m>.
|
||||
// flash-fastr-spi<n>-<m> - Enables flash device with fast read capability on SPI<n>, CS#<m>.
|
||||
+// speed - Set the SPI clock speed in Hz
|
||||
//
|
||||
// If devices are present on SPI1 or SPI2, those interfaces must be enabled with one of the spi1-1/2/3cs and/or spi2-1/2/3cs overlays.
|
||||
//
|
||||
@@ -79,50 +80,23 @@
|
||||
};
|
||||
};
|
||||
|
||||
- // enable flash on spi0.0
|
||||
+ // Enable fast read for device
|
||||
+ // Use default active low interrupt signalling.
|
||||
fragment@8 {
|
||||
- target = <&spi0>;
|
||||
+ target = <&spi_nor>;
|
||||
__dormant__ {
|
||||
- status = "okay";
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
- spi_nor_00: spi_nor@0 {
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <1>;
|
||||
- compatible = "jedec,spi-nor";
|
||||
- reg = <0>;
|
||||
- spi-max-frequency = <500000>;
|
||||
- };
|
||||
+ m25p,fast-read;
|
||||
};
|
||||
};
|
||||
|
||||
- // enable flash on spi0.1
|
||||
- fragment@9 {
|
||||
+ payload: fragment@100 {
|
||||
target = <&spi0>;
|
||||
- __dormant__ {
|
||||
+ __overlay__ {
|
||||
status = "okay";
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
- spi_nor_01: spi_nor@1 {
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <1>;
|
||||
- compatible = "jedec,spi-nor";
|
||||
- reg = <1>;
|
||||
- spi-max-frequency = <500000>;
|
||||
- };
|
||||
- };
|
||||
- };
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
|
||||
- // enable flash on spi1.0
|
||||
- fragment@10 {
|
||||
- target = <&spi1>;
|
||||
- __dormant__ {
|
||||
- status = "okay";
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
- spi_nor_10: spi_nor@0 {
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <1>;
|
||||
+ spi_nor: spi_nor@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <500000>;
|
||||
@@ -130,180 +104,33 @@
|
||||
};
|
||||
};
|
||||
|
||||
- // enable flash on spi1.1
|
||||
- fragment@11 {
|
||||
- target = <&spi1>;
|
||||
- __dormant__ {
|
||||
- status = "okay";
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
- spi_nor_11: spi_nor@1 {
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <1>;
|
||||
- compatible = "jedec,spi-nor";
|
||||
- reg = <1>;
|
||||
- spi-max-frequency = <500000>;
|
||||
- };
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // enable flash on spi1.2
|
||||
- fragment@12 {
|
||||
- target = <&spi1>;
|
||||
- __dormant__ {
|
||||
- status = "okay";
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
- spi_nor_12: spi_nor@2 {
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <1>;
|
||||
- compatible = "jedec,spi-nor";
|
||||
- reg = <2>;
|
||||
- spi-max-frequency = <500000>;
|
||||
- };
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // enable flash on spi2.0
|
||||
- fragment@13 {
|
||||
- target = <&spi2>;
|
||||
- __dormant__ {
|
||||
- status = "okay";
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
- spi_nor_20: spi_nor@0 {
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <1>;
|
||||
- compatible = "jedec,spi-nor";
|
||||
- reg = <0>;
|
||||
- spi-max-frequency = <500000>;
|
||||
- };
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // enable flash on spi2.1
|
||||
- fragment@14 {
|
||||
- target = <&spi2>;
|
||||
- __dormant__ {
|
||||
- status = "okay";
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
- spi_nor_21: spi_nor@1 {
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <1>;
|
||||
- compatible = "jedec,spi-nor";
|
||||
- reg = <1>;
|
||||
- spi-max-frequency = <500000>;
|
||||
- };
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // enable flash on spi2.2
|
||||
- fragment@15 {
|
||||
- target = <&spi2>;
|
||||
- __dormant__ {
|
||||
- status = "okay";
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
- spi_nor_22: spi_nor@2 {
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <1>;
|
||||
- compatible = "jedec,spi-nor";
|
||||
- reg = <2>;
|
||||
- spi-max-frequency = <500000>;
|
||||
- };
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // Enable fast read for device on spi0.0.
|
||||
- // Use default active low interrupt signalling.
|
||||
- fragment@16 {
|
||||
- target = <&spi_nor_00>;
|
||||
- __dormant__ {
|
||||
- m25p,fast-read;
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // Enable fast read for device on spi0.1.
|
||||
- // Use default active low interrupt signalling.
|
||||
- fragment@17 {
|
||||
- target = <&spi_nor_01>;
|
||||
- __dormant__ {
|
||||
- m25p,fast-read;
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // Enable fast read for device on spi1.0.
|
||||
- // Use default active low interrupt signalling.
|
||||
- fragment@18 {
|
||||
- target = <&spi_nor_10>;
|
||||
- __dormant__ {
|
||||
- m25p,fast-read;
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // Enable fast read for device on spi1.1.
|
||||
- // Use default active low interrupt signalling.
|
||||
- fragment@19 {
|
||||
- target = <&spi_nor_11>;
|
||||
- __dormant__ {
|
||||
- m25p,fast-read;
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // Enable fast read for device on spi1.2.
|
||||
- // Use default active low interrupt signalling.
|
||||
- fragment@20 {
|
||||
- target = <&spi_nor_12>;
|
||||
- __dormant__ {
|
||||
- m25p,fast-read;
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // Enable fast read for device on spi2.0.
|
||||
- // Use default active low interrupt signalling.
|
||||
- fragment@21 {
|
||||
- target = <&spi_nor_20>;
|
||||
- __dormant__ {
|
||||
- m25p,fast-read;
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // Enable fast read for device on spi2.1.
|
||||
- // Use default active low interrupt signalling.
|
||||
- fragment@22 {
|
||||
- target = <&spi_nor_21>;
|
||||
- __dormant__ {
|
||||
- m25p,fast-read;
|
||||
- };
|
||||
- };
|
||||
-
|
||||
- // Enable fast read for device on spi2.2.
|
||||
- // Use default active low interrupt signalling.
|
||||
- fragment@23 {
|
||||
- target = <&spi_nor_22>;
|
||||
- __dormant__ {
|
||||
- m25p,fast-read;
|
||||
- };
|
||||
- };
|
||||
-
|
||||
__overrides__ {
|
||||
- flash-spi0-0 = <0>,"+0+8";
|
||||
- flash-spi0-1 = <0>,"+1+9";
|
||||
- flash-spi1-0 = <0>,"+2+10";
|
||||
- flash-spi1-1 = <0>,"+3+11";
|
||||
- flash-spi1-2 = <0>,"+4+12";
|
||||
- flash-spi2-0 = <0>,"+5+13";
|
||||
- flash-spi2-1 = <0>,"+6+14";
|
||||
- flash-spi2-2 = <0>,"+7+15";
|
||||
- flash-fastr-spi0-0 = <0>,"+0+8+16";
|
||||
- flash-fastr-spi0-1 = <0>,"+1+9+17";
|
||||
- flash-fastr-spi1-0 = <0>,"+2+10+18";
|
||||
- flash-fastr-spi1-1 = <0>,"+3+11+19";
|
||||
- flash-fastr-spi1-2 = <0>,"+4+12+20";
|
||||
- flash-fastr-spi2-0 = <0>,"+5+13+21";
|
||||
- flash-fastr-spi2-1 = <0>,"+6+14+22";
|
||||
- flash-fastr-spi2-2 = <0>,"+7+15+23";
|
||||
+ spi0-0 = <0>,"+0", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=0";
|
||||
+ spi0-1 = <0>,"+1", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=1";
|
||||
+ spi1-0 = <0>,"+2", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=0";
|
||||
+ spi1-1 = <0>,"+3", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=1";
|
||||
+ spi1-2 = <0>,"+4", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=2";
|
||||
+ spi2-0 = <0>,"+5", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=0";
|
||||
+ spi2-1 = <0>,"+6", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=1";
|
||||
+ spi2-2 = <0>,"+7", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=2";
|
||||
+ flash-spi0-0 = <0>,"+0", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=0";
|
||||
+ flash-spi0-1 = <0>,"+1", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=1";
|
||||
+ flash-spi1-0 = <0>,"+2", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=0";
|
||||
+ flash-spi1-1 = <0>,"+3", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=1";
|
||||
+ flash-spi1-2 = <0>,"+4", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=2";
|
||||
+ flash-spi2-0 = <0>,"+5", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=0";
|
||||
+ flash-spi2-1 = <0>,"+6", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=1";
|
||||
+ flash-spi2-2 = <0>,"+7", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=2";
|
||||
+ flash-fastr-spi0-0 = <0>,"+0+8", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=0";
|
||||
+ flash-fastr-spi0-1 = <0>,"+1+8", <&payload>,"target:0=",<&spi0>, <&spi_nor>,"reg:0=1";
|
||||
+ flash-fastr-spi1-0 = <0>,"+2+8", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=0";
|
||||
+ flash-fastr-spi1-1 = <0>,"+3+8", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=1";
|
||||
+ flash-fastr-spi1-2 = <0>,"+4+8", <&payload>,"target:0=",<&spi1>, <&spi_nor>,"reg:0=2";
|
||||
+ flash-fastr-spi2-0 = <0>,"+5+8", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=0";
|
||||
+ flash-fastr-spi2-1 = <0>,"+6+8", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=1";
|
||||
+ flash-fastr-spi2-2 = <0>,"+7+8", <&payload>,"target:0=",<&spi2>, <&spi_nor>,"reg:0=2";
|
||||
+ fastr = <0>,"+8";
|
||||
+ speed = <&spi_nor>, "spi-max-frequency:0";
|
||||
};
|
||||
};
|
||||
|
137
target/linux/bcm27xx/patches-6.1/950-0798-ALSA-pcm-fix-ELD-constraints-for-E-AC3-DTS-HD-and-ML.patch
Normal file
137
target/linux/bcm27xx/patches-6.1/950-0798-ALSA-pcm-fix-ELD-constraints-for-E-AC3-DTS-HD-and-ML.patch
Normal file
@ -0,0 +1,137 @@
|
||||
From e866f9fc7c6dd6af1e74ce6fa50db9ba21acae5e Mon Sep 17 00:00:00 2001
|
||||
From: Matthias Reichl <hias@horus.com>
|
||||
Date: Sat, 24 Jun 2023 18:52:16 +0200
|
||||
Subject: [PATCH] ALSA: pcm: fix ELD constraints for (E)AC3, DTS(-HD) and MLP
|
||||
formats
|
||||
|
||||
commit 04b49b90caeed0b5544ff616d654900d27d403b6 upstream.
|
||||
|
||||
The SADs of compressed formats contain the channel and sample rate
|
||||
info of the audio data inside the compressed stream, but when
|
||||
building constraints we must use the rates and channels used to
|
||||
transport the compressed streams.
|
||||
|
||||
eg 48kHz 6ch EAC3 needs to be transmitted as a 2ch 192kHz stream.
|
||||
|
||||
This patch fixes the constraints for the common AC3 and DTS formats,
|
||||
the constraints for the less common MPEG, DSD etc formats are copied
|
||||
directly from the info in the SADs as before as I don't have the specs
|
||||
and equipment to test those.
|
||||
|
||||
Signed-off-by: Matthias Reichl <hias@horus.com>
|
||||
Link: https://lore.kernel.org/r/20230624165216.5719-1-hias@horus.com
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
sound/core/pcm_drm_eld.c | 73 ++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 70 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/sound/core/pcm_drm_eld.c
|
||||
+++ b/sound/core/pcm_drm_eld.c
|
||||
@@ -2,11 +2,25 @@
|
||||
/*
|
||||
* PCM DRM helpers
|
||||
*/
|
||||
+#include <linux/bitfield.h>
|
||||
#include <linux/export.h>
|
||||
+#include <linux/hdmi.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_drm_eld.h>
|
||||
|
||||
+#define SAD0_CHANNELS_MASK GENMASK(2, 0) /* max number of channels - 1 */
|
||||
+#define SAD0_FORMAT_MASK GENMASK(6, 3) /* audio format */
|
||||
+
|
||||
+#define SAD1_RATE_MASK GENMASK(6, 0) /* bitfield of supported rates */
|
||||
+#define SAD1_RATE_32000_MASK BIT(0)
|
||||
+#define SAD1_RATE_44100_MASK BIT(1)
|
||||
+#define SAD1_RATE_48000_MASK BIT(2)
|
||||
+#define SAD1_RATE_88200_MASK BIT(3)
|
||||
+#define SAD1_RATE_96000_MASK BIT(4)
|
||||
+#define SAD1_RATE_176400_MASK BIT(5)
|
||||
+#define SAD1_RATE_192000_MASK BIT(6)
|
||||
+
|
||||
static const unsigned int eld_rates[] = {
|
||||
32000,
|
||||
44100,
|
||||
@@ -17,9 +31,62 @@ static const unsigned int eld_rates[] =
|
||||
192000,
|
||||
};
|
||||
|
||||
+static unsigned int map_rate_families(const u8 *sad,
|
||||
+ unsigned int mask_32000,
|
||||
+ unsigned int mask_44100,
|
||||
+ unsigned int mask_48000)
|
||||
+{
|
||||
+ unsigned int rate_mask = 0;
|
||||
+
|
||||
+ if (sad[1] & SAD1_RATE_32000_MASK)
|
||||
+ rate_mask |= mask_32000;
|
||||
+ if (sad[1] & (SAD1_RATE_44100_MASK | SAD1_RATE_88200_MASK | SAD1_RATE_176400_MASK))
|
||||
+ rate_mask |= mask_44100;
|
||||
+ if (sad[1] & (SAD1_RATE_48000_MASK | SAD1_RATE_96000_MASK | SAD1_RATE_192000_MASK))
|
||||
+ rate_mask |= mask_48000;
|
||||
+ return rate_mask;
|
||||
+}
|
||||
+
|
||||
+static unsigned int sad_rate_mask(const u8 *sad)
|
||||
+{
|
||||
+ switch (FIELD_GET(SAD0_FORMAT_MASK, sad[0])) {
|
||||
+ case HDMI_AUDIO_CODING_TYPE_PCM:
|
||||
+ return sad[1] & SAD1_RATE_MASK;
|
||||
+ case HDMI_AUDIO_CODING_TYPE_AC3:
|
||||
+ case HDMI_AUDIO_CODING_TYPE_DTS:
|
||||
+ return map_rate_families(sad,
|
||||
+ SAD1_RATE_32000_MASK,
|
||||
+ SAD1_RATE_44100_MASK,
|
||||
+ SAD1_RATE_48000_MASK);
|
||||
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
|
||||
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
|
||||
+ case HDMI_AUDIO_CODING_TYPE_MLP:
|
||||
+ return map_rate_families(sad,
|
||||
+ 0,
|
||||
+ SAD1_RATE_176400_MASK,
|
||||
+ SAD1_RATE_192000_MASK);
|
||||
+ default:
|
||||
+ /* TODO adjust for other compressed formats as well */
|
||||
+ return sad[1] & SAD1_RATE_MASK;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static unsigned int sad_max_channels(const u8 *sad)
|
||||
{
|
||||
- return 1 + (sad[0] & 7);
|
||||
+ switch (FIELD_GET(SAD0_FORMAT_MASK, sad[0])) {
|
||||
+ case HDMI_AUDIO_CODING_TYPE_PCM:
|
||||
+ return 1 + FIELD_GET(SAD0_CHANNELS_MASK, sad[0]);
|
||||
+ case HDMI_AUDIO_CODING_TYPE_AC3:
|
||||
+ case HDMI_AUDIO_CODING_TYPE_DTS:
|
||||
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
|
||||
+ return 2;
|
||||
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
|
||||
+ case HDMI_AUDIO_CODING_TYPE_MLP:
|
||||
+ return 8;
|
||||
+ default:
|
||||
+ /* TODO adjust for other compressed formats as well */
|
||||
+ return 1 + FIELD_GET(SAD0_CHANNELS_MASK, sad[0]);
|
||||
+ }
|
||||
}
|
||||
|
||||
static int eld_limit_rates(struct snd_pcm_hw_params *params,
|
||||
@@ -42,7 +109,7 @@ static int eld_limit_rates(struct snd_pc
|
||||
* requested number of channels.
|
||||
*/
|
||||
if (c->min <= max_channels)
|
||||
- rate_mask |= sad[1];
|
||||
+ rate_mask |= sad_rate_mask(sad);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +137,7 @@ static int eld_limit_channels(struct snd
|
||||
rate_mask |= BIT(i);
|
||||
|
||||
for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3)
|
||||
- if (rate_mask & sad[1])
|
||||
+ if (rate_mask & sad_rate_mask(sad))
|
||||
t.max = max(t.max, sad_max_channels(sad));
|
||||
}
|
||||
|
86
target/linux/bcm27xx/patches-6.1/950-0799-ASoC-hdmi-codec-fix-channel-info-for-compressed-form.patch
Normal file
86
target/linux/bcm27xx/patches-6.1/950-0799-ASoC-hdmi-codec-fix-channel-info-for-compressed-form.patch
Normal file
@ -0,0 +1,86 @@
|
||||
From 3f388718331b5ce2acd34730448db001759868aa Mon Sep 17 00:00:00 2001
|
||||
From: Matthias Reichl <hias@horus.com>
|
||||
Date: Sat, 24 Jun 2023 18:52:32 +0200
|
||||
Subject: [PATCH] ASoC: hdmi-codec: fix channel info for compressed formats
|
||||
|
||||
commit 4e0871333661d2ec0ed3dc00a945c2160eccae77 upstream.
|
||||
|
||||
According to CTA 861 the channel/speaker allocation info in the
|
||||
audio infoframe only applies to uncompressed (PCM) audio streams.
|
||||
|
||||
The channel count info should indicate the number of channels
|
||||
in the transmitted audio, which usually won't match the number of
|
||||
channels used to transmit the compressed bitstream.
|
||||
|
||||
Some devices (eg some Sony TVs) will refuse to decode compressed
|
||||
audio if these values are not set correctly.
|
||||
|
||||
To fix this we can simply set the channel count to 0 (which means
|
||||
"refer to stream header") and set the channel/speaker allocation to 0
|
||||
as well (which would mean stereo FL/FR for PCM, a safe value all sinks
|
||||
will support) when transmitting compressed audio.
|
||||
|
||||
Signed-off-by: Matthias Reichl <hias@horus.com>
|
||||
Link: https://lore.kernel.org/r/20230624165232.5751-1-hias@horus.com
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
sound/soc/codecs/hdmi-codec.c | 36 +++++++++++++++++++++++------------
|
||||
1 file changed, 24 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/sound/soc/codecs/hdmi-codec.c
|
||||
+++ b/sound/soc/codecs/hdmi-codec.c
|
||||
@@ -484,31 +484,43 @@ static int hdmi_codec_fill_codec_params(
|
||||
struct hdmi_codec_params *hp)
|
||||
{
|
||||
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
|
||||
- int idx;
|
||||
+ int idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
|
||||
+ u8 ca_id = 0;
|
||||
+ bool pcm_audio = !(hcp->iec_status[0] & IEC958_AES0_NONAUDIO);
|
||||
+
|
||||
+ if (pcm_audio) {
|
||||
+ /* Select a channel allocation that matches with ELD and pcm channels */
|
||||
+ idx = hdmi_codec_get_ch_alloc_table_idx(hcp, channels);
|
||||
+
|
||||
+ if (idx < 0) {
|
||||
+ dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
|
||||
+ idx);
|
||||
+ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
|
||||
+ return idx;
|
||||
+ }
|
||||
|
||||
- /* Select a channel allocation that matches with ELD and pcm channels */
|
||||
- idx = hdmi_codec_get_ch_alloc_table_idx(hcp, channels);
|
||||
- if (idx < 0) {
|
||||
- dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
|
||||
- idx);
|
||||
- hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
|
||||
- return idx;
|
||||
+ ca_id = hdmi_codec_channel_alloc[idx].ca_id;
|
||||
}
|
||||
|
||||
memset(hp, 0, sizeof(*hp));
|
||||
|
||||
hdmi_audio_infoframe_init(&hp->cea);
|
||||
- hp->cea.channels = channels;
|
||||
+
|
||||
+ if (pcm_audio)
|
||||
+ hp->cea.channels = channels;
|
||||
+ else
|
||||
+ hp->cea.channels = 0;
|
||||
+
|
||||
hp->cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
|
||||
hp->cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
|
||||
hp->cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
|
||||
- hp->cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id;
|
||||
+ hp->cea.channel_allocation = ca_id;
|
||||
|
||||
hp->sample_width = sample_width;
|
||||
hp->sample_rate = sample_rate;
|
||||
hp->channels = channels;
|
||||
|
||||
- hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id;
|
||||
+ hcp->chmap_idx = idx;
|
||||
|
||||
return 0;
|
||||
}
|
44
target/linux/bcm27xx/patches-6.1/950-0800-media-i2c-arducam_64mp-Modify-the-line-length-of-128.patch
Normal file
44
target/linux/bcm27xx/patches-6.1/950-0800-media-i2c-arducam_64mp-Modify-the-line-length-of-128.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From 9c5a7f04cab6b020389d7c5af155b1ee7f46537d Mon Sep 17 00:00:00 2001
|
||||
From: Lee Jackson <lee.jackson@arducam.com>
|
||||
Date: Thu, 4 May 2023 11:14:04 +0800
|
||||
Subject: [PATCH] media: i2c: arducam_64mp: Modify the line length of 1280x720
|
||||
resolution
|
||||
|
||||
Arducam 64MP has specific requirements for the line length, and if these
|
||||
conditions are not met, the camera will not function properly. Under the
|
||||
previous configuration, once a stream off operation is performed, the
|
||||
camera will not output any data, even if a stream on operation is
|
||||
performed. This prevents us from switching from 1280x720 to another
|
||||
resolution.
|
||||
|
||||
Signed-off-by: Lee Jackson <lee.jackson@arducam.com>
|
||||
---
|
||||
drivers/media/i2c/arducam_64mp.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/media/i2c/arducam_64mp.c
|
||||
+++ b/drivers/media/i2c/arducam_64mp.c
|
||||
@@ -1063,10 +1063,10 @@ static const struct arducam_64mp_reg mod
|
||||
|
||||
/* 720p 120fps mode */
|
||||
static const struct arducam_64mp_reg mode_1280x720_regs[] = {
|
||||
- {0x0342, 0x1d},
|
||||
- {0x0343, 0xc4},
|
||||
- {0x0340, 0x03},
|
||||
- {0x0341, 0xd8},
|
||||
+ {0x0342, 0x1b},
|
||||
+ {0x0343, 0x08},
|
||||
+ {0x0340, 0x04},
|
||||
+ {0x0341, 0x3b},
|
||||
{0x0344, 0x08},
|
||||
{0x0345, 0x10},
|
||||
{0x0346, 0x07},
|
||||
@@ -1209,7 +1209,7 @@ static const struct arducam_64mp_mode su
|
||||
}, {
|
||||
.width = 1280,
|
||||
.height = 720,
|
||||
- .line_length_pix = 0x1dc4,
|
||||
+ .line_length_pix = 0x1b08,
|
||||
.crop = {
|
||||
.left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT + 2064,
|
||||
.top = ARDUCAM_64MP_PIXEL_ARRAY_TOP + 2032,
|
105
target/linux/bcm27xx/patches-6.1/950-0801-media-i2c-arducam_64mp-Add-8000x6000-resolution.patch
Normal file
105
target/linux/bcm27xx/patches-6.1/950-0801-media-i2c-arducam_64mp-Add-8000x6000-resolution.patch
Normal file
@ -0,0 +1,105 @@
|
||||
From 7b3d0124c5cf462d5be0b0d4e558002b74750911 Mon Sep 17 00:00:00 2001
|
||||
From: Lee Jackson <lee.jackson@arducam.com>
|
||||
Date: Fri, 5 May 2023 14:36:15 +0800
|
||||
Subject: [PATCH] media: i2c: arducam_64mp: Add 8000x6000 resolution
|
||||
|
||||
Added 8000x6000 10-bit (cropped) @ 3fps mode for Arducam 64MP
|
||||
|
||||
Signed-off-by: Lee Jackson <lee.jackson@arducam.com>
|
||||
---
|
||||
drivers/media/i2c/arducam_64mp.c | 77 ++++++++++++++++++++++++++++++++
|
||||
1 file changed, 77 insertions(+)
|
||||
|
||||
--- a/drivers/media/i2c/arducam_64mp.c
|
||||
+++ b/drivers/media/i2c/arducam_64mp.c
|
||||
@@ -849,6 +849,65 @@ static const struct arducam_64mp_reg mod
|
||||
{0x020f, 0x00},
|
||||
};
|
||||
|
||||
+/* 48 mpix 3.0fps */
|
||||
+static const struct arducam_64mp_reg mode_8000x6000_regs[] = {
|
||||
+ {0x0342, 0xb6},
|
||||
+ {0x0343, 0xb2},
|
||||
+ {0x0340, 0x19},
|
||||
+ {0x0341, 0x0e},
|
||||
+ {0x0344, 0x02},
|
||||
+ {0x0345, 0x70},
|
||||
+ {0x0346, 0x01},
|
||||
+ {0x0347, 0xd8},
|
||||
+ {0x0348, 0x21},
|
||||
+ {0x0349, 0xaf},
|
||||
+ {0x034a, 0x19},
|
||||
+ {0x034b, 0x47},
|
||||
+ {0x0900, 0x00},
|
||||
+ {0x0901, 0x11},
|
||||
+ {0x0902, 0x0a},
|
||||
+ {0x30d8, 0x00},
|
||||
+ {0x3200, 0x01},
|
||||
+ {0x3201, 0x01},
|
||||
+ {0x0408, 0x00},
|
||||
+ {0x0409, 0x00},
|
||||
+ {0x040a, 0x00},
|
||||
+ {0x040b, 0x00},
|
||||
+ {0x040c, 0x1f},
|
||||
+ {0x040d, 0x40},
|
||||
+ {0x040e, 0x17},
|
||||
+ {0x040f, 0x70},
|
||||
+ {0x034c, 0x1f},
|
||||
+ {0x034d, 0x40},
|
||||
+ {0x034e, 0x17},
|
||||
+ {0x034f, 0x70},
|
||||
+ {0x30d9, 0x01},
|
||||
+ {0x32d5, 0x01},
|
||||
+ {0x32d6, 0x00},
|
||||
+ {0x401e, 0x00},
|
||||
+ {0x40b8, 0x04},
|
||||
+ {0x40b9, 0x20},
|
||||
+ {0x40bc, 0x02},
|
||||
+ {0x40bd, 0x58},
|
||||
+ {0x40be, 0x02},
|
||||
+ {0x40bf, 0x58},
|
||||
+ {0x41a4, 0x00},
|
||||
+ {0x5a09, 0x01},
|
||||
+ {0x5a17, 0x01},
|
||||
+ {0x5a25, 0x01},
|
||||
+ {0x5a33, 0x01},
|
||||
+ {0x98d7, 0x14},
|
||||
+ {0x98d8, 0x14},
|
||||
+ {0x98d9, 0x00},
|
||||
+ {0x99c4, 0x00},
|
||||
+ {0x0202, 0x03},
|
||||
+ {0x0203, 0xe8},
|
||||
+ {0x0204, 0x00},
|
||||
+ {0x0205, 0x00},
|
||||
+ {0x020e, 0x01},
|
||||
+ {0x020f, 0x00},
|
||||
+};
|
||||
+
|
||||
/* 16 mpix 10fps */
|
||||
static const struct arducam_64mp_reg mode_4624x3472_regs[] = {
|
||||
{0x0342, 0x63},
|
||||
@@ -1135,6 +1194,24 @@ static const struct arducam_64mp_mode su
|
||||
.regs = mode_9152x6944_regs,
|
||||
}
|
||||
}, {
|
||||
+ .width = 8000,
|
||||
+ .height = 6000,
|
||||
+ .line_length_pix = 0xb6b2,
|
||||
+ .crop = {
|
||||
+ .left = ARDUCAM_64MP_PIXEL_ARRAY_LEFT + 624,
|
||||
+ .top = ARDUCAM_64MP_PIXEL_ARRAY_TOP + 472,
|
||||
+ .width = 9248,
|
||||
+ .height = 6944,
|
||||
+ },
|
||||
+ .timeperframe_default = {
|
||||
+ .numerator = 100,
|
||||
+ .denominator = 300
|
||||
+ },
|
||||
+ .reg_list = {
|
||||
+ .num_of_regs = ARRAY_SIZE(mode_8000x6000_regs),
|
||||
+ .regs = mode_8000x6000_regs,
|
||||
+ }
|
||||
+ }, {
|
||||
.width = 4624,
|
||||
.height = 3472,
|
||||
.line_length_pix = 0x6397,
|
163
target/linux/bcm27xx/patches-6.1/950-0802-media-i2c-arducam_64mp-Add-PDAF-support.patch
Normal file
163
target/linux/bcm27xx/patches-6.1/950-0802-media-i2c-arducam_64mp-Add-PDAF-support.patch
Normal file
@ -0,0 +1,163 @@
|
||||
From b9d2d1862aa5b798cecb87a95d970ad34a4aebc0 Mon Sep 17 00:00:00 2001
|
||||
From: Lee Jackson <lee.jackson@arducam.com>
|
||||
Date: Tue, 30 May 2023 15:50:05 +0800
|
||||
Subject: [PATCH] media: i2c: arducam_64mp: Add PDAF support
|
||||
|
||||
Enable PDAF output for all modes, and also need to modify Embedded Line
|
||||
Width to 11560 * 3 (two lines of Embedded Data + one line of PDAF).
|
||||
|
||||
Signed-off-by: Lee Jackson <lee.jackson@arducam.com>
|
||||
---
|
||||
drivers/media/i2c/arducam_64mp.c | 64 ++++++++++++++++++++++++++++++--
|
||||
1 file changed, 61 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/media/i2c/arducam_64mp.c
|
||||
+++ b/drivers/media/i2c/arducam_64mp.c
|
||||
@@ -95,7 +95,7 @@
|
||||
#define ARDUCAM_64MP_TEST_PATTERN_GB_DEFAULT 0
|
||||
|
||||
/* Embedded metadata stream structure */
|
||||
-#define ARDUCAM_64MP_EMBEDDED_LINE_WIDTH 16384
|
||||
+#define ARDUCAM_64MP_EMBEDDED_LINE_WIDTH (11560 * 3)
|
||||
#define ARDUCAM_64MP_NUM_EMBEDDED_LINES 1
|
||||
|
||||
enum pad_types {
|
||||
@@ -144,6 +144,7 @@ struct arducam_64mp_mode {
|
||||
};
|
||||
|
||||
static const struct arducam_64mp_reg mode_common_regs[] = {
|
||||
+ {0x0100, 0x00},
|
||||
{0x0136, 0x18},
|
||||
{0x0137, 0x00},
|
||||
{0x33F0, 0x01},
|
||||
@@ -788,6 +789,7 @@ static const struct arducam_64mp_reg mod
|
||||
{0x3092, 0x01},
|
||||
{0x3093, 0x00},
|
||||
{0x0350, 0x00},
|
||||
+ {0x3419, 0x00},
|
||||
};
|
||||
|
||||
/* 64 mpix 2.7fps */
|
||||
@@ -847,6 +849,14 @@ static const struct arducam_64mp_reg mod
|
||||
{0x0205, 0x00},
|
||||
{0x020e, 0x01},
|
||||
{0x020f, 0x00},
|
||||
+ {0x341a, 0x00},
|
||||
+ {0x341b, 0x00},
|
||||
+ {0x341c, 0x00},
|
||||
+ {0x341d, 0x00},
|
||||
+ {0x341e, 0x02},
|
||||
+ {0x341f, 0x3c},
|
||||
+ {0x3420, 0x02},
|
||||
+ {0x3421, 0x42},
|
||||
};
|
||||
|
||||
/* 48 mpix 3.0fps */
|
||||
@@ -906,6 +916,14 @@ static const struct arducam_64mp_reg mod
|
||||
{0x0205, 0x00},
|
||||
{0x020e, 0x01},
|
||||
{0x020f, 0x00},
|
||||
+ {0x341a, 0x00},
|
||||
+ {0x341b, 0x00},
|
||||
+ {0x341c, 0x00},
|
||||
+ {0x341d, 0x00},
|
||||
+ {0x341e, 0x01},
|
||||
+ {0x341f, 0xf4},
|
||||
+ {0x3420, 0x01},
|
||||
+ {0x3421, 0xf4},
|
||||
};
|
||||
|
||||
/* 16 mpix 10fps */
|
||||
@@ -959,6 +977,14 @@ static const struct arducam_64mp_reg mod
|
||||
{0x98d8, 0x8c},
|
||||
{0x98d9, 0x0a},
|
||||
{0x99c4, 0x16},
|
||||
+ {0x341a, 0x00},
|
||||
+ {0x341b, 0x00},
|
||||
+ {0x341c, 0x00},
|
||||
+ {0x341d, 0x00},
|
||||
+ {0x341e, 0x01},
|
||||
+ {0x341f, 0x21},
|
||||
+ {0x3420, 0x01},
|
||||
+ {0x3421, 0x21},
|
||||
};
|
||||
|
||||
/* 4k 20fps mode */
|
||||
@@ -1012,6 +1038,14 @@ static const struct arducam_64mp_reg mod
|
||||
{0x98d8, 0x8c},
|
||||
{0x98d9, 0x0a},
|
||||
{0x99c4, 0x16},
|
||||
+ {0x341a, 0x00},
|
||||
+ {0x341b, 0x00},
|
||||
+ {0x341c, 0x00},
|
||||
+ {0x341d, 0x00},
|
||||
+ {0x341e, 0x00},
|
||||
+ {0x341f, 0xf0},
|
||||
+ {0x3420, 0x00},
|
||||
+ {0x3421, 0xb4},
|
||||
};
|
||||
|
||||
/* 4x4 binned 30fps mode */
|
||||
@@ -1031,7 +1065,7 @@ static const struct arducam_64mp_reg mod
|
||||
{0x0900, 0x01},
|
||||
{0x0901, 0x44},
|
||||
{0x0902, 0x08},
|
||||
- {0x30d8, 0x00},
|
||||
+ {0x30d8, 0x04},
|
||||
{0x3200, 0x43},
|
||||
{0x3201, 0x43},
|
||||
{0x0408, 0x00},
|
||||
@@ -1046,7 +1080,7 @@ static const struct arducam_64mp_reg mod
|
||||
{0x034d, 0x08},
|
||||
{0x034e, 0x06},
|
||||
{0x034f, 0xc8},
|
||||
- {0x30d9, 0x01},
|
||||
+ {0x30d9, 0x00},
|
||||
{0x32d5, 0x00},
|
||||
{0x32d6, 0x00},
|
||||
{0x401e, 0x00},
|
||||
@@ -1065,6 +1099,14 @@ static const struct arducam_64mp_reg mod
|
||||
{0x98d8, 0x8c},
|
||||
{0x98d9, 0x0a},
|
||||
{0x99c4, 0x16},
|
||||
+ {0x341a, 0x00},
|
||||
+ {0x341b, 0x00},
|
||||
+ {0x341c, 0x00},
|
||||
+ {0x341d, 0x00},
|
||||
+ {0x341e, 0x00},
|
||||
+ {0x341f, 0x90},
|
||||
+ {0x3420, 0x00},
|
||||
+ {0x3421, 0x90},
|
||||
};
|
||||
|
||||
/* 1080p 60fps mode */
|
||||
@@ -1118,6 +1160,14 @@ static const struct arducam_64mp_reg mod
|
||||
{0x98d8, 0x8c},
|
||||
{0x98d9, 0x0a},
|
||||
{0x99c4, 0x16},
|
||||
+ {0x341a, 0x00},
|
||||
+ {0x341b, 0x00},
|
||||
+ {0x341c, 0x00},
|
||||
+ {0x341d, 0x00},
|
||||
+ {0x341e, 0x00},
|
||||
+ {0x341f, 0x78},
|
||||
+ {0x3420, 0x00},
|
||||
+ {0x3421, 0x5a},
|
||||
};
|
||||
|
||||
/* 720p 120fps mode */
|
||||
@@ -1171,6 +1221,14 @@ static const struct arducam_64mp_reg mod
|
||||
{0x98d8, 0x8c},
|
||||
{0x98d9, 0x0a},
|
||||
{0x99c4, 0x16},
|
||||
+ {0x341a, 0x00},
|
||||
+ {0x341b, 0x00},
|
||||
+ {0x341c, 0x00},
|
||||
+ {0x341d, 0x00},
|
||||
+ {0x341e, 0x00},
|
||||
+ {0x341f, 0x50},
|
||||
+ {0x3420, 0x00},
|
||||
+ {0x3421, 0x3c},
|
||||
};
|
||||
|
||||
/* Mode configs */
|
24
target/linux/bcm27xx/patches-6.1/950-0803-overlays-audremap-Document-CM4-40-41-restriction.patch
Normal file
24
target/linux/bcm27xx/patches-6.1/950-0803-overlays-audremap-Document-CM4-40-41-restriction.patch
Normal file
@ -0,0 +1,24 @@
|
||||
From 6f4106f7a7fdcbc03290008713915b4122988c90 Mon Sep 17 00:00:00 2001
|
||||
From: James Hughes <JamesH65@users.noreply.github.com>
|
||||
Date: Wed, 5 Jul 2023 15:43:30 +0100
|
||||
Subject: [PATCH] overlays: audremap: Document CM4 40&41 restriction
|
||||
|
||||
Update audremap information to state pins 40,41 are not available on the CM4.
|
||||
|
||||
Signed-off-by: James Hughes (james.hughes@raspberrypi.com)
|
||||
---
|
||||
arch/arm/boot/dts/overlays/README | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/README
|
||||
+++ b/arch/arm/boot/dts/overlays/README
|
||||
@@ -703,7 +703,8 @@ Params: swap_lr Reverse
|
||||
nothing on BCM2711 (default off)
|
||||
pins_12_13 Select GPIOs 12 & 13 (default)
|
||||
pins_18_19 Select GPIOs 18 & 19
|
||||
- pins_40_41 Select GPIOs 40 & 41
|
||||
+ pins_40_41 Select GPIOs 40 & 41 (not available on CM4, used
|
||||
+ for other purposes)
|
||||
pins_40_45 Select GPIOs 40 & 45 (don't use on BCM2711 - the
|
||||
pins are on different controllers)
|
||||
|
120
target/linux/bcm27xx/patches-6.1/950-0804-fixup-Allow-mac-address-to-be-set-in-smsc95xx.patch
Normal file
120
target/linux/bcm27xx/patches-6.1/950-0804-fixup-Allow-mac-address-to-be-set-in-smsc95xx.patch
Normal file
@ -0,0 +1,120 @@
|
||||
From 1d15e6a34222cc8d8eb1050e7a3e276b0348be41 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Mon, 3 Jul 2023 11:04:56 +0100
|
||||
Subject: [PATCH] fixup! Allow mac address to be set in smsc95xx
|
||||
|
||||
usbnet: smsc95xx: Fix indentation of smsc95xx_is_macaddr_param()
|
||||
|
||||
smsc95xx_is_macaddr_param() is incorrectly indented, it uses 7 spaces
|
||||
instead of tabs. Fix it.
|
||||
|
||||
Fixes: aac7b105788e ("Allow mac address to be set in smsc95xx")
|
||||
Signed-off-by: Philipp Rosenberger <p.rosenberger@kunbus.com>
|
||||
[lukas: fix netif_dbg() indentation as well, wordsmith commit message]
|
||||
Signed-off-by: Lukas Wunner <lukas@wunner.de>
|
||||
|
||||
usbnet: smsc95xx: Simplify MAC address parsing
|
||||
|
||||
Parsing the MAC address provided on the kernel command line can be
|
||||
simplified quite a bit by taking advantage of the kernel's built-in
|
||||
mac_pton() helper.
|
||||
|
||||
Likewise emitting the MAC address can be simplified with the %pM
|
||||
format string conversion.
|
||||
|
||||
Signed-off-by: Lukas Wunner <lukas@wunner.de>
|
||||
|
||||
usbnet: smsc95xx: Fix style issues in smsc95xx_is_macaddr_param()
|
||||
|
||||
It is bad practice to have a function named ..._is_...() which has side
|
||||
effects. So drop the 'is' from the name.
|
||||
|
||||
Per kernel convention return 0 on success and a negative errno on
|
||||
failure.
|
||||
|
||||
Validate the MAC address retrieved from the command line.
|
||||
|
||||
Signed-off-by: Philipp Rosenberger <p.rosenberger@kunbus.com>
|
||||
[lukas: leave 2nd function parameter unchanged, wordsmith commit message]
|
||||
Signed-off-by: Lukas Wunner <lukas@wunner.de>
|
||||
---
|
||||
drivers/net/usb/smsc95xx.c | 61 +++++++++++---------------------------
|
||||
1 file changed, 17 insertions(+), 44 deletions(-)
|
||||
|
||||
--- a/drivers/net/usb/smsc95xx.c
|
||||
+++ b/drivers/net/usb/smsc95xx.c
|
||||
@@ -814,49 +814,18 @@ static int smsc95xx_ioctl(struct net_dev
|
||||
}
|
||||
|
||||
/* Check the macaddr module parameter for a MAC address */
|
||||
-static int smsc95xx_is_macaddr_param(struct usbnet *dev, struct net_device *nd)
|
||||
+static int smsc95xx_macaddr_param(struct usbnet *dev, struct net_device *nd)
|
||||
{
|
||||
- int i, j, got_num, num;
|
||||
- u8 mtbl[ETH_ALEN];
|
||||
+ u8 mtbl[ETH_ALEN];
|
||||
|
||||
- if (macaddr[0] == ':')
|
||||
- return 0;
|
||||
-
|
||||
- i = 0;
|
||||
- j = 0;
|
||||
- num = 0;
|
||||
- got_num = 0;
|
||||
- while (j < ETH_ALEN) {
|
||||
- if (macaddr[i] && macaddr[i] != ':') {
|
||||
- got_num++;
|
||||
- if ('0' <= macaddr[i] && macaddr[i] <= '9')
|
||||
- num = num * 16 + macaddr[i] - '0';
|
||||
- else if ('A' <= macaddr[i] && macaddr[i] <= 'F')
|
||||
- num = num * 16 + 10 + macaddr[i] - 'A';
|
||||
- else if ('a' <= macaddr[i] && macaddr[i] <= 'f')
|
||||
- num = num * 16 + 10 + macaddr[i] - 'a';
|
||||
- else
|
||||
- break;
|
||||
- i++;
|
||||
- } else if (got_num == 2) {
|
||||
- mtbl[j++] = (u8) num;
|
||||
- num = 0;
|
||||
- got_num = 0;
|
||||
- i++;
|
||||
- } else {
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (j == ETH_ALEN) {
|
||||
- netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: "
|
||||
- "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2],
|
||||
- mtbl[3], mtbl[4], mtbl[5]);
|
||||
- dev_addr_mod(nd, 0, mtbl, ETH_ALEN);
|
||||
- return 1;
|
||||
- } else {
|
||||
- return 0;
|
||||
- }
|
||||
+ if (mac_pton(macaddr, mtbl)) {
|
||||
+ netif_dbg(dev, ifup, dev->net,
|
||||
+ "Overriding MAC address with: %pM\n", mtbl);
|
||||
+ dev_addr_mod(nd, 0, mtbl, ETH_ALEN);
|
||||
+ return 0;
|
||||
+ } else {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
}
|
||||
|
||||
static void smsc95xx_init_mac_address(struct usbnet *dev)
|
||||
@@ -883,8 +852,12 @@ static void smsc95xx_init_mac_address(st
|
||||
}
|
||||
|
||||
/* Check module parameters */
|
||||
- if (smsc95xx_is_macaddr_param(dev, dev->net))
|
||||
- return;
|
||||
+ if (smsc95xx_macaddr_param(dev, dev->net) == 0) {
|
||||
+ if (is_valid_ether_addr(dev->net->dev_addr)) {
|
||||
+ netif_dbg(dev, ifup, dev->net, "MAC address read from module parameter\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/* no useful static MAC address found. generate a random one */
|
||||
eth_hw_addr_random(dev->net);
|
1455
target/linux/bcm27xx/patches-6.1/950-0809-cfg80211-ship-debian-certificates-as-hex-files.patch
Normal file
1455
target/linux/bcm27xx/patches-6.1/950-0809-cfg80211-ship-debian-certificates-as-hex-files.patch
Normal file
File diff suppressed because it is too large
Load Diff
329
target/linux/bcm27xx/patches-6.1/950-0810-fixup-Add-support-for-all-the-downstream-rpi-sound-c.patch
Normal file
329
target/linux/bcm27xx/patches-6.1/950-0810-fixup-Add-support-for-all-the-downstream-rpi-sound-c.patch
Normal file
@ -0,0 +1,329 @@
|
||||
From 3ece03b1575b0c3a0989e372aaaa4557ae74dc89 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Thu, 20 Jul 2023 11:28:20 +0100
|
||||
Subject: [PATCH] fixup! Add support for all the downstream rpi sound card
|
||||
drivers
|
||||
|
||||
Replace the Allo Dac clock driver with an extension of the
|
||||
HiFiBerry clock driver that it cloned.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/clk/Makefile | 1 -
|
||||
drivers/clk/clk-allo-dac.c | 161 -----------------------------
|
||||
drivers/clk/clk-hifiberry-dacpro.c | 57 ++++++----
|
||||
sound/soc/bcm/Kconfig | 1 +
|
||||
4 files changed, 40 insertions(+), 180 deletions(-)
|
||||
delete mode 100644 drivers/clk/clk-allo-dac.c
|
||||
|
||||
--- a/drivers/clk/Makefile
|
||||
+++ b/drivers/clk/Makefile
|
||||
@@ -19,7 +19,6 @@ endif
|
||||
|
||||
# hardware specific clock types
|
||||
# please keep this section sorted lexicographically by file path name
|
||||
-obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC) += clk-allo-dac.o
|
||||
obj-$(CONFIG_COMMON_CLK_APPLE_NCO) += clk-apple-nco.o
|
||||
obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o
|
||||
obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
|
||||
--- a/drivers/clk/clk-allo-dac.c
|
||||
+++ /dev/null
|
||||
@@ -1,161 +0,0 @@
|
||||
-/*
|
||||
- * Clock Driver for Allo DAC
|
||||
- *
|
||||
- * Author: Baswaraj K <jaikumar@cem-solutions.net>
|
||||
- * Copyright 2016
|
||||
- * based on code by Stuart MacLean
|
||||
- *
|
||||
- * This program is free software; you can redistribute it and/or
|
||||
- * modify it under the terms of the GNU General Public License
|
||||
- * version 2 as published by the Free Software Foundation.
|
||||
- *
|
||||
- * 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 <linux/clk-provider.h>
|
||||
-#include <linux/clkdev.h>
|
||||
-#include <linux/kernel.h>
|
||||
-#include <linux/module.h>
|
||||
-#include <linux/of.h>
|
||||
-#include <linux/slab.h>
|
||||
-#include <linux/platform_device.h>
|
||||
-
|
||||
-/* Clock rate of CLK44EN attached to GPIO6 pin */
|
||||
-#define CLK_44EN_RATE 45158400UL
|
||||
-/* Clock rate of CLK48EN attached to GPIO3 pin */
|
||||
-#define CLK_48EN_RATE 49152000UL
|
||||
-
|
||||
-/**
|
||||
- * struct allo_dac_clk - Common struct to the Allo DAC
|
||||
- * @hw: clk_hw for the common clk framework
|
||||
- * @mode: 0 => CLK44EN, 1 => CLK48EN
|
||||
- */
|
||||
-struct clk_allo_hw {
|
||||
- struct clk_hw hw;
|
||||
- uint8_t mode;
|
||||
-};
|
||||
-
|
||||
-#define to_allo_clk(_hw) container_of(_hw, struct clk_allo_hw, hw)
|
||||
-
|
||||
-static const struct of_device_id clk_allo_dac_dt_ids[] = {
|
||||
- { .compatible = "allo,dac-clk",},
|
||||
- { }
|
||||
-};
|
||||
-MODULE_DEVICE_TABLE(of, clk_allo_dac_dt_ids);
|
||||
-
|
||||
-static unsigned long clk_allo_dac_recalc_rate(struct clk_hw *hw,
|
||||
- unsigned long parent_rate)
|
||||
-{
|
||||
- return (to_allo_clk(hw)->mode == 0) ? CLK_44EN_RATE :
|
||||
- CLK_48EN_RATE;
|
||||
-}
|
||||
-
|
||||
-static long clk_allo_dac_round_rate(struct clk_hw *hw,
|
||||
- unsigned long rate, unsigned long *parent_rate)
|
||||
-{
|
||||
- long actual_rate;
|
||||
-
|
||||
- if (rate <= CLK_44EN_RATE) {
|
||||
- actual_rate = (long)CLK_44EN_RATE;
|
||||
- } else if (rate >= CLK_48EN_RATE) {
|
||||
- actual_rate = (long)CLK_48EN_RATE;
|
||||
- } else {
|
||||
- long diff44Rate = (long)(rate - CLK_44EN_RATE);
|
||||
- long diff48Rate = (long)(CLK_48EN_RATE - rate);
|
||||
-
|
||||
- if (diff44Rate < diff48Rate)
|
||||
- actual_rate = (long)CLK_44EN_RATE;
|
||||
- else
|
||||
- actual_rate = (long)CLK_48EN_RATE;
|
||||
- }
|
||||
- return actual_rate;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-static int clk_allo_dac_set_rate(struct clk_hw *hw,
|
||||
- unsigned long rate, unsigned long parent_rate)
|
||||
-{
|
||||
- unsigned long actual_rate;
|
||||
- struct clk_allo_hw *clk = to_allo_clk(hw);
|
||||
-
|
||||
- actual_rate = (unsigned long)clk_allo_dac_round_rate(hw, rate,
|
||||
- &parent_rate);
|
||||
- clk->mode = (actual_rate == CLK_44EN_RATE) ? 0 : 1;
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-const struct clk_ops clk_allo_dac_rate_ops = {
|
||||
- .recalc_rate = clk_allo_dac_recalc_rate,
|
||||
- .round_rate = clk_allo_dac_round_rate,
|
||||
- .set_rate = clk_allo_dac_set_rate,
|
||||
-};
|
||||
-
|
||||
-static int clk_allo_dac_probe(struct platform_device *pdev)
|
||||
-{
|
||||
- int ret;
|
||||
- struct clk_allo_hw *proclk;
|
||||
- struct clk *clk;
|
||||
- struct device *dev;
|
||||
- struct clk_init_data init;
|
||||
-
|
||||
- dev = &pdev->dev;
|
||||
-
|
||||
- proclk = kzalloc(sizeof(struct clk_allo_hw), GFP_KERNEL);
|
||||
- if (!proclk)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- init.name = "clk-allo-dac";
|
||||
- init.ops = &clk_allo_dac_rate_ops;
|
||||
- init.flags = 0;
|
||||
- init.parent_names = NULL;
|
||||
- init.num_parents = 0;
|
||||
-
|
||||
- proclk->mode = 0;
|
||||
- proclk->hw.init = &init;
|
||||
-
|
||||
- clk = devm_clk_register(dev, &proclk->hw);
|
||||
- if (!IS_ERR(clk)) {
|
||||
- ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
|
||||
- clk);
|
||||
- } else {
|
||||
- dev_err(dev, "Fail to register clock driver\n");
|
||||
- kfree(proclk);
|
||||
- ret = PTR_ERR(clk);
|
||||
- }
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static int clk_allo_dac_remove(struct platform_device *pdev)
|
||||
-{
|
||||
- of_clk_del_provider(pdev->dev.of_node);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static struct platform_driver clk_allo_dac_driver = {
|
||||
- .probe = clk_allo_dac_probe,
|
||||
- .remove = clk_allo_dac_remove,
|
||||
- .driver = {
|
||||
- .name = "clk-allo-dac",
|
||||
- .of_match_table = clk_allo_dac_dt_ids,
|
||||
- },
|
||||
-};
|
||||
-
|
||||
-static int __init clk_allo_dac_init(void)
|
||||
-{
|
||||
- return platform_driver_register(&clk_allo_dac_driver);
|
||||
-}
|
||||
-core_initcall(clk_allo_dac_init);
|
||||
-
|
||||
-static void __exit clk_allo_dac_exit(void)
|
||||
-{
|
||||
- platform_driver_unregister(&clk_allo_dac_driver);
|
||||
-}
|
||||
-module_exit(clk_allo_dac_exit);
|
||||
-
|
||||
-MODULE_DESCRIPTION("Allo DAC clock driver");
|
||||
-MODULE_LICENSE("GPL v2");
|
||||
-MODULE_ALIAS("platform:clk-allo-dac");
|
||||
--- a/drivers/clk/clk-hifiberry-dacpro.c
|
||||
+++ b/drivers/clk/clk-hifiberry-dacpro.c
|
||||
@@ -22,10 +22,12 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
-/* Clock rate of CLK44EN attached to GPIO6 pin */
|
||||
-#define CLK_44EN_RATE 22579200UL
|
||||
-/* Clock rate of CLK48EN attached to GPIO3 pin */
|
||||
-#define CLK_48EN_RATE 24576000UL
|
||||
+struct ext_clk_rates {
|
||||
+ /* Clock rate of CLK44EN attached to GPIO6 pin */
|
||||
+ unsigned long clk_44en;
|
||||
+ /* Clock rate of CLK48EN attached to GPIO3 pin */
|
||||
+ unsigned long clk_48en;
|
||||
+};
|
||||
|
||||
/**
|
||||
* struct hifiberry_dacpro_clk - Common struct to the HiFiBerry DAC Pro
|
||||
@@ -35,12 +37,24 @@
|
||||
struct clk_hifiberry_hw {
|
||||
struct clk_hw hw;
|
||||
uint8_t mode;
|
||||
+ struct ext_clk_rates clk_rates;
|
||||
};
|
||||
|
||||
#define to_hifiberry_clk(_hw) container_of(_hw, struct clk_hifiberry_hw, hw)
|
||||
|
||||
+static const struct ext_clk_rates hifiberry_dacpro_clks = {
|
||||
+ .clk_44en = 22579200UL,
|
||||
+ .clk_48en = 24576000UL,
|
||||
+};
|
||||
+
|
||||
+static const struct ext_clk_rates allo_dac_clks = {
|
||||
+ .clk_44en = 45158400UL,
|
||||
+ .clk_48en = 49152000UL,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id clk_hifiberry_dacpro_dt_ids[] = {
|
||||
- { .compatible = "hifiberry,dacpro-clk",},
|
||||
+ { .compatible = "hifiberry,dacpro-clk", &hifiberry_dacpro_clks },
|
||||
+ { .compatible = "allo,dac-clk", &allo_dac_clks },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, clk_hifiberry_dacpro_dt_ids);
|
||||
@@ -48,27 +62,29 @@ MODULE_DEVICE_TABLE(of, clk_hifiberry_da
|
||||
static unsigned long clk_hifiberry_dacpro_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
- return (to_hifiberry_clk(hw)->mode == 0) ? CLK_44EN_RATE :
|
||||
- CLK_48EN_RATE;
|
||||
+ struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw);
|
||||
+ return (clk->mode == 0) ? clk->clk_rates.clk_44en :
|
||||
+ clk->clk_rates.clk_48en;
|
||||
}
|
||||
|
||||
static long clk_hifiberry_dacpro_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long *parent_rate)
|
||||
{
|
||||
+ struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw);
|
||||
long actual_rate;
|
||||
|
||||
- if (rate <= CLK_44EN_RATE) {
|
||||
- actual_rate = (long)CLK_44EN_RATE;
|
||||
- } else if (rate >= CLK_48EN_RATE) {
|
||||
- actual_rate = (long)CLK_48EN_RATE;
|
||||
+ if (rate <= clk->clk_rates.clk_44en) {
|
||||
+ actual_rate = (long)clk->clk_rates.clk_44en;
|
||||
+ } else if (rate >= clk->clk_rates.clk_48en) {
|
||||
+ actual_rate = (long)clk->clk_rates.clk_48en;
|
||||
} else {
|
||||
- long diff44Rate = (long)(rate - CLK_44EN_RATE);
|
||||
- long diff48Rate = (long)(CLK_48EN_RATE - rate);
|
||||
+ long diff44Rate = (long)(rate - clk->clk_rates.clk_44en);
|
||||
+ long diff48Rate = (long)(clk->clk_rates.clk_48en - rate);
|
||||
|
||||
if (diff44Rate < diff48Rate)
|
||||
- actual_rate = (long)CLK_44EN_RATE;
|
||||
+ actual_rate = (long)clk->clk_rates.clk_44en;
|
||||
else
|
||||
- actual_rate = (long)CLK_48EN_RATE;
|
||||
+ actual_rate = (long)clk->clk_rates.clk_48en;
|
||||
}
|
||||
return actual_rate;
|
||||
}
|
||||
@@ -77,12 +93,12 @@ static long clk_hifiberry_dacpro_round_r
|
||||
static int clk_hifiberry_dacpro_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long parent_rate)
|
||||
{
|
||||
- unsigned long actual_rate;
|
||||
struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw);
|
||||
+ unsigned long actual_rate;
|
||||
|
||||
actual_rate = (unsigned long)clk_hifiberry_dacpro_round_rate(hw, rate,
|
||||
&parent_rate);
|
||||
- clk->mode = (actual_rate == CLK_44EN_RATE) ? 0 : 1;
|
||||
+ clk->mode = (actual_rate == clk->clk_rates.clk_44en) ? 0 : 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -95,13 +111,17 @@ const struct clk_ops clk_hifiberry_dacpr
|
||||
|
||||
static int clk_hifiberry_dacpro_probe(struct platform_device *pdev)
|
||||
{
|
||||
- int ret;
|
||||
+ const struct of_device_id *of_id;
|
||||
struct clk_hifiberry_hw *proclk;
|
||||
struct clk *clk;
|
||||
struct device *dev;
|
||||
struct clk_init_data init;
|
||||
+ int ret;
|
||||
|
||||
dev = &pdev->dev;
|
||||
+ of_id = of_match_node(clk_hifiberry_dacpro_dt_ids, dev->of_node);
|
||||
+ if (!of_id)
|
||||
+ return -EINVAL;
|
||||
|
||||
proclk = kzalloc(sizeof(struct clk_hifiberry_hw), GFP_KERNEL);
|
||||
if (!proclk)
|
||||
@@ -115,6 +135,7 @@ static int clk_hifiberry_dacpro_probe(st
|
||||
|
||||
proclk->mode = 0;
|
||||
proclk->hw.init = &init;
|
||||
+ memcpy(&proclk->clk_rates, of_id->data, sizeof(proclk->clk_rates));
|
||||
|
||||
clk = devm_clk_register(dev, &proclk->hw);
|
||||
if (!IS_ERR(clk)) {
|
||||
--- a/sound/soc/bcm/Kconfig
|
||||
+++ b/sound/soc/bcm/Kconfig
|
||||
@@ -271,6 +271,7 @@ config SND_BCM2708_SOC_ALLO_BOSS_DAC
|
||||
tristate "Support for Allo Boss DAC"
|
||||
depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM512x_I2C
|
||||
+ select COMMON_CLK_HIFIBERRY_DACPRO
|
||||
help
|
||||
Say Y or M if you want to add support for Allo Boss DAC.
|
||||
|
21
target/linux/bcm27xx/patches-6.1/950-0815-fixup-drm-tc358762-Set-the-pre_enable_upstream_first.patch
Normal file
21
target/linux/bcm27xx/patches-6.1/950-0815-fixup-drm-tc358762-Set-the-pre_enable_upstream_first.patch
Normal file
@ -0,0 +1,21 @@
|
||||
From 2addf7045f2b4866ab819f48e4d32f5734a32134 Mon Sep 17 00:00:00 2001
|
||||
From: Dom Cobley <popcornmix@gmail.com>
|
||||
Date: Thu, 20 Jul 2023 15:15:27 +0100
|
||||
Subject: [PATCH] fixup! drm/tc358762: Set the pre_enable_upstream_first flag
|
||||
to configure DSI host
|
||||
|
||||
---
|
||||
drivers/gpu/drm/bridge/tc358762.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/gpu/drm/bridge/tc358762.c
|
||||
+++ b/drivers/gpu/drm/bridge/tc358762.c
|
||||
@@ -229,7 +229,7 @@ static int tc358762_probe(struct mipi_ds
|
||||
ctx->bridge.funcs = &tc358762_bridge_funcs;
|
||||
ctx->bridge.type = DRM_MODE_CONNECTOR_DPI;
|
||||
ctx->bridge.of_node = dev->of_node;
|
||||
- ctx->bridge.pre_enable_upstream_first = true;
|
||||
+ ctx->bridge.pre_enable_prev_first = true;
|
||||
|
||||
drm_bridge_add(&ctx->bridge);
|
||||
|
48
target/linux/bcm27xx/patches-6.1/950-0816-rpi-sound-cards-Fix-Codec-Zero-rate-switching.patch
Normal file
48
target/linux/bcm27xx/patches-6.1/950-0816-rpi-sound-cards-Fix-Codec-Zero-rate-switching.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From b84b8a9ad2046a855a7044b6368def01ddd5de6e Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Fri, 21 Jul 2023 16:50:56 +0100
|
||||
Subject: [PATCH] rpi sound cards: Fix Codec Zero rate switching
|
||||
|
||||
The Raspberry Pi Codec Zero (and IQaudIO Codec) don't notify the DA7213
|
||||
codec when it needs to change PLL frequencies. As a result, audio can
|
||||
be played at the wrong rate - play a 48kHz sound immediately after a
|
||||
44.1kHz sound to see the effect, but in some configurations the codec
|
||||
can lock into the wrong state and always get some rates wrong.
|
||||
|
||||
Add the necessary notification to fix the issue.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
sound/soc/bcm/iqaudio-codec.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/sound/soc/bcm/iqaudio-codec.c
|
||||
+++ b/sound/soc/bcm/iqaudio-codec.c
|
||||
@@ -143,6 +143,7 @@ static int snd_rpi_iqaudio_codec_hw_para
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
+ struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
unsigned int samplerate = params_rate(params);
|
||||
|
||||
switch (samplerate) {
|
||||
@@ -152,15 +153,17 @@ static int snd_rpi_iqaudio_codec_hw_para
|
||||
case 48000:
|
||||
case 96000:
|
||||
pll_out = DA7213_PLL_FREQ_OUT_98304000;
|
||||
- return 0;
|
||||
+ break;
|
||||
case 44100:
|
||||
case 88200:
|
||||
pll_out = DA7213_PLL_FREQ_OUT_90316800;
|
||||
- return 0;
|
||||
+ break;
|
||||
default:
|
||||
dev_err(rtd->dev,"Unsupported samplerate %d\n", samplerate);
|
||||
return -EINVAL;
|
||||
}
|
||||
+
|
||||
+ return snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0, pll_out);
|
||||
}
|
||||
|
||||
static const struct snd_soc_ops snd_rpi_iqaudio_codec_ops = {
|
68
target/linux/bcm27xx/patches-6.1/950-0818-overlays-Add-trickle-voltage-mv-parameter-to-RTCs.patch
Normal file
68
target/linux/bcm27xx/patches-6.1/950-0818-overlays-Add-trickle-voltage-mv-parameter-to-RTCs.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From 31822340129e3c4030500d7f30ce4d19bbf9dd40 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Mon, 24 Jul 2023 17:34:47 +0100
|
||||
Subject: [PATCH] overlays: Add trickle-voltage-mv parameter to RTCs
|
||||
|
||||
The RV3032 RTC requires an additional DT property to enable trickle
|
||||
charging. Add a parameter - trickle-voltage-mv - to the i2c-rtc
|
||||
and i2c-rtc-gpio overlays to set it.
|
||||
|
||||
See: https://github.com/raspberrypi/linux/issues/5547
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/README | 12 ++++++++----
|
||||
arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi | 2 ++
|
||||
2 files changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/README
|
||||
+++ b/arch/arm/boot/dts/overlays/README
|
||||
@@ -1957,13 +1957,15 @@ Params: abx80x Select o
|
||||
"schottky" (ABx80x and RV1805 only)
|
||||
|
||||
trickle-resistor-ohms Resistor value for trickle charge (DS1339,
|
||||
- ABx80x, RV1805, RV3028)
|
||||
+ ABx80x, BQ32000, RV1805, RV3028, RV3032)
|
||||
+
|
||||
+ trickle-voltage-mv Charge pump voltage for trickle charge (RV3032)
|
||||
|
||||
wakeup-source Specify that the RTC can be used as a wakeup
|
||||
source
|
||||
|
||||
backup-switchover-mode Backup power supply switch mode. Must be 0 for
|
||||
- off or 1 for Vdd < VBackup (RV3028 only)
|
||||
+ off or 1 for Vdd < VBackup (RV3028, RV3032)
|
||||
|
||||
|
||||
Name: i2c-rtc-gpio
|
||||
@@ -2027,13 +2029,15 @@ Params: abx80x Select o
|
||||
"schottky" (ABx80x and RV1805 only)
|
||||
|
||||
trickle-resistor-ohms Resistor value for trickle charge (DS1339,
|
||||
- ABx80x, RV1805, RV3028)
|
||||
+ ABx80x, BQ32000, RV1805, RV3028, RV3032)
|
||||
+
|
||||
+ trickle-voltage-mv Charge pump voltage for trickle charge (RV3032)
|
||||
|
||||
wakeup-source Specify that the RTC can be used as a wakeup
|
||||
source
|
||||
|
||||
backup-switchover-mode Backup power supply switch mode. Must be 0 for
|
||||
- off or 1 for Vdd < VBackup (RV3028 only)
|
||||
+ off or 1 for Vdd < VBackup (RV3028, RV3032)
|
||||
|
||||
i2c_gpio_sda GPIO used for I2C data (default "23")
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi
|
||||
+++ b/arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi
|
||||
@@ -339,8 +339,10 @@
|
||||
<&ds1340>,"trickle-resistor-ohms:0",
|
||||
<&abx80x>,"abracon,tc-resistor:0",
|
||||
<&rv3028>,"trickle-resistor-ohms:0",
|
||||
+ <&rv3032>,"trickle-resistor-ohms:0",
|
||||
<&rv1805>,"abracon,tc-resistor:0",
|
||||
<&bq32000>,"abracon,tc-resistor:0";
|
||||
+ trickle-voltage-mv = <&rv3032>,"trickle-voltage-millivolts:0";
|
||||
backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0";
|
||||
wakeup-source = <&ds1339>,"wakeup-source?",
|
||||
<&ds3231>,"wakeup-source?",
|
25
target/linux/bcm27xx/patches-6.1/950-0819-drivers-media-imx296-Add-standby-delay-during-probe.patch
Normal file
25
target/linux/bcm27xx/patches-6.1/950-0819-drivers-media-imx296-Add-standby-delay-during-probe.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 5fb3b300557d6a6902e7321f42fdabb8c09eef54 Mon Sep 17 00:00:00 2001
|
||||
From: Naushir Patuck <naush@raspberrypi.com>
|
||||
Date: Fri, 28 Jul 2023 12:00:40 +0100
|
||||
Subject: [PATCH] drivers: media: imx296: Add standby delay during probe
|
||||
|
||||
Add a 2-5ms delay when coming out of standby and before reading the
|
||||
sensor info register durning probe, as instructed by the datasheet. This
|
||||
standby delay is already present when the sensor starts streaming.
|
||||
|
||||
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
|
||||
---
|
||||
drivers/media/i2c/imx296.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/media/i2c/imx296.c
|
||||
+++ b/drivers/media/i2c/imx296.c
|
||||
@@ -1022,6 +1022,8 @@ static int imx296_identify_model(struct
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ usleep_range(2000, 5000);
|
||||
+
|
||||
ret = imx296_read(sensor, IMX296_SENSOR_INFO);
|
||||
if (ret < 0) {
|
||||
dev_err(sensor->dev, "failed to read sensor information (%d)\n",
|
78
target/linux/bcm27xx/patches-6.1/950-0820-overlays-Add-bmp380-to-i2c-sensor-overlay.patch
Normal file
78
target/linux/bcm27xx/patches-6.1/950-0820-overlays-Add-bmp380-to-i2c-sensor-overlay.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From e1016d61e3dcb058932e8ec5072f2c4bbb05fcb7 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Sun, 30 Jul 2023 18:27:03 +0100
|
||||
Subject: [PATCH] overlays: Add bmp380 to i2c-sensor overlay
|
||||
|
||||
Add support for the BMP380 pressor sensor to the i2c-sensor overlay.
|
||||
|
||||
See: https://github.com/raspberrypi/linux/issues/5558
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/README | 7 +++++--
|
||||
.../boot/dts/overlays/i2c-sensor-common.dtsi | 19 ++++++++++++++++++-
|
||||
2 files changed, 23 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/README
|
||||
+++ b/arch/arm/boot/dts/overlays/README
|
||||
@@ -2052,8 +2052,8 @@ Info: Adds support for a number of I2C
|
||||
light level and chemical sensors on i2c_arm
|
||||
Load: dtoverlay=i2c-sensor,<param>=<val>
|
||||
Params: addr Set the address for the BH1750, BME280, BME680,
|
||||
- BMP280, CCS811, DS1621, HDC100X, JC42, LM75,
|
||||
- MCP980x, MPU6050, MPU9250, MS5637, MS5803,
|
||||
+ BMP280, BMP380, CCS811, DS1621, HDC100X, JC42,
|
||||
+ LM75, MCP980x, MPU6050, MPU9250, MS5637, MS5803,
|
||||
MS5805, MS5837, MS8607, SHT3x or TMP102
|
||||
|
||||
aht10 Select the Aosong AHT10 temperature and humidity
|
||||
@@ -2075,6 +2075,9 @@ Params: addr Set the
|
||||
bmp280 Select the Bosch Sensortronic BMP280
|
||||
Valid addresses 0x76-0x77, default 0x76
|
||||
|
||||
+ bmp380 Select the Bosch Sensortronic BMP380
|
||||
+ Valid addresses 0x76-0x77, default 0x76
|
||||
+
|
||||
bno055 Select the Bosch Sensortronic BNO055 IMU
|
||||
Valid address 0x28-0x29, default 0x29
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi
|
||||
+++ b/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi
|
||||
@@ -493,11 +493,27 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ fragment@33 {
|
||||
+ target = <&i2cbus>;
|
||||
+ __dormant__ {
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ status = "okay";
|
||||
+
|
||||
+ bmp380: bmp380@76 {
|
||||
+ compatible = "bosch,bmp380";
|
||||
+ reg = <0x76>;
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
__overrides__ {
|
||||
bme280 = <0>,"+0";
|
||||
bmp085 = <0>,"+1";
|
||||
bmp180 = <0>,"+2";
|
||||
bmp280 = <0>,"+3";
|
||||
+ bmp380 = <0>,"+33";
|
||||
htu21 = <0>,"+4";
|
||||
lm75 = <0>,"+5";
|
||||
lm75addr = <&lm75>,"reg:0";
|
||||
@@ -535,7 +551,8 @@
|
||||
<&ms5637>,"reg:0", <&ms5803>,"reg:0", <&ms5805>,"reg:0",
|
||||
<&ms5837>,"reg:0", <&ms8607>,"reg:0",
|
||||
<&mpu6050>,"reg:0", <&mpu9250>,"reg:0",
|
||||
- <&bno055>,"reg:0", <&sht4x>,"reg:0";
|
||||
+ <&bno055>,"reg:0", <&sht4x>,"reg:0",
|
||||
+ <&bmp380>,"reg:0";
|
||||
int_pin = <&max30102>, "interrupts:0",
|
||||
<&mpu6050>, "interrupts:0",
|
||||
<&mpu9250>, "interrupts:0";
|
162
target/linux/bcm27xx/patches-6.1/950-0821-can-isotp-add-module-parameter-for-maximum-pdu-size.patch
Normal file
162
target/linux/bcm27xx/patches-6.1/950-0821-can-isotp-add-module-parameter-for-maximum-pdu-size.patch
Normal file
@ -0,0 +1,162 @@
|
||||
From 4b729a06b15fc5ee3694dcc62346dcb718ae4290 Mon Sep 17 00:00:00 2001
|
||||
From: Oliver Hartkopp <socketcan@hartkopp.net>
|
||||
Date: Sun, 26 Mar 2023 13:59:11 +0200
|
||||
Subject: [PATCH] can: isotp: add module parameter for maximum pdu size
|
||||
|
||||
commit 96d1c81e6a0478535342dff6c730adb076cd84e8 upstream.
|
||||
|
||||
With ISO 15765-2:2016 the PDU size is not limited to 2^12 - 1 (4095)
|
||||
bytes but can be represented as a 32 bit unsigned integer value which
|
||||
allows 2^32 - 1 bytes (~4GB). The use-cases like automotive unified
|
||||
diagnostic services (UDS) and flashing of ECUs still use the small
|
||||
static buffers which are provided at socket creation time.
|
||||
|
||||
When a use-case requires to transfer PDUs up to 1025 kByte the maximum
|
||||
PDU size can now be extended by setting the module parameter
|
||||
max_pdu_size. The extended size buffers are only allocated on a
|
||||
per-socket/connection base when needed at run-time.
|
||||
|
||||
changes since v2: https://lore.kernel.org/all/20230313172510.3851-1-socketcan@hartkopp.net
|
||||
- use ARRAY_SIZE() to reference DEFAULT_MAX_PDU_SIZE only at one place
|
||||
|
||||
changes since v1: https://lore.kernel.org/all/20230311143446.3183-1-socketcan@hartkopp.net
|
||||
- limit the minimum 'max_pdu_size' to 4095 to maintain the classic
|
||||
behavior before ISO 15765-2:2016
|
||||
|
||||
Link: https://github.com/raspberrypi/linux/issues/5371
|
||||
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
|
||||
Link: https://lore.kernel.org/all/20230326115911.15094-1-socketcan@hartkopp.net
|
||||
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
|
||||
---
|
||||
net/can/isotp.c | 65 ++++++++++++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 56 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/net/can/isotp.c
|
||||
+++ b/net/can/isotp.c
|
||||
@@ -85,10 +85,21 @@ MODULE_ALIAS("can-proto-6");
|
||||
|
||||
/* ISO 15765-2:2016 supports more than 4095 byte per ISO PDU as the FF_DL can
|
||||
* take full 32 bit values (4 Gbyte). We would need some good concept to handle
|
||||
- * this between user space and kernel space. For now increase the static buffer
|
||||
- * to something about 64 kbyte to be able to test this new functionality.
|
||||
+ * this between user space and kernel space. For now set the static buffer to
|
||||
+ * something about 8 kbyte to be able to test this new functionality.
|
||||
*/
|
||||
-#define MAX_MSG_LENGTH 66000
|
||||
+#define DEFAULT_MAX_PDU_SIZE 8300
|
||||
+
|
||||
+/* maximum PDU size before ISO 15765-2:2016 extension was 4095 */
|
||||
+#define MAX_12BIT_PDU_SIZE 4095
|
||||
+
|
||||
+/* limit the isotp pdu size from the optional module parameter to 1MByte */
|
||||
+#define MAX_PDU_SIZE (1025 * 1024U)
|
||||
+
|
||||
+static unsigned int max_pdu_size __read_mostly = DEFAULT_MAX_PDU_SIZE;
|
||||
+module_param(max_pdu_size, uint, 0444);
|
||||
+MODULE_PARM_DESC(max_pdu_size, "maximum isotp pdu size (default "
|
||||
+ __stringify(DEFAULT_MAX_PDU_SIZE) ")");
|
||||
|
||||
/* N_PCI type values in bits 7-4 of N_PCI bytes */
|
||||
#define N_PCI_SF 0x00 /* single frame */
|
||||
@@ -124,13 +135,15 @@ enum {
|
||||
};
|
||||
|
||||
struct tpcon {
|
||||
- unsigned int idx;
|
||||
+ u8 *buf;
|
||||
+ unsigned int buflen;
|
||||
unsigned int len;
|
||||
+ unsigned int idx;
|
||||
u32 state;
|
||||
u8 bs;
|
||||
u8 sn;
|
||||
u8 ll_dl;
|
||||
- u8 buf[MAX_MSG_LENGTH + 1];
|
||||
+ u8 sbuf[DEFAULT_MAX_PDU_SIZE];
|
||||
};
|
||||
|
||||
struct isotp_sock {
|
||||
@@ -498,7 +511,17 @@ static int isotp_rcv_ff(struct sock *sk,
|
||||
if (so->rx.len + ae + off + ff_pci_sz < so->rx.ll_dl)
|
||||
return 1;
|
||||
|
||||
- if (so->rx.len > MAX_MSG_LENGTH) {
|
||||
+ /* PDU size > default => try max_pdu_size */
|
||||
+ if (so->rx.len > so->rx.buflen && so->rx.buflen < max_pdu_size) {
|
||||
+ u8 *newbuf = kmalloc(max_pdu_size, GFP_ATOMIC);
|
||||
+
|
||||
+ if (newbuf) {
|
||||
+ so->rx.buf = newbuf;
|
||||
+ so->rx.buflen = max_pdu_size;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (so->rx.len > so->rx.buflen) {
|
||||
/* send FC frame with overflow status */
|
||||
isotp_send_fc(sk, ae, ISOTP_FC_OVFLW);
|
||||
return 1;
|
||||
@@ -802,7 +825,7 @@ static void isotp_create_fframe(struct c
|
||||
cf->data[0] = so->opt.ext_address;
|
||||
|
||||
/* create N_PCI bytes with 12/32 bit FF_DL data length */
|
||||
- if (so->tx.len > 4095) {
|
||||
+ if (so->tx.len > MAX_12BIT_PDU_SIZE) {
|
||||
/* use 32 bit FF_DL notation */
|
||||
cf->data[ae] = N_PCI_FF;
|
||||
cf->data[ae + 1] = 0;
|
||||
@@ -939,7 +962,17 @@ static int isotp_sendmsg(struct socket *
|
||||
goto err_event_drop;
|
||||
}
|
||||
|
||||
- if (!size || size > MAX_MSG_LENGTH) {
|
||||
+ /* PDU size > default => try max_pdu_size */
|
||||
+ if (size > so->tx.buflen && so->tx.buflen < max_pdu_size) {
|
||||
+ u8 *newbuf = kmalloc(max_pdu_size, GFP_KERNEL);
|
||||
+
|
||||
+ if (newbuf) {
|
||||
+ so->tx.buf = newbuf;
|
||||
+ so->tx.buflen = max_pdu_size;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!size || size > so->tx.buflen) {
|
||||
err = -EINVAL;
|
||||
goto err_out_drop;
|
||||
}
|
||||
@@ -1194,6 +1227,12 @@ static int isotp_release(struct socket *
|
||||
so->ifindex = 0;
|
||||
so->bound = 0;
|
||||
|
||||
+ if (so->rx.buf != so->rx.sbuf)
|
||||
+ kfree(so->rx.buf);
|
||||
+
|
||||
+ if (so->tx.buf != so->tx.sbuf)
|
||||
+ kfree(so->tx.buf);
|
||||
+
|
||||
sock_orphan(sk);
|
||||
sock->sk = NULL;
|
||||
|
||||
@@ -1588,6 +1627,11 @@ static int isotp_init(struct sock *sk)
|
||||
so->rx.state = ISOTP_IDLE;
|
||||
so->tx.state = ISOTP_IDLE;
|
||||
|
||||
+ so->rx.buf = so->rx.sbuf;
|
||||
+ so->tx.buf = so->tx.sbuf;
|
||||
+ so->rx.buflen = ARRAY_SIZE(so->rx.sbuf);
|
||||
+ so->tx.buflen = ARRAY_SIZE(so->tx.sbuf);
|
||||
+
|
||||
hrtimer_init(&so->rxtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
|
||||
so->rxtimer.function = isotp_rx_timer_handler;
|
||||
hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
|
||||
@@ -1670,7 +1714,10 @@ static __init int isotp_module_init(void
|
||||
{
|
||||
int err;
|
||||
|
||||
- pr_info("can: isotp protocol\n");
|
||||
+ max_pdu_size = max_t(unsigned int, max_pdu_size, MAX_12BIT_PDU_SIZE);
|
||||
+ max_pdu_size = min_t(unsigned int, max_pdu_size, MAX_PDU_SIZE);
|
||||
+
|
||||
+ pr_info("can: isotp protocol (max_pdu_size %d)\n", max_pdu_size);
|
||||
|
||||
err = can_proto_register(&isotp_can_proto);
|
||||
if (err < 0)
|
40
target/linux/bcm27xx/patches-6.1/950-0822-drivers-media-imx296-Updated-imx296-driver-for-exter.patch
Normal file
40
target/linux/bcm27xx/patches-6.1/950-0822-drivers-media-imx296-Updated-imx296-driver-for-exter.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From e1b03ea9e84320e6bf36a1486abaebbceadd7fc7 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Benson <ben.benson@raspberrypi.com>
|
||||
Date: Fri, 21 Jul 2023 15:59:51 +0100
|
||||
Subject: [PATCH] drivers: media: imx296: Updated imx296 driver for external
|
||||
trigger
|
||||
|
||||
Updated imx296 driver to support external trigger mode via XTR pin.
|
||||
Added module parameter to control this mode.
|
||||
|
||||
Signed-off-by: Ben Benson <ben.benson@raspberrypi.com>
|
||||
---
|
||||
drivers/media/i2c/imx296.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/drivers/media/i2c/imx296.c
|
||||
+++ b/drivers/media/i2c/imx296.c
|
||||
@@ -20,6 +20,10 @@
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
|
||||
+static int trigger_mode;
|
||||
+module_param(trigger_mode, int, 0644);
|
||||
+MODULE_PARM_DESC(trigger_mode, "Set trigger mode: 0=default, 1=XTRIG");
|
||||
+
|
||||
#define IMX296_PIXEL_ARRAY_WIDTH 1456
|
||||
#define IMX296_PIXEL_ARRAY_HEIGHT 1088
|
||||
|
||||
@@ -645,6 +649,12 @@ static int imx296_stream_on(struct imx29
|
||||
|
||||
imx296_write(sensor, IMX296_CTRL00, 0, &ret);
|
||||
usleep_range(2000, 5000);
|
||||
+
|
||||
+ if (trigger_mode == 1) {
|
||||
+ imx296_write(sensor, IMX296_CTRL0B, IMX296_CTRL0B_TRIGEN, &ret);
|
||||
+ imx296_write(sensor, IMX296_LOWLAGTRG, IMX296_LOWLAGTRG_FAST, &ret);
|
||||
+ }
|
||||
+
|
||||
imx296_write(sensor, IMX296_CTRL0A, 0, &ret);
|
||||
|
||||
/* vflip and hflip cannot change during streaming */
|
26
target/linux/bcm27xx/patches-6.1/950-0823-media-dt-bindings-imx258-Fix-alternate-compatible-st.patch
Normal file
26
target/linux/bcm27xx/patches-6.1/950-0823-media-dt-bindings-imx258-Fix-alternate-compatible-st.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From 74bc238e86e62109c74d8f229dc105bf3818b4a7 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Wed, 2 Aug 2023 14:35:32 +0100
|
||||
Subject: [PATCH] media: dt-bindings: imx258: Fix alternate compatible strings
|
||||
|
||||
Multiple compatible strings must appear as an enum.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
Documentation/devicetree/bindings/media/i2c/imx258.yaml | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/media/i2c/imx258.yaml
|
||||
+++ b/Documentation/devicetree/bindings/media/i2c/imx258.yaml
|
||||
@@ -19,8 +19,9 @@ description: |-
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
- const: sony,imx258
|
||||
- const: sony,imx258-pdaf
|
||||
+ enum:
|
||||
+ - sony,imx258
|
||||
+ - sony,imx258-pdaf
|
||||
|
||||
assigned-clocks: true
|
||||
assigned-clock-parents: true
|
21
target/linux/bcm27xx/patches-6.1/950-0825-char-broadcom-vc_mem-Fix-preprocessor-conditional.patch
Normal file
21
target/linux/bcm27xx/patches-6.1/950-0825-char-broadcom-vc_mem-Fix-preprocessor-conditional.patch
Normal file
@ -0,0 +1,21 @@
|
||||
From 282819aead0166af415b780241dc2def4caee7f4 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Winkowski <dereference23@outlook.com>
|
||||
Date: Mon, 3 Jul 2023 18:12:01 +0000
|
||||
Subject: [PATCH] char: broadcom: vc_mem: Fix preprocessor conditional
|
||||
|
||||
Signed-off-by: Alexander Winkowski <dereference23@outlook.com>
|
||||
---
|
||||
drivers/char/broadcom/vc_mem.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/char/broadcom/vc_mem.c
|
||||
+++ b/drivers/char/broadcom/vc_mem.c
|
||||
@@ -353,7 +353,7 @@ vc_mem_exit(void)
|
||||
pr_debug("%s: called\n", __func__);
|
||||
|
||||
if (vc_mem_inited) {
|
||||
-#if CONFIG_DEBUG_FS
|
||||
+#ifdef CONFIG_DEBUG_FS
|
||||
vc_mem_debugfs_deinit();
|
||||
#endif
|
||||
device_destroy(vc_mem_class, vc_mem_devnum);
|
32
target/linux/bcm27xx/patches-6.1/950-0826-drivers-dwc_otg-Fix-fallthrough-warnings.patch
Normal file
32
target/linux/bcm27xx/patches-6.1/950-0826-drivers-dwc_otg-Fix-fallthrough-warnings.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From ec61075a786c455444a1d5df338a41bacfce0bb1 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Winkowski <dereference23@outlook.com>
|
||||
Date: Mon, 3 Jul 2023 18:23:02 +0000
|
||||
Subject: [PATCH] drivers: dwc_otg: Fix fallthrough warnings
|
||||
|
||||
Signed-off-by: Alexander Winkowski <dereference23@outlook.com>
|
||||
---
|
||||
drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 1 +
|
||||
drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
|
||||
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
|
||||
@@ -2049,6 +2049,7 @@ int fiq_fsm_queue_split_transaction(dwc_
|
||||
} else {
|
||||
st->fsm = FIQ_PER_SSPLIT_QUEUED;
|
||||
}
|
||||
+ break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
|
||||
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
|
||||
@@ -402,7 +402,7 @@ int32_t dwc_otg_hcd_handle_rx_status_q_l
|
||||
hc->xfer_count += grxsts.b.bcnt;
|
||||
hc->xfer_buff += grxsts.b.bcnt;
|
||||
}
|
||||
-
|
||||
+ break;
|
||||
case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
|
||||
case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
|
||||
case DWC_GRXSTS_PKTSTS_CH_HALTED:
|
61
target/linux/bcm27xx/patches-6.1/950-0827-vc04_services-vc-sm-cma-Switch-one-bit-bitfields-to-.patch
Normal file
61
target/linux/bcm27xx/patches-6.1/950-0827-vc04_services-vc-sm-cma-Switch-one-bit-bitfields-to-.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From 2dd2f36d10961e3819ff0525ae2567e601973826 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Winkowski <dereference23@outlook.com>
|
||||
Date: Mon, 3 Jul 2023 18:29:37 +0000
|
||||
Subject: [PATCH] vc04_services/vc-sm-cma: Switch one-bit bitfields to bool
|
||||
|
||||
Clang 16 warns:
|
||||
|
||||
../drivers/staging/vc04_services/vc-sm-cma/vc_sm.c:816:19: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
|
||||
buffer->imported = 1;
|
||||
^ ~
|
||||
../drivers/staging/vc04_services/vc-sm-cma/vc_sm.c:822:17: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
|
||||
buffer->in_use = 1;
|
||||
^ ~
|
||||
2 warnings generated.
|
||||
|
||||
Signed-off-by: Alexander Winkowski <dereference23@outlook.com>
|
||||
---
|
||||
drivers/staging/vc04_services/vc-sm-cma/vc_sm.c | 6 +++---
|
||||
drivers/staging/vc04_services/vc-sm-cma/vc_sm.h | 4 ++--
|
||||
2 files changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
|
||||
+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
|
||||
@@ -533,7 +533,7 @@ static void vc_sm_dma_buf_release(struct
|
||||
|
||||
pr_debug("%s dmabuf %p, buffer %p\n", __func__, dmabuf, buffer);
|
||||
|
||||
- buffer->in_use = 0;
|
||||
+ buffer->in_use = false;
|
||||
|
||||
/* Unmap on the VPU */
|
||||
vc_sm_vpu_free(buffer);
|
||||
@@ -813,13 +813,13 @@ vc_sm_cma_import_dmabuf_internal(struct
|
||||
buffer->size = import.size;
|
||||
buffer->vpu_state = VPU_MAPPED;
|
||||
|
||||
- buffer->imported = 1;
|
||||
+ buffer->imported = true;
|
||||
buffer->import.dma_buf = dma_buf;
|
||||
|
||||
buffer->import.attach = attach;
|
||||
buffer->import.sgt = sgt;
|
||||
buffer->dma_addr = dma_addr;
|
||||
- buffer->in_use = 1;
|
||||
+ buffer->in_use = true;
|
||||
buffer->kernel_id = import.kernel_id;
|
||||
|
||||
/*
|
||||
--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
|
||||
+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.h
|
||||
@@ -57,8 +57,8 @@ struct vc_sm_buffer {
|
||||
|
||||
char name[VC_SM_MAX_NAME_LEN];
|
||||
|
||||
- int in_use:1; /* Kernel is still using this resource */
|
||||
- int imported:1; /* Imported dmabuf */
|
||||
+ bool in_use:1; /* Kernel is still using this resource */
|
||||
+ bool imported:1; /* Imported dmabuf */
|
||||
|
||||
enum vc_sm_vpu_mapping_state vpu_state;
|
||||
u32 vc_handle; /* VideoCore handle for this buffer */
|
21
target/linux/bcm27xx/patches-6.1/950-0828-media-i2c-ov2311-Fix-uninitialized-variable-usage.patch
Normal file
21
target/linux/bcm27xx/patches-6.1/950-0828-media-i2c-ov2311-Fix-uninitialized-variable-usage.patch
Normal file
@ -0,0 +1,21 @@
|
||||
From 3333d45347d313ea589b8b8da1193d342060a946 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Winkowski <dereference23@outlook.com>
|
||||
Date: Mon, 3 Jul 2023 18:36:45 +0000
|
||||
Subject: [PATCH] media: i2c: ov2311: Fix uninitialized variable usage
|
||||
|
||||
Signed-off-by: Alexander Winkowski <dereference23@outlook.com>
|
||||
---
|
||||
drivers/media/i2c/ov2311.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/media/i2c/ov2311.c
|
||||
+++ b/drivers/media/i2c/ov2311.c
|
||||
@@ -1018,7 +1018,7 @@ static int ov2311_check_sensor_id(struct
|
||||
struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &ov2311->client->dev;
|
||||
- u32 id = 0, id_msb;
|
||||
+ u32 id = 0, id_msb = 0;
|
||||
int ret;
|
||||
|
||||
ret = ov2311_read_reg(client, OV2311_REG_CHIP_ID + 1,
|
29
target/linux/bcm27xx/patches-6.1/950-0830-drm-panel-Fix-default-values-for-Waveshare-7.9-inch-.patch
Normal file
29
target/linux/bcm27xx/patches-6.1/950-0830-drm-panel-Fix-default-values-for-Waveshare-7.9-inch-.patch
Normal file
@ -0,0 +1,29 @@
|
||||
From e89e7655a197d28df49da2be7e2003436cf52197 Mon Sep 17 00:00:00 2001
|
||||
From: Ignacio Larrain <ilarrain@gmail.com>
|
||||
Date: Tue, 22 Aug 2023 11:11:56 -0400
|
||||
Subject: [PATCH] drm/panel: Fix default values for Waveshare 7.9 inch DSI
|
||||
touchscreen (#5565)
|
||||
|
||||
This fixes touchscreen calibration, axis swapping and inversion.
|
||||
|
||||
As referenced in https://github.com/raspberrypi/linux/issues/5550
|
||||
---
|
||||
.../dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- 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
|
||||
@@ -93,10 +93,10 @@
|
||||
<&touch>, "touchscreen-size-x:0=800",
|
||||
<&touch>, "touchscreen-size-y:0=480";
|
||||
7_9_inch = <&panel>, "compatible=waveshare,7.9inch-panel",
|
||||
- <&touch>, "touchscreen-size-x:0=400",
|
||||
- <&touch>, "touchscreen-size-y:0=1280",
|
||||
+ <&touch>, "touchscreen-size-x:0=4096",
|
||||
+ <&touch>, "touchscreen-size-y:0=4096",
|
||||
<&touch>, "touchscreen-inverted-x?",
|
||||
- <&touch>, "touchscreen-inverted-y?";
|
||||
+ <&touch>, "touchscreen-swapped-x-y?";
|
||||
8_0_inch = <&panel>, "compatible=waveshare,8.0inch-panel",
|
||||
<&touch>, "touchscreen-size-x:0=800",
|
||||
<&touch>, "touchscreen-size-y:0=1280",
|
102
target/linux/bcm27xx/patches-6.1/950-0831-dtoverlays-Add-i2c-bus-overrides-to-edt-ft5406-overl.patch
Normal file
102
target/linux/bcm27xx/patches-6.1/950-0831-dtoverlays-Add-i2c-bus-overrides-to-edt-ft5406-overl.patch
Normal file
@ -0,0 +1,102 @@
|
||||
From 3fa2fbb7f6e60b85086e454403c5eab1af63b1aa Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
Date: Wed, 14 Jun 2023 13:43:58 +0100
|
||||
Subject: [PATCH] dtoverlays: Add i2c bus overrides to edt-ft5406 overlay
|
||||
|
||||
Adds the option for the touch controller to be connected to any
|
||||
of the I2C ports.
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/README | 17 +++++++++++++++-
|
||||
.../boot/dts/overlays/edt-ft5406-overlay.dts | 20 +++++++++++++++++++
|
||||
arch/arm/boot/dts/overlays/edt-ft5406.dtsi | 9 ++++++++-
|
||||
3 files changed, 44 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/README
|
||||
+++ b/arch/arm/boot/dts/overlays/README
|
||||
@@ -1040,9 +1040,11 @@ Params: dr_mode Dual rol
|
||||
|
||||
|
||||
Name: edt-ft5406
|
||||
-Info: Overlay for the EDT FT5406 touchscreen on the CSI/DSI I2C interface.
|
||||
+Info: Overlay for the EDT FT5406 touchscreen.
|
||||
This works with the Raspberry Pi 7" touchscreen when not being polled
|
||||
by the firmware.
|
||||
+ By default the overlay uses the i2c_csi_dsi I2C interface, but this
|
||||
+ can be overridden
|
||||
You MUST use either "disable_touchscreen=1" or "ignore_lcd=1" in
|
||||
config.txt to stop the firmware polling the touchscreen.
|
||||
Load: dtoverlay=edt-ft5406,<param>=<val>
|
||||
@@ -1051,6 +1053,19 @@ Params: sizex Touchscr
|
||||
invx Touchscreen inverted x axis
|
||||
invy Touchscreen inverted y axis
|
||||
swapxy Touchscreen swapped x y axis
|
||||
+ i2c0 Choose the I2C0 bus on GPIOs 0&1
|
||||
+ i2c1 Choose the I2C1 bus on GPIOs 2&3
|
||||
+ 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)
|
||||
+ addr Sets the address for the touch controller. Note
|
||||
+ that the device must be configured to use the
|
||||
+ specified address.
|
||||
|
||||
|
||||
Name: enc28j60
|
||||
--- a/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts
|
||||
@@ -23,4 +23,24 @@
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
+
|
||||
+ __overrides__ {
|
||||
+ i2c0 = <&frag13>,"target:0=",<&i2c0>;
|
||||
+ i2c1 = <&frag13>, "target?=0",
|
||||
+ <&frag13>, "target-path=i2c1",
|
||||
+ <0>,"-0-1";
|
||||
+ i2c3 = <&frag13>, "target?=0",
|
||||
+ <&frag13>, "target-path=i2c3",
|
||||
+ <0>,"-0-1";
|
||||
+ i2c4 = <&frag13>, "target?=0",
|
||||
+ <&frag13>, "target-path=i2c4",
|
||||
+ <0>,"-0-1";
|
||||
+ i2c5 = <&frag13>, "target?=0",
|
||||
+ <&frag13>, "target-path=i2c5",
|
||||
+ <0>,"-0-1";
|
||||
+ i2c6 = <&frag13>, "target?=0",
|
||||
+ <&frag13>, "target-path=i2c6",
|
||||
+ <0>,"-0-1";
|
||||
+ addr = <&ft5406>,"reg:0";
|
||||
+ };
|
||||
};
|
||||
--- a/arch/arm/boot/dts/overlays/edt-ft5406.dtsi
|
||||
+++ b/arch/arm/boot/dts/overlays/edt-ft5406.dtsi
|
||||
@@ -23,7 +23,7 @@
|
||||
};
|
||||
|
||||
fragment@12 {
|
||||
- target = <&i2c_csi_dsi>;
|
||||
+ target = <&i2cbus>;
|
||||
__overlay__ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
@@ -37,6 +37,13 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ frag13: fragment@13 {
|
||||
+ target = <&i2c_csi_dsi>;
|
||||
+ i2cbus: __overlay__ {
|
||||
+ status = "okay";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
__overrides__ {
|
||||
sizex = <&ft5406>,"touchscreen-size-x:0";
|
||||
sizey = <&ft5406>,"touchscreen-size-y:0";
|
25
target/linux/bcm27xx/patches-6.1/950-0832-dtoverlays-Fix-README-text-for-i2c-fan.patch
Normal file
25
target/linux/bcm27xx/patches-6.1/950-0832-dtoverlays-Fix-README-text-for-i2c-fan.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 9d9586dc0c0deecb90675bd70862fe262f7376ab Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
Date: Wed, 14 Jun 2023 14:25:21 +0100
|
||||
Subject: [PATCH] dtoverlays: Fix README text for i2c-fan
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/README | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/README
|
||||
+++ b/arch/arm/boot/dts/overlays/README
|
||||
@@ -1800,10 +1800,10 @@ Params: addr Sets the
|
||||
i2c3 Choose the I2C3 bus (configure with the i2c3
|
||||
overlay - BCM2711 only)
|
||||
|
||||
- i2c4 Choose the I2C3 bus (configure with the i2c3
|
||||
+ i2c4 Choose the I2C4 bus (configure with the i2c4
|
||||
overlay - BCM2711 only)
|
||||
|
||||
- i2c5 Choose the I2C5 bus (configure with the i2c4
|
||||
+ i2c5 Choose the I2C5 bus (configure with the i2c5
|
||||
overlay - BCM2711 only)
|
||||
|
||||
i2c6 Choose the I2C6 bus (configure with the i2c6
|
50
target/linux/bcm27xx/patches-6.1/950-0833-drivers-irqchip-irq-bcm2835-Concurrency-fix.patch
Normal file
50
target/linux/bcm27xx/patches-6.1/950-0833-drivers-irqchip-irq-bcm2835-Concurrency-fix.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From e804bd1843236a63815e9acfb1a38ebf9a28ef5b Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Thu, 31 Aug 2023 16:45:44 +0100
|
||||
Subject: [PATCH] drivers: irqchip: irq-bcm2835: Concurrency fix
|
||||
|
||||
The commit shown in Fixes: aims to improve interrupt throughput by
|
||||
getting the handlers invoked on different CPU cores. It does so (*) by
|
||||
using an irq_ack hook to change the interrupt routing.
|
||||
|
||||
Unfortunately, the IRQ status bits must be cleared at source, which only
|
||||
happens once the interrupt handler has run - there is no easy way for
|
||||
one core to claim one of the IRQs before sending the remainder to the
|
||||
next core on the list, so waking another core immediately results in a
|
||||
race with a chance of both cores handling the same IRQ. It is probably
|
||||
for this reason that the routing change is deferred to irq_ack, but that
|
||||
doesn't guarantee no clashes - after irq_ack is called, control returns
|
||||
to bcm2836_chained_handler_irq which proceeds to check for other pending
|
||||
IRQs at a time when the next core is probably doing the same thing.
|
||||
|
||||
Since the whole point of the original commit is to distribute the IRQ
|
||||
handling, there is no reason to attempt to handle multiple IRQs in one
|
||||
interrupt callback, so the problem can be solved (or at least made much
|
||||
harder to reproduce) by changing a "while" into an "if", so that each
|
||||
invocation only handles one IRQ.
|
||||
|
||||
(*) I'm not convinced it's as effective as claimed since irq_ack is
|
||||
called _after_ the interrupt handler, but the author thought it made a
|
||||
difference.
|
||||
|
||||
See: https://github.com/raspberrypi/linux/issues/5214
|
||||
https://github.com/raspberrypi/linux/pull/1794
|
||||
|
||||
Fixes: fd4c9785bde8 ("ARM64: Round-Robin dispatch IRQs between CPUs.")
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/irqchip/irq-bcm2835.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/irqchip/irq-bcm2835.c
|
||||
+++ b/drivers/irqchip/irq-bcm2835.c
|
||||
@@ -343,7 +343,8 @@ static void bcm2836_chained_handle_irq(s
|
||||
{
|
||||
u32 hwirq;
|
||||
|
||||
- while ((hwirq = get_next_armctrl_hwirq()) != ~0)
|
||||
+ hwirq = get_next_armctrl_hwirq();
|
||||
+ if (hwirq != ~0)
|
||||
generic_handle_domain_irq(intc.domain, hwirq);
|
||||
}
|
||||
|
58
target/linux/bcm27xx/patches-6.1/950-0835-dtoverlays-Add-drm-option-to-piscreen-overlay.patch
Normal file
58
target/linux/bcm27xx/patches-6.1/950-0835-dtoverlays-Add-drm-option-to-piscreen-overlay.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From 5e54398e1b61335883dff1be46a6c8b3ca973926 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
Date: Wed, 30 Aug 2023 18:03:37 +0100
|
||||
Subject: [PATCH] dtoverlays: Add drm option to piscreen overlay
|
||||
|
||||
Adds the option of selecting the DRM/KMS TinyDRM driver for
|
||||
this panel, rather than the deprecated FBTFT one.
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/README | 3 +++
|
||||
arch/arm/boot/dts/overlays/piscreen-overlay.dts | 10 +++++++---
|
||||
2 files changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/README
|
||||
+++ b/arch/arm/boot/dts/overlays/README
|
||||
@@ -3245,6 +3245,9 @@ Params: speed Display
|
||||
|
||||
xohms Touchpanel sensitivity (X-plate resistance)
|
||||
|
||||
+ drm Select the DRM/KMS driver instead of the FBTFT
|
||||
+ one
|
||||
+
|
||||
|
||||
Name: piscreen2r
|
||||
Info: PiScreen 2 with resistive TP display by OzzMaker.com
|
||||
--- a/arch/arm/boot/dts/overlays/piscreen-overlay.dts
|
||||
+++ b/arch/arm/boot/dts/overlays/piscreen-overlay.dts
|
||||
@@ -6,6 +6,8 @@
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
+#include <dt-bindings/gpio/gpio.h>
|
||||
+
|
||||
/ {
|
||||
compatible = "brcm,bcm2835";
|
||||
|
||||
@@ -59,9 +61,9 @@
|
||||
fps = <30>;
|
||||
buswidth = <8>;
|
||||
regwidth = <16>;
|
||||
- reset-gpios = <&gpio 25 1>;
|
||||
- dc-gpios = <&gpio 24 0>;
|
||||
- led-gpios = <&gpio 22 0>;
|
||||
+ reset-gpios = <&gpio 25 GPIO_ACTIVE_LOW>;
|
||||
+ dc-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
|
||||
+ led-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
|
||||
debug = <0>;
|
||||
|
||||
init = <0x10000b0 0x00
|
||||
@@ -98,5 +100,7 @@
|
||||
fps = <&piscreen>,"fps:0";
|
||||
debug = <&piscreen>,"debug:0";
|
||||
xohms = <&piscreen_ts>,"ti,x-plate-ohms;0";
|
||||
+ drm = <&piscreen>,"compatible=waveshare,rpi-lcd-35",
|
||||
+ <&piscreen>,"reset-gpios:8=",<GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
36
target/linux/bcm27xx/patches-6.1/950-0836-drm-ili9486-Resolve-clash-in-spi_device_id-names.patch
Normal file
36
target/linux/bcm27xx/patches-6.1/950-0836-drm-ili9486-Resolve-clash-in-spi_device_id-names.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From f59fe2d1bd056af117eb512bb0e9210a943c6d47 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
Date: Fri, 1 Sep 2023 12:17:38 +0100
|
||||
Subject: [PATCH] drm/ili9486: Resolve clash in spi_device_id names
|
||||
|
||||
For "Really Good Reasons" [1] the SPI core requires a match
|
||||
between compatible device strings and the name in spi_device_id.
|
||||
|
||||
The ili9486 driver uses compatible strings "waveshare,rpi-lcd-35"
|
||||
and "ozzmaker,piscreen", but "rpi-lcd-35" and "piscreen" are missing,
|
||||
so add them.
|
||||
|
||||
Compatible string "ilitek,ili9486" is already used by
|
||||
staging/fbtft/fb_ili9486, therefore leaving it present in ili9486 as an
|
||||
spi_device_id causes the incorrect module to be loaded, therefore remove
|
||||
this id.
|
||||
|
||||
[1] https://elixir.bootlin.com/linux/latest/source/drivers/spi/spi.c#L487
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
---
|
||||
drivers/gpu/drm/tiny/ili9486.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/gpu/drm/tiny/ili9486.c
|
||||
+++ b/drivers/gpu/drm/tiny/ili9486.c
|
||||
@@ -187,7 +187,8 @@ static const struct of_device_id ili9486
|
||||
MODULE_DEVICE_TABLE(of, ili9486_of_match);
|
||||
|
||||
static const struct spi_device_id ili9486_id[] = {
|
||||
- { "ili9486", 0 },
|
||||
+ { "rpi-lcd-35", 0 },
|
||||
+ { "piscreen", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, ili9486_id);
|
50
target/linux/bcm27xx/patches-6.1/950-0837-input-ads7846-Add-missing-spi_device_id-strings.patch
Normal file
50
target/linux/bcm27xx/patches-6.1/950-0837-input-ads7846-Add-missing-spi_device_id-strings.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 50c5a8558f4aaa54a3c4f5a8c2b6053f641d94eb Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
Date: Fri, 1 Sep 2023 12:23:30 +0100
|
||||
Subject: [PATCH] input: ads7846: Add missing spi_device_id strings
|
||||
|
||||
The SPI core logs error messages if a compatible string device
|
||||
name is not also present as an spi_device_id.
|
||||
|
||||
No spi_device_id values are specified by the driver, therefore
|
||||
we get 4 log lines every time it is loaded:
|
||||
SPI driver ads7846 has no spi_device_id for ti,tsc2046
|
||||
SPI driver ads7846 has no spi_device_id for ti,ads7843
|
||||
SPI driver ads7846 has no spi_device_id for ti,ads7845
|
||||
SPI driver ads7846 has no spi_device_id for ti,ads7873
|
||||
|
||||
Add the spi_device_id values for these devices.
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
---
|
||||
drivers/input/touchscreen/ads7846.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
--- a/drivers/input/touchscreen/ads7846.c
|
||||
+++ b/drivers/input/touchscreen/ads7846.c
|
||||
@@ -1127,6 +1127,17 @@ static const struct of_device_id ads7846
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ads7846_dt_ids);
|
||||
|
||||
+static const struct spi_device_id ads7846_spi_ids[] = {
|
||||
+ { "tsc2046", 0 },
|
||||
+ { "ads7843", 0 },
|
||||
+ { "ads7843", 0 },
|
||||
+ { "ads7845", 0 },
|
||||
+ { "ads7846", 0 },
|
||||
+ { "ads7873", 0 },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(spi, ads7846_spi_ids);
|
||||
+
|
||||
static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
|
||||
{
|
||||
struct ads7846_platform_data *pdata;
|
||||
@@ -1424,6 +1435,7 @@ static struct spi_driver ads7846_driver
|
||||
.pm = &ads7846_pm,
|
||||
.of_match_table = of_match_ptr(ads7846_dt_ids),
|
||||
},
|
||||
+ .id_table = ads7846_spi_ids,
|
||||
.probe = ads7846_probe,
|
||||
.remove = ads7846_remove,
|
||||
};
|
27
target/linux/bcm27xx/patches-6.1/950-0838-staging-bcm2835-codec-Downgrade-the-level-for-a-debu.patch
Normal file
27
target/linux/bcm27xx/patches-6.1/950-0838-staging-bcm2835-codec-Downgrade-the-level-for-a-debu.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 65742d7116e89b08858fcd7d67bd521ee19ee837 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
Date: Wed, 30 Aug 2023 18:05:43 +0100
|
||||
Subject: [PATCH] staging: bcm2835-codec: Downgrade the level for a debug
|
||||
message
|
||||
|
||||
The debug message from bcm2835_codec_buf_prepare when the buffer
|
||||
size is incorrect can be a little spammy if the application isn't
|
||||
careful on how it drives it, therefore drop the priority of the
|
||||
message.
|
||||
|
||||
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
---
|
||||
.../staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
|
||||
@@ -2883,7 +2883,7 @@ static int bcm2835_codec_buf_prepare(str
|
||||
}
|
||||
|
||||
if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
|
||||
- v4l2_err(&ctx->dev->v4l2_dev, "%s data will not fit into plane (%lu < %lu)\n",
|
||||
+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s data will not fit into plane (%lu < %lu)\n",
|
||||
__func__, vb2_plane_size(vb, 0),
|
||||
(long)q_data->sizeimage);
|
||||
return -EINVAL;
|
286
target/linux/bcm27xx/patches-6.1/950-0840-gpio-fsm-Sort-functions-into-a-more-logical-order.patch
Normal file
286
target/linux/bcm27xx/patches-6.1/950-0840-gpio-fsm-Sort-functions-into-a-more-logical-order.patch
Normal file
@ -0,0 +1,286 @@
|
||||
From cee471c3ada3215d6dfc53fb0f1b97548444dea7 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Tue, 5 Sep 2023 11:56:19 +0100
|
||||
Subject: [PATCH] gpio-fsm: Sort functions into a more logical order
|
||||
|
||||
Move some functions into a more logical ordering. This change causes
|
||||
no functional change and is essentially cosmetic.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/gpio/gpio-fsm.c | 245 ++++++++++++++++++++--------------------
|
||||
1 file changed, 125 insertions(+), 120 deletions(-)
|
||||
|
||||
--- a/drivers/gpio/gpio-fsm.c
|
||||
+++ b/drivers/gpio/gpio-fsm.c
|
||||
@@ -193,131 +193,14 @@ static void free_symbols(struct symtab_e
|
||||
}
|
||||
}
|
||||
|
||||
-static int gpio_fsm_get_direction(struct gpio_chip *gc, unsigned int off)
|
||||
-{
|
||||
- struct gpio_fsm *gf = gpiochip_get_data(gc);
|
||||
- struct soft_gpio *sg;
|
||||
-
|
||||
- if (off >= gf->num_soft_gpios)
|
||||
- return -EINVAL;
|
||||
- sg = &gf->soft_gpios[off];
|
||||
-
|
||||
- return sg->dir;
|
||||
-}
|
||||
-
|
||||
-static int gpio_fsm_get(struct gpio_chip *gc, unsigned int off)
|
||||
-{
|
||||
- struct gpio_fsm *gf = gpiochip_get_data(gc);
|
||||
- struct soft_gpio *sg;
|
||||
-
|
||||
- if (off >= gf->num_soft_gpios)
|
||||
- return -EINVAL;
|
||||
- sg = &gf->soft_gpios[off];
|
||||
-
|
||||
- return sg->value;
|
||||
-}
|
||||
-
|
||||
static void gpio_fsm_go_to_state(struct gpio_fsm *gf,
|
||||
- struct fsm_state *new_state)
|
||||
-{
|
||||
- struct input_gpio_state *inp_state;
|
||||
- struct gpio_event *gp_ev;
|
||||
- struct fsm_state *state;
|
||||
- int i;
|
||||
-
|
||||
- dev_dbg(gf->dev, "go_to_state(%s)\n",
|
||||
- new_state ? new_state->name : "<unset>");
|
||||
-
|
||||
- spin_lock(&gf->spinlock);
|
||||
-
|
||||
- if (gf->next_state) {
|
||||
- /* Something else has already requested a transition */
|
||||
- spin_unlock(&gf->spinlock);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- gf->next_state = new_state;
|
||||
- state = gf->current_state;
|
||||
- gf->delay_target_state = NULL;
|
||||
-
|
||||
- if (state) {
|
||||
- /* Disarm any GPIO IRQs */
|
||||
- for (i = 0; i < state->num_gpio_events; i++) {
|
||||
- gp_ev = &state->gpio_events[i];
|
||||
- inp_state = &gf->input_gpio_states[gp_ev->index];
|
||||
- inp_state->target = NULL;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- spin_unlock(&gf->spinlock);
|
||||
-
|
||||
- if (new_state)
|
||||
- schedule_work(&gf->work);
|
||||
-}
|
||||
+ struct fsm_state *new_state);
|
||||
|
||||
static void gpio_fsm_set_soft(struct gpio_fsm *gf,
|
||||
- unsigned int off, int val)
|
||||
-{
|
||||
- struct soft_gpio *sg = &gf->soft_gpios[off];
|
||||
- struct gpio_event *gp_ev;
|
||||
- struct fsm_state *state;
|
||||
- int i;
|
||||
-
|
||||
- dev_dbg(gf->dev, "set(%d,%d)\n", off, val);
|
||||
- state = gf->current_state;
|
||||
- sg->value = val;
|
||||
- for (i = 0; i < state->num_soft_events; i++) {
|
||||
- gp_ev = &state->soft_events[i];
|
||||
- if (gp_ev->index == off && gp_ev->value == val) {
|
||||
- if (gf->debug)
|
||||
- dev_info(gf->dev,
|
||||
- "GF_SOFT %d->%d -> %s\n", gp_ev->index,
|
||||
- gp_ev->value, gp_ev->target->name);
|
||||
- gpio_fsm_go_to_state(gf, gp_ev->target);
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static int gpio_fsm_direction_input(struct gpio_chip *gc, unsigned int off)
|
||||
-{
|
||||
- struct gpio_fsm *gf = gpiochip_get_data(gc);
|
||||
- struct soft_gpio *sg;
|
||||
-
|
||||
- if (off >= gf->num_soft_gpios)
|
||||
- return -EINVAL;
|
||||
- sg = &gf->soft_gpios[off];
|
||||
- sg->dir = GPIOF_DIR_IN;
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int gpio_fsm_direction_output(struct gpio_chip *gc, unsigned int off,
|
||||
- int value)
|
||||
-{
|
||||
- struct gpio_fsm *gf = gpiochip_get_data(gc);
|
||||
- struct soft_gpio *sg;
|
||||
-
|
||||
- if (off >= gf->num_soft_gpios)
|
||||
- return -EINVAL;
|
||||
- sg = &gf->soft_gpios[off];
|
||||
- sg->dir = GPIOF_DIR_OUT;
|
||||
- gpio_fsm_set_soft(gf, off, value);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void gpio_fsm_set(struct gpio_chip *gc, unsigned int off, int val)
|
||||
-{
|
||||
- struct gpio_fsm *gf;
|
||||
-
|
||||
- gf = gpiochip_get_data(gc);
|
||||
- if (off < gf->num_soft_gpios)
|
||||
- gpio_fsm_set_soft(gf, off, val);
|
||||
-}
|
||||
+ unsigned int off, int val);
|
||||
|
||||
static void gpio_fsm_enter_state(struct gpio_fsm *gf,
|
||||
- struct fsm_state *state)
|
||||
+ struct fsm_state *state)
|
||||
{
|
||||
struct input_gpio_state *inp_state;
|
||||
struct output_signal *signal;
|
||||
@@ -431,6 +314,44 @@ static void gpio_fsm_enter_state(struct
|
||||
}
|
||||
}
|
||||
|
||||
+static void gpio_fsm_go_to_state(struct gpio_fsm *gf,
|
||||
+ struct fsm_state *new_state)
|
||||
+{
|
||||
+ struct input_gpio_state *inp_state;
|
||||
+ struct gpio_event *gp_ev;
|
||||
+ struct fsm_state *state;
|
||||
+ int i;
|
||||
+
|
||||
+ dev_dbg(gf->dev, "go_to_state(%s)\n",
|
||||
+ new_state ? new_state->name : "<unset>");
|
||||
+
|
||||
+ spin_lock(&gf->spinlock);
|
||||
+
|
||||
+ if (gf->next_state) {
|
||||
+ /* Something else has already requested a transition */
|
||||
+ spin_unlock(&gf->spinlock);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ gf->next_state = new_state;
|
||||
+ state = gf->current_state;
|
||||
+ gf->delay_target_state = NULL;
|
||||
+
|
||||
+ if (state) {
|
||||
+ /* Disarm any GPIO IRQs */
|
||||
+ for (i = 0; i < state->num_gpio_events; i++) {
|
||||
+ gp_ev = &state->gpio_events[i];
|
||||
+ inp_state = &gf->input_gpio_states[gp_ev->index];
|
||||
+ inp_state->target = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock(&gf->spinlock);
|
||||
+
|
||||
+ if (new_state)
|
||||
+ schedule_work(&gf->work);
|
||||
+}
|
||||
+
|
||||
static void gpio_fsm_work(struct work_struct *work)
|
||||
{
|
||||
struct input_gpio_state *inp_state;
|
||||
@@ -851,6 +772,90 @@ static int resolve_sym_to_state(struct g
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void gpio_fsm_set_soft(struct gpio_fsm *gf,
|
||||
+ unsigned int off, int val)
|
||||
+{
|
||||
+ struct soft_gpio *sg = &gf->soft_gpios[off];
|
||||
+ struct gpio_event *gp_ev;
|
||||
+ struct fsm_state *state;
|
||||
+ int i;
|
||||
+
|
||||
+ dev_dbg(gf->dev, "set(%d,%d)\n", off, val);
|
||||
+ state = gf->current_state;
|
||||
+ sg->value = val;
|
||||
+ for (i = 0; i < state->num_soft_events; i++) {
|
||||
+ gp_ev = &state->soft_events[i];
|
||||
+ if (gp_ev->index == off && gp_ev->value == val) {
|
||||
+ if (gf->debug)
|
||||
+ dev_info(gf->dev,
|
||||
+ "GF_SOFT %d->%d -> %s\n", gp_ev->index,
|
||||
+ gp_ev->value, gp_ev->target->name);
|
||||
+ gpio_fsm_go_to_state(gf, gp_ev->target);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int gpio_fsm_get(struct gpio_chip *gc, unsigned int off)
|
||||
+{
|
||||
+ struct gpio_fsm *gf = gpiochip_get_data(gc);
|
||||
+ struct soft_gpio *sg;
|
||||
+
|
||||
+ if (off >= gf->num_soft_gpios)
|
||||
+ return -EINVAL;
|
||||
+ sg = &gf->soft_gpios[off];
|
||||
+
|
||||
+ return sg->value;
|
||||
+}
|
||||
+
|
||||
+static void gpio_fsm_set(struct gpio_chip *gc, unsigned int off, int val)
|
||||
+{
|
||||
+ struct gpio_fsm *gf;
|
||||
+
|
||||
+ gf = gpiochip_get_data(gc);
|
||||
+ if (off < gf->num_soft_gpios)
|
||||
+ gpio_fsm_set_soft(gf, off, val);
|
||||
+}
|
||||
+
|
||||
+static int gpio_fsm_get_direction(struct gpio_chip *gc, unsigned int off)
|
||||
+{
|
||||
+ struct gpio_fsm *gf = gpiochip_get_data(gc);
|
||||
+ struct soft_gpio *sg;
|
||||
+
|
||||
+ if (off >= gf->num_soft_gpios)
|
||||
+ return -EINVAL;
|
||||
+ sg = &gf->soft_gpios[off];
|
||||
+
|
||||
+ return sg->dir;
|
||||
+}
|
||||
+
|
||||
+static int gpio_fsm_direction_input(struct gpio_chip *gc, unsigned int off)
|
||||
+{
|
||||
+ struct gpio_fsm *gf = gpiochip_get_data(gc);
|
||||
+ struct soft_gpio *sg;
|
||||
+
|
||||
+ if (off >= gf->num_soft_gpios)
|
||||
+ return -EINVAL;
|
||||
+ sg = &gf->soft_gpios[off];
|
||||
+ sg->dir = GPIOF_DIR_IN;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int gpio_fsm_direction_output(struct gpio_chip *gc, unsigned int off,
|
||||
+ int value)
|
||||
+{
|
||||
+ struct gpio_fsm *gf = gpiochip_get_data(gc);
|
||||
+ struct soft_gpio *sg;
|
||||
+
|
||||
+ if (off >= gf->num_soft_gpios)
|
||||
+ return -EINVAL;
|
||||
+ sg = &gf->soft_gpios[off];
|
||||
+ sg->dir = GPIOF_DIR_OUT;
|
||||
+ gpio_fsm_set_soft(gf, off, value);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
|
||||
/*
|
||||
* /sys/class/gpio-fsm/<fsm-name>/
|
192
target/linux/bcm27xx/patches-6.1/950-0841-gpio_fsm-Rework-the-atomic-vs-non-atomic-split.patch
Normal file
192
target/linux/bcm27xx/patches-6.1/950-0841-gpio_fsm-Rework-the-atomic-vs-non-atomic-split.patch
Normal file
@ -0,0 +1,192 @@
|
||||
From f0061ffc98c6e027c5774e2a24ceadcfee4167ea Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Tue, 5 Sep 2023 12:01:13 +0100
|
||||
Subject: [PATCH] gpio_fsm: Rework the atomic-vs-non-atomic split
|
||||
|
||||
Partition the code to separate atomic and non-atomic methods so that
|
||||
none of them have to handle both cases. The result avoids using deferred
|
||||
work unless necessary, and should be easier to understand.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/gpio/gpio-fsm.c | 84 ++++++++++++++++++++---------------------
|
||||
1 file changed, 41 insertions(+), 43 deletions(-)
|
||||
|
||||
--- a/drivers/gpio/gpio-fsm.c
|
||||
+++ b/drivers/gpio/gpio-fsm.c
|
||||
@@ -193,9 +193,6 @@ static void free_symbols(struct symtab_e
|
||||
}
|
||||
}
|
||||
|
||||
-static void gpio_fsm_go_to_state(struct gpio_fsm *gf,
|
||||
- struct fsm_state *new_state);
|
||||
-
|
||||
static void gpio_fsm_set_soft(struct gpio_fsm *gf,
|
||||
unsigned int off, int val);
|
||||
|
||||
@@ -213,6 +210,7 @@ static void gpio_fsm_enter_state(struct
|
||||
dev_dbg(gf->dev, "enter_state(%s)\n", state->name);
|
||||
|
||||
gf->current_state = state;
|
||||
+ gf->delay_target_state = NULL;
|
||||
|
||||
// 1. Apply any listed signals
|
||||
for (i = 0; i < state->num_signals; i++) {
|
||||
@@ -271,7 +269,7 @@ static void gpio_fsm_enter_state(struct
|
||||
dev_info(gf->dev,
|
||||
"GF_SOFT %d=%d -> %s\n", event->index,
|
||||
event->value, event->target->name);
|
||||
- gpio_fsm_go_to_state(gf, event->target);
|
||||
+ gpio_fsm_enter_state(gf, event->target);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -284,7 +282,7 @@ static void gpio_fsm_enter_state(struct
|
||||
inp_state->value = event->value;
|
||||
inp_state->enabled = true;
|
||||
|
||||
- value = gpiod_get_value(gf->input_gpios->desc[event->index]);
|
||||
+ value = gpiod_get_value_cansleep(gf->input_gpios->desc[event->index]);
|
||||
|
||||
// Clear stale event state
|
||||
disable_irq(inp_state->irq);
|
||||
@@ -299,7 +297,7 @@ static void gpio_fsm_enter_state(struct
|
||||
dev_info(gf->dev,
|
||||
"GF_IN %d=%d -> %s\n", event->index,
|
||||
event->value, event->target->name);
|
||||
- gpio_fsm_go_to_state(gf, event->target);
|
||||
+ gpio_fsm_enter_state(gf, event->target);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -325,6 +323,33 @@ static void gpio_fsm_go_to_state(struct
|
||||
dev_dbg(gf->dev, "go_to_state(%s)\n",
|
||||
new_state ? new_state->name : "<unset>");
|
||||
|
||||
+ state = gf->current_state;
|
||||
+
|
||||
+ /* Disable any enabled GPIO IRQs */
|
||||
+ for (i = 0; i < state->num_gpio_events; i++) {
|
||||
+ gp_ev = &state->gpio_events[i];
|
||||
+ inp_state = &gf->input_gpio_states[gp_ev->index];
|
||||
+ if (inp_state->enabled) {
|
||||
+ inp_state->enabled = false;
|
||||
+ irq_set_irq_type(inp_state->irq,
|
||||
+ IRQF_TRIGGER_NONE);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ gpio_fsm_enter_state(gf, new_state);
|
||||
+}
|
||||
+
|
||||
+static void gpio_fsm_go_to_state_deferred(struct gpio_fsm *gf,
|
||||
+ struct fsm_state *new_state)
|
||||
+{
|
||||
+ struct input_gpio_state *inp_state;
|
||||
+ struct gpio_event *gp_ev;
|
||||
+ struct fsm_state *state;
|
||||
+ int i;
|
||||
+
|
||||
+ dev_dbg(gf->dev, "go_to_state_deferred(%s)\n",
|
||||
+ new_state ? new_state->name : "<unset>");
|
||||
+
|
||||
spin_lock(&gf->spinlock);
|
||||
|
||||
if (gf->next_state) {
|
||||
@@ -335,57 +360,31 @@ static void gpio_fsm_go_to_state(struct
|
||||
|
||||
gf->next_state = new_state;
|
||||
state = gf->current_state;
|
||||
- gf->delay_target_state = NULL;
|
||||
|
||||
- if (state) {
|
||||
- /* Disarm any GPIO IRQs */
|
||||
- for (i = 0; i < state->num_gpio_events; i++) {
|
||||
- gp_ev = &state->gpio_events[i];
|
||||
- inp_state = &gf->input_gpio_states[gp_ev->index];
|
||||
- inp_state->target = NULL;
|
||||
- }
|
||||
+ /* Disarm any GPIO IRQs */
|
||||
+ for (i = 0; i < state->num_gpio_events; i++) {
|
||||
+ gp_ev = &state->gpio_events[i];
|
||||
+ inp_state = &gf->input_gpio_states[gp_ev->index];
|
||||
+ inp_state->target = NULL;
|
||||
}
|
||||
|
||||
spin_unlock(&gf->spinlock);
|
||||
|
||||
- if (new_state)
|
||||
- schedule_work(&gf->work);
|
||||
+ schedule_work(&gf->work);
|
||||
}
|
||||
|
||||
static void gpio_fsm_work(struct work_struct *work)
|
||||
{
|
||||
- struct input_gpio_state *inp_state;
|
||||
struct fsm_state *new_state;
|
||||
- struct fsm_state *state;
|
||||
- struct gpio_event *gp_ev;
|
||||
struct gpio_fsm *gf;
|
||||
- int i;
|
||||
|
||||
gf = container_of(work, struct gpio_fsm, work);
|
||||
spin_lock(&gf->spinlock);
|
||||
- state = gf->current_state;
|
||||
new_state = gf->next_state;
|
||||
- if (!new_state)
|
||||
- new_state = gf->delay_target_state;
|
||||
gf->next_state = NULL;
|
||||
- gf->delay_target_state = NULL;
|
||||
spin_unlock(&gf->spinlock);
|
||||
|
||||
- if (state) {
|
||||
- /* Disable any enabled GPIO IRQs */
|
||||
- for (i = 0; i < state->num_gpio_events; i++) {
|
||||
- gp_ev = &state->gpio_events[i];
|
||||
- inp_state = &gf->input_gpio_states[gp_ev->index];
|
||||
- if (inp_state->enabled) {
|
||||
- inp_state->enabled = false;
|
||||
- irq_set_irq_type(inp_state->irq,
|
||||
- IRQF_TRIGGER_NONE);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (new_state)
|
||||
- gpio_fsm_enter_state(gf, new_state);
|
||||
+ gpio_fsm_go_to_state(gf, new_state);
|
||||
}
|
||||
|
||||
static irqreturn_t gpio_fsm_gpio_irq_handler(int irq, void *dev_id)
|
||||
@@ -404,7 +403,7 @@ static irqreturn_t gpio_fsm_gpio_irq_han
|
||||
if (gf->debug)
|
||||
dev_info(gf->dev, "GF_IN %d->%d -> %s\n",
|
||||
inp_state->index, inp_state->value, target->name);
|
||||
- gpio_fsm_go_to_state(gf, target);
|
||||
+ gpio_fsm_go_to_state_deferred(gf, target);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -416,12 +415,11 @@ static void gpio_fsm_timer(struct timer_
|
||||
target = gf->delay_target_state;
|
||||
if (!target)
|
||||
return;
|
||||
-
|
||||
if (gf->debug)
|
||||
dev_info(gf->dev, "GF_DELAY %d -> %s\n", gf->delay_ms,
|
||||
target->name);
|
||||
|
||||
- gpio_fsm_go_to_state(gf, target);
|
||||
+ gpio_fsm_go_to_state_deferred(gf, target);
|
||||
}
|
||||
|
||||
int gpio_fsm_parse_signals(struct gpio_fsm *gf, struct fsm_state *state,
|
||||
@@ -1119,7 +1117,7 @@ static int gpio_fsm_probe(struct platfor
|
||||
if (gf->debug)
|
||||
dev_info(gf->dev, "Start -> %s\n", gf->start_state->name);
|
||||
|
||||
- gpio_fsm_go_to_state(gf, gf->start_state);
|
||||
+ gpio_fsm_enter_state(gf, gf->start_state);
|
||||
|
||||
return devm_gpiochip_add_data(dev, &gf->gc, gf);
|
||||
}
|
63
target/linux/bcm27xx/patches-6.1/950-0842-f2fs-fix-to-avoid-NULL-pointer-dereference-in-f2fs_i.patch
Normal file
63
target/linux/bcm27xx/patches-6.1/950-0842-f2fs-fix-to-avoid-NULL-pointer-dereference-in-f2fs_i.patch
Normal file
@ -0,0 +1,63 @@
|
||||
From bf9fb25f3265605572f04e5c7836bb83ee345236 Mon Sep 17 00:00:00 2001
|
||||
From: Chao Yu <chao@kernel.org>
|
||||
Date: Fri, 30 Dec 2022 23:43:32 +0800
|
||||
Subject: [PATCH] f2fs: fix to avoid NULL pointer dereference in
|
||||
f2fs_issue_flush()
|
||||
|
||||
commit b3d83066cbebc76dbac8a5fca931f64b4c6fff34 upstream.
|
||||
|
||||
With below two cases, it will cause NULL pointer dereference when
|
||||
accessing SM_I(sbi)->fcc_info in f2fs_issue_flush().
|
||||
|
||||
a) If kthread_run() fails in f2fs_create_flush_cmd_control(), it will
|
||||
release SM_I(sbi)->fcc_info,
|
||||
|
||||
- mount -o noflush_merge /dev/vda /mnt/f2fs
|
||||
- mount -o remount,flush_merge /dev/vda /mnt/f2fs -- kthread_run() fails
|
||||
- dd if=/dev/zero of=/mnt/f2fs/file bs=4k count=1 conv=fsync
|
||||
|
||||
b) we will never allocate memory for SM_I(sbi)->fcc_info w/ below
|
||||
testcase,
|
||||
|
||||
- mount -o ro /dev/vda /mnt/f2fs
|
||||
- mount -o rw,remount /dev/vda /mnt/f2fs
|
||||
- dd if=/dev/zero of=/mnt/f2fs/file bs=4k count=1 conv=fsync
|
||||
|
||||
In order to fix this issue, let change as below:
|
||||
- fix error path handling in f2fs_create_flush_cmd_control().
|
||||
- allocate SM_I(sbi)->fcc_info even if readonly is on.
|
||||
|
||||
Signed-off-by: Chao Yu <chao@kernel.org>
|
||||
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
|
||||
---
|
||||
fs/f2fs/segment.c | 12 ++++--------
|
||||
1 file changed, 4 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/fs/f2fs/segment.c
|
||||
+++ b/fs/f2fs/segment.c
|
||||
@@ -663,9 +663,7 @@ init_thread:
|
||||
"f2fs_flush-%u:%u", MAJOR(dev), MINOR(dev));
|
||||
if (IS_ERR(fcc->f2fs_issue_flush)) {
|
||||
err = PTR_ERR(fcc->f2fs_issue_flush);
|
||||
- kfree(fcc);
|
||||
- SM_I(sbi)->fcc_info = NULL;
|
||||
- return err;
|
||||
+ fcc->f2fs_issue_flush = NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -5062,11 +5060,9 @@ int f2fs_build_segment_manager(struct f2
|
||||
|
||||
init_f2fs_rwsem(&sm_info->curseg_lock);
|
||||
|
||||
- if (!f2fs_readonly(sbi->sb)) {
|
||||
- err = f2fs_create_flush_cmd_control(sbi);
|
||||
- if (err)
|
||||
- return err;
|
||||
- }
|
||||
+ err = f2fs_create_flush_cmd_control(sbi);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
err = create_discard_cmd_control(sbi);
|
||||
if (err)
|
@ -1,4 +1,4 @@
|
||||
From b642f64d629df5515f3a01fc5b2e17c3fa7b404c Mon Sep 17 00:00:00 2001
|
||||
From e079555a4c68356e58249cfc041b28f6eb455bd5 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Wahren <wahrenst@gmx.net>
|
||||
Date: Sat, 4 May 2019 17:06:15 +0200
|
||||
Subject: [PATCH] hwrng: iproc-rng200: Add BCM2838 support
|
||||
@ -17,8 +17,8 @@ Fixes: "hwrng: iproc-rng200: Add BCM2838 support"
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/char/hw_random/Kconfig | 2 +-
|
||||
drivers/char/hw_random/iproc-rng200.c | 78 +++++++++++++++++++++++++--
|
||||
2 files changed, 76 insertions(+), 4 deletions(-)
|
||||
drivers/char/hw_random/iproc-rng200.c | 79 ++++++++++++++++++++++++++-
|
||||
2 files changed, 77 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/char/hw_random/Kconfig
|
||||
+++ b/drivers/char/hw_random/Kconfig
|
||||
@ -33,7 +33,15 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
module will be called iproc-rng200
|
||||
--- a/drivers/char/hw_random/iproc-rng200.c
|
||||
+++ b/drivers/char/hw_random/iproc-rng200.c
|
||||
@@ -21,6 +21,7 @@
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
+#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
@@ -21,6 +22,7 @@
|
||||
#define RNG_CTRL_OFFSET 0x00
|
||||
#define RNG_CTRL_RNG_RBGEN_MASK 0x00001FFF
|
||||
#define RNG_CTRL_RNG_RBGEN_ENABLE 0x00000001
|
||||
@ -41,7 +49,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
|
||||
#define RNG_SOFT_RESET_OFFSET 0x04
|
||||
#define RNG_SOFT_RESET 0x00000001
|
||||
@@ -28,16 +29,23 @@
|
||||
@@ -28,16 +30,23 @@
|
||||
#define RBG_SOFT_RESET_OFFSET 0x08
|
||||
#define RBG_SOFT_RESET 0x00000001
|
||||
|
||||
@ -65,7 +73,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
|
||||
struct iproc_rng200_dev {
|
||||
struct hwrng rng;
|
||||
@@ -158,6 +166,64 @@ static int iproc_rng200_init(struct hwrn
|
||||
@@ -158,6 +167,64 @@ static int iproc_rng200_init(struct hwrn
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -130,7 +138,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
static void iproc_rng200_cleanup(struct hwrng *rng)
|
||||
{
|
||||
struct iproc_rng200_dev *priv = to_rng_priv(rng);
|
||||
@@ -184,11 +250,17 @@ static int iproc_rng200_probe(struct pla
|
||||
@@ -184,11 +251,17 @@ static int iproc_rng200_probe(struct pla
|
||||
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
39
target/linux/bcm27xx/patches-6.1/950-0847-PCI-brcmstb-Wait-for-100ms-following-PERST-deassert.patch
Normal file
39
target/linux/bcm27xx/patches-6.1/950-0847-PCI-brcmstb-Wait-for-100ms-following-PERST-deassert.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 6f634d7efb8876e5953c30c0a613aaa5f575fe05 Mon Sep 17 00:00:00 2001
|
||||
From: Jim Quinlan <jim2101024@gmail.com>
|
||||
Date: Tue, 11 Oct 2022 14:42:07 -0400
|
||||
Subject: [PATCH] PCI: brcmstb: Wait for 100ms following PERST# deassert
|
||||
|
||||
commit 3ae140ad827b359bc4fa7c7985691c4c1e3ca8f4 upstream.
|
||||
|
||||
Be prudent and give some time for power and clocks to become stable. As
|
||||
described in the PCIe CEM specification sections 2.2 and 2.2.1; as well as
|
||||
PCIe r5.0, 6.6.1.
|
||||
|
||||
Link: https://lore.kernel.org/r/20221011184211.18128-3-jim2101024@gmail.com
|
||||
Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
|
||||
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
|
||||
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
---
|
||||
drivers/pci/controller/pcie-brcmstb.c | 11 +++++++++--
|
||||
1 file changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-brcmstb.c
|
||||
+++ b/drivers/pci/controller/pcie-brcmstb.c
|
||||
@@ -1038,8 +1038,15 @@ static int brcm_pcie_start_link(struct b
|
||||
pcie->perst_set(pcie, 0);
|
||||
|
||||
/*
|
||||
- * Give the RC/EP time to wake up, before trying to configure RC.
|
||||
- * Intermittently check status for link-up, up to a total of 100ms.
|
||||
+ * Wait for 100ms after PERST# deassertion; see PCIe CEM specification
|
||||
+ * sections 2.2, PCIe r5.0, 6.6.1.
|
||||
+ */
|
||||
+ msleep(100);
|
||||
+
|
||||
+ /*
|
||||
+ * Give the RC/EP even more time to wake up, before trying to
|
||||
+ * configure RC. Intermittently check status for link-up, up to a
|
||||
+ * total of 100ms.
|
||||
*/
|
||||
for (i = 0; i < 100 && !brcm_pcie_link_up(pcie); i += 5)
|
||||
msleep(5);
|
@ -0,0 +1,47 @@
|
||||
From cc08810f89e52337a99cc6ae5f53f08588357c5f Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Tue, 19 Sep 2023 20:31:34 +0100
|
||||
Subject: [PATCH] overlays: Add a sample hat_map
|
||||
|
||||
The HAT map is way of associating named overlays with HATs whose
|
||||
EEPROMs were programmed with the contents of the overlay.
|
||||
Unfortunately, change in the DT and kernel drivers has meant that some
|
||||
of these embedded overlays no longer function, or even don't apply.
|
||||
|
||||
The HAT map is a mapping from HAT UUIDs to overlay names. If a HAT with
|
||||
a listed UUID is detected, the embedded overlay is ignored and the
|
||||
overlay named in the mapping is loaded in its place.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
arch/arm/boot/dts/overlays/Makefile | 2 +-
|
||||
arch/arm/boot/dts/overlays/hat_map.dts | 13 +++++++++++++
|
||||
2 files changed, 14 insertions(+), 1 deletion(-)
|
||||
create mode 100644 arch/arm/boot/dts/overlays/hat_map.dts
|
||||
|
||||
--- a/arch/arm/boot/dts/overlays/Makefile
|
||||
+++ b/arch/arm/boot/dts/overlays/Makefile
|
||||
@@ -1,6 +1,6 @@
|
||||
# Overlays for the Raspberry Pi platform
|
||||
|
||||
-dtb-$(CONFIG_ARCH_BCM2835) += overlay_map.dtb
|
||||
+dtb-$(CONFIG_ARCH_BCM2835) += overlay_map.dtb hat_map.dtb
|
||||
|
||||
dtbo-$(CONFIG_ARCH_BCM2835) += \
|
||||
act-led.dtbo \
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/overlays/hat_map.dts
|
||||
@@ -0,0 +1,13 @@
|
||||
+/dts-v1/;
|
||||
+
|
||||
+/ {
|
||||
+ iqaudio-pi-codecplus {
|
||||
+ uuid = [ dc1c9594 c1ab 4c6c acda a88dc59a3c5b ];
|
||||
+ overlay = "iqaudio-codec";
|
||||
+ };
|
||||
+
|
||||
+ recalbox-rgbdual {
|
||||
+ uuid = [ 1c955808 681f 4bbc a2ef b7ea47cd388e ];
|
||||
+ overlay = "recalboxrgbdual";
|
||||
+ };
|
||||
+};
|
26
target/linux/bcm27xx/patches-6.1/950-0851-Revert-usb-phy-generic-Get-the-vbus-supply.patch
Normal file
26
target/linux/bcm27xx/patches-6.1/950-0851-Revert-usb-phy-generic-Get-the-vbus-supply.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From 406e7dc82be6ce1b81c88b418640daeef6c2be42 Mon Sep 17 00:00:00 2001
|
||||
From: Dom Cobley <popcornmix@gmail.com>
|
||||
Date: Mon, 23 May 2022 16:56:44 +0100
|
||||
Subject: [PATCH] Revert "usb: phy: generic: Get the vbus supply"
|
||||
|
||||
This reverts commit c0ea202fbc855d60bc4a0603ca52a9e80654b327.
|
||||
---
|
||||
drivers/usb/phy/phy-generic.c | 7 -------
|
||||
1 file changed, 7 deletions(-)
|
||||
|
||||
--- a/drivers/usb/phy/phy-generic.c
|
||||
+++ b/drivers/usb/phy/phy-generic.c
|
||||
@@ -265,13 +265,6 @@ int usb_phy_gen_create_phy(struct device
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
- nop->vbus_draw = devm_regulator_get_exclusive(dev, "vbus");
|
||||
- if (PTR_ERR(nop->vbus_draw) == -ENODEV)
|
||||
- nop->vbus_draw = NULL;
|
||||
- if (IS_ERR(nop->vbus_draw))
|
||||
- return dev_err_probe(dev, PTR_ERR(nop->vbus_draw),
|
||||
- "could not get vbus regulator\n");
|
||||
-
|
||||
nop->dev = dev;
|
||||
nop->phy.dev = nop->dev;
|
||||
nop->phy.label = "nop-xceiv";
|
File diff suppressed because it is too large
Load Diff
282
target/linux/bcm27xx/patches-6.1/950-0855-gpio_brcmstb-Allow-to-build-for-ARCH_BCM2835.patch
Normal file
282
target/linux/bcm27xx/patches-6.1/950-0855-gpio_brcmstb-Allow-to-build-for-ARCH_BCM2835.patch
Normal file
@ -0,0 +1,282 @@
|
||||
From fa18902ee1e53ad391a455a01be3ab2ea1c5af5f Mon Sep 17 00:00:00 2001
|
||||
From: Dom Cobley <popcornmix@gmail.com>
|
||||
Date: Fri, 21 May 2021 12:33:38 +0100
|
||||
Subject: [PATCH] gpio_brcmstb: Allow to build for ARCH_BCM2835
|
||||
|
||||
gpio-brcmstb: Report the correct bank width
|
||||
|
||||
gpio: brcmstb: Use bank address as gpiochip label
|
||||
|
||||
If the path to the device node is used as gpiochip label then
|
||||
gpio-brcmstb instances with multiple banks end up with duplicated
|
||||
names. Instead, use a combination of the driver name with the physical
|
||||
address of the bank, which is both unique and helpful for devmem
|
||||
debugging.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
|
||||
gpio: mmio: Add DIRECT mode for shared access
|
||||
|
||||
The generic MMIO GPIO library uses shadow registers for efficiency,
|
||||
but this breaks attempts by raspi-gpio to change other GPIOs in the
|
||||
same bank. Add a DIRECT mode that makes fewer assumptions about the
|
||||
existing register contents, but note that genuinely simultaneous
|
||||
accesses are likely to lose updates.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
|
||||
gpio: brcmstb: Don't always clear interrupt mask
|
||||
|
||||
If the GPIO controller is not being used as an interrupt source
|
||||
leave the interrupt mask register alone. On BCM2712 it might be used
|
||||
to generate interrupts to the VPU firmware, and on other devices it
|
||||
doesn't matter since no interrupts will be generated.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/gpio/Kconfig | 2 +-
|
||||
drivers/gpio/gpio-brcmstb.c | 14 ++--
|
||||
drivers/gpio/gpio-mmio.c | 124 ++++++++++++++++++++++++++++++++++--
|
||||
include/linux/gpio/driver.h | 1 +
|
||||
4 files changed, 131 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/gpio/Kconfig
|
||||
+++ b/drivers/gpio/Kconfig
|
||||
@@ -203,7 +203,7 @@ config GPIO_BCM_VIRT
|
||||
config GPIO_BRCMSTB
|
||||
tristate "BRCMSTB GPIO support"
|
||||
default y if (ARCH_BRCMSTB || BMIPS_GENERIC)
|
||||
- depends on OF_GPIO && (ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST)
|
||||
+ depends on OF_GPIO && (ARCH_BRCMSTB || BMIPS_GENERIC || ARCH_BCM2835 || COMPILE_TEST)
|
||||
select GPIO_GENERIC
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
--- a/drivers/gpio/gpio-brcmstb.c
|
||||
+++ b/drivers/gpio/gpio-brcmstb.c
|
||||
@@ -640,6 +640,8 @@ static int brcmstb_gpio_probe(struct pla
|
||||
#if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN)
|
||||
flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
|
||||
#endif
|
||||
+ if (of_property_read_bool(np, "brcm,gpio-direct"))
|
||||
+ flags |= BGPIOF_REG_DIRECT;
|
||||
|
||||
of_property_for_each_u32(np, "brcm,gpio-bank-widths", prop, p,
|
||||
bank_width) {
|
||||
@@ -689,7 +691,9 @@ static int brcmstb_gpio_probe(struct pla
|
||||
}
|
||||
|
||||
gc->owner = THIS_MODULE;
|
||||
- gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np);
|
||||
+ gc->label = devm_kasprintf(dev, GFP_KERNEL, "gpio-brcmstb@%zx",
|
||||
+ (size_t)res->start +
|
||||
+ GIO_BANK_OFF(bank->id, 0));
|
||||
if (!gc->label) {
|
||||
err = -ENOMEM;
|
||||
goto fail;
|
||||
@@ -698,7 +702,7 @@ static int brcmstb_gpio_probe(struct pla
|
||||
gc->of_gpio_n_cells = 2;
|
||||
gc->of_xlate = brcmstb_gpio_of_xlate;
|
||||
/* not all ngpio lines are valid, will use bank width later */
|
||||
- gc->ngpio = MAX_GPIO_PER_BANK;
|
||||
+ gc->ngpio = bank_width;
|
||||
gc->offset = bank->id * MAX_GPIO_PER_BANK;
|
||||
if (priv->parent_irq > 0)
|
||||
gc->to_irq = brcmstb_gpio_to_irq;
|
||||
@@ -707,8 +711,10 @@ static int brcmstb_gpio_probe(struct pla
|
||||
* Mask all interrupts by default, since wakeup interrupts may
|
||||
* be retained from S5 cold boot
|
||||
*/
|
||||
- need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank);
|
||||
- gc->write_reg(reg_base + GIO_MASK(bank->id), 0);
|
||||
+ if (priv->parent_irq > 0) {
|
||||
+ need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank);
|
||||
+ gc->write_reg(reg_base + GIO_MASK(bank->id), 0);
|
||||
+ }
|
||||
|
||||
err = gpiochip_add_data(gc, bank);
|
||||
if (err) {
|
||||
--- a/drivers/gpio/gpio-mmio.c
|
||||
+++ b/drivers/gpio/gpio-mmio.c
|
||||
@@ -232,6 +232,25 @@ static void bgpio_set(struct gpio_chip *
|
||||
raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
|
||||
}
|
||||
|
||||
+static void bgpio_set_direct(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
+{
|
||||
+ unsigned long mask = bgpio_line2mask(gc, gpio);
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
|
||||
+
|
||||
+ gc->bgpio_data = gc->read_reg(gc->reg_dat);
|
||||
+
|
||||
+ if (val)
|
||||
+ gc->bgpio_data |= mask;
|
||||
+ else
|
||||
+ gc->bgpio_data &= ~mask;
|
||||
+
|
||||
+ gc->write_reg(gc->reg_dat, gc->bgpio_data);
|
||||
+
|
||||
+ raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
|
||||
+}
|
||||
+
|
||||
static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
|
||||
int val)
|
||||
{
|
||||
@@ -324,6 +343,27 @@ static void bgpio_set_multiple_with_clea
|
||||
gc->write_reg(gc->reg_clr, clear_mask);
|
||||
}
|
||||
|
||||
+static void bgpio_set_multiple_direct(struct gpio_chip *gc,
|
||||
+ unsigned long *mask,
|
||||
+ unsigned long *bits)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ unsigned long set_mask, clear_mask;
|
||||
+
|
||||
+ raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
|
||||
+
|
||||
+ bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask);
|
||||
+
|
||||
+ gc->bgpio_data = gc->read_reg(gc->reg_dat);
|
||||
+
|
||||
+ gc->bgpio_data |= set_mask;
|
||||
+ gc->bgpio_data &= ~clear_mask;
|
||||
+
|
||||
+ gc->write_reg(gc->reg_dat, gc->bgpio_data);
|
||||
+
|
||||
+ raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
|
||||
+}
|
||||
+
|
||||
static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
return 0;
|
||||
@@ -361,6 +401,29 @@ static int bgpio_dir_in(struct gpio_chip
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int bgpio_dir_in_direct(struct gpio_chip *gc, unsigned int gpio)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
|
||||
+
|
||||
+ if (gc->reg_dir_in)
|
||||
+ gc->bgpio_dir = ~gc->read_reg(gc->reg_dir_in);
|
||||
+ if (gc->reg_dir_out)
|
||||
+ gc->bgpio_dir = gc->read_reg(gc->reg_dir_out);
|
||||
+
|
||||
+ gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio);
|
||||
+
|
||||
+ if (gc->reg_dir_in)
|
||||
+ gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir);
|
||||
+ if (gc->reg_dir_out)
|
||||
+ gc->write_reg(gc->reg_dir_out, gc->bgpio_dir);
|
||||
+
|
||||
+ raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
/* Return 0 if output, 1 if input */
|
||||
@@ -399,6 +462,28 @@ static void bgpio_dir_out(struct gpio_ch
|
||||
raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
|
||||
}
|
||||
|
||||
+static void bgpio_dir_out_direct(struct gpio_chip *gc, unsigned int gpio,
|
||||
+ int val)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
|
||||
+
|
||||
+ if (gc->reg_dir_in)
|
||||
+ gc->bgpio_dir = ~gc->read_reg(gc->reg_dir_in);
|
||||
+ if (gc->reg_dir_out)
|
||||
+ gc->bgpio_dir = gc->read_reg(gc->reg_dir_out);
|
||||
+
|
||||
+ gc->bgpio_dir |= bgpio_line2mask(gc, gpio);
|
||||
+
|
||||
+ if (gc->reg_dir_in)
|
||||
+ gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir);
|
||||
+ if (gc->reg_dir_out)
|
||||
+ gc->write_reg(gc->reg_dir_out, gc->bgpio_dir);
|
||||
+
|
||||
+ raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
|
||||
+}
|
||||
+
|
||||
static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio,
|
||||
int val)
|
||||
{
|
||||
@@ -415,6 +500,22 @@ static int bgpio_dir_out_val_first(struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int bgpio_dir_out_dir_first_direct(struct gpio_chip *gc,
|
||||
+ unsigned int gpio, int val)
|
||||
+{
|
||||
+ bgpio_dir_out_direct(gc, gpio, val);
|
||||
+ gc->set(gc, gpio, val);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int bgpio_dir_out_val_first_direct(struct gpio_chip *gc,
|
||||
+ unsigned int gpio, int val)
|
||||
+{
|
||||
+ gc->set(gc, gpio, val);
|
||||
+ bgpio_dir_out_direct(gc, gpio, val);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int bgpio_setup_accessors(struct device *dev,
|
||||
struct gpio_chip *gc,
|
||||
bool byte_be)
|
||||
@@ -508,6 +609,9 @@ static int bgpio_setup_io(struct gpio_ch
|
||||
} else if (flags & BGPIOF_NO_OUTPUT) {
|
||||
gc->set = bgpio_set_none;
|
||||
gc->set_multiple = NULL;
|
||||
+ } else if (flags & BGPIOF_REG_DIRECT) {
|
||||
+ gc->set = bgpio_set_direct;
|
||||
+ gc->set_multiple = bgpio_set_multiple_direct;
|
||||
} else {
|
||||
gc->set = bgpio_set;
|
||||
gc->set_multiple = bgpio_set_multiple;
|
||||
@@ -544,11 +648,21 @@ static int bgpio_setup_direction(struct
|
||||
if (dirout || dirin) {
|
||||
gc->reg_dir_out = dirout;
|
||||
gc->reg_dir_in = dirin;
|
||||
- if (flags & BGPIOF_NO_SET_ON_INPUT)
|
||||
- gc->direction_output = bgpio_dir_out_dir_first;
|
||||
- else
|
||||
- gc->direction_output = bgpio_dir_out_val_first;
|
||||
- gc->direction_input = bgpio_dir_in;
|
||||
+ if (flags & BGPIOF_REG_DIRECT) {
|
||||
+ if (flags & BGPIOF_NO_SET_ON_INPUT)
|
||||
+ gc->direction_output =
|
||||
+ bgpio_dir_out_dir_first_direct;
|
||||
+ else
|
||||
+ gc->direction_output =
|
||||
+ bgpio_dir_out_val_first_direct;
|
||||
+ gc->direction_input = bgpio_dir_in_direct;
|
||||
+ } else {
|
||||
+ if (flags & BGPIOF_NO_SET_ON_INPUT)
|
||||
+ gc->direction_output = bgpio_dir_out_dir_first;
|
||||
+ else
|
||||
+ gc->direction_output = bgpio_dir_out_val_first;
|
||||
+ gc->direction_input = bgpio_dir_in;
|
||||
+ }
|
||||
gc->get_direction = bgpio_get_dir;
|
||||
} else {
|
||||
if (flags & BGPIOF_NO_OUTPUT)
|
||||
--- a/include/linux/gpio/driver.h
|
||||
+++ b/include/linux/gpio/driver.h
|
||||
@@ -690,6 +690,7 @@ int bgpio_init(struct gpio_chip *gc, str
|
||||
#define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */
|
||||
#define BGPIOF_NO_OUTPUT BIT(5) /* only input */
|
||||
#define BGPIOF_NO_SET_ON_INPUT BIT(6)
|
||||
+#define BGPIOF_REG_DIRECT BIT(7) /* ignore shadow registers */
|
||||
|
||||
int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
|
||||
irq_hw_number_t hwirq);
|
@ -0,0 +1,20 @@
|
||||
From 22ae3b2ee3293278e647877b269a5aebad3f077d Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Thu, 27 May 2021 11:46:30 +0100
|
||||
Subject: [PATCH] Allow RESET_BRCMSTB on ARCH_BCM2835
|
||||
|
||||
---
|
||||
drivers/reset/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/reset/Kconfig
|
||||
+++ b/drivers/reset/Kconfig
|
||||
@@ -51,7 +51,7 @@ config RESET_BERLIN
|
||||
|
||||
config RESET_BRCMSTB
|
||||
tristate "Broadcom STB reset controller"
|
||||
- depends on ARCH_BRCMSTB || COMPILE_TEST
|
||||
+ depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
|
||||
default ARCH_BRCMSTB
|
||||
help
|
||||
This enables the reset controller driver for Broadcom STB SoCs using
|
1324
target/linux/bcm27xx/patches-6.1/950-0857-pinctrl-bcm2712-pinctrl-pinconf-driver.patch
Normal file
1324
target/linux/bcm27xx/patches-6.1/950-0857-pinctrl-bcm2712-pinctrl-pinconf-driver.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,498 @@
|
||||
From b627647c4500d39cb026924b608841fdf4d4d7e9 Mon Sep 17 00:00:00 2001
|
||||
From: Ulf Hansson <ulf.hansson@linaro.org>
|
||||
Date: Thu, 29 Oct 2020 09:57:16 +0800
|
||||
Subject: [PATCH] mmc: brcmstb: add support for BCM2712
|
||||
|
||||
BCM2712 has an SD Express capable SDHCI implementation and uses
|
||||
the SDIO CFG register block present on other STB chips.
|
||||
|
||||
Add plumbing for SD Express handover and BCM2712-specific functions.
|
||||
|
||||
Due to the common bus infrastructure between BCM2711 and BCM2712,
|
||||
the driver also needs to implement 32-bit IO accessors.
|
||||
|
||||
mmc: brcmstb: override card presence if broken-cd is set
|
||||
|
||||
Not just if the card is declared as nonremovable.
|
||||
|
||||
sdhci: brcmstb: align SD express switchover with SD spec v8.00
|
||||
|
||||
Part 1 of the Physical specification, figure 3-24, details the switch
|
||||
sequence for cards initially probed as SD. Add a missing check for DAT2
|
||||
level after switching VDD2 on.
|
||||
|
||||
sdhci: brcmstb: clean up SD Express probe and error handling
|
||||
|
||||
Refactor to avoid spurious error messages in dmesg if the requisite SD
|
||||
Express DT nodes aren't present.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
|
||||
mmc: sdhci-brcmstb: only use the delay line PHY for tuneable speeds
|
||||
|
||||
The MMC core has a 200MHz core clock which allows the use of DDR50 and
|
||||
below without incremental phase tuning. SDR50/SDR104 and the EMMC HS200
|
||||
speeds require tuning.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
---
|
||||
drivers/mmc/host/Kconfig | 2 +
|
||||
drivers/mmc/host/sdhci-brcmstb.c | 356 +++++++++++++++++++++++++++++++
|
||||
2 files changed, 358 insertions(+)
|
||||
|
||||
--- a/drivers/mmc/host/Kconfig
|
||||
+++ b/drivers/mmc/host/Kconfig
|
||||
@@ -1082,7 +1082,9 @@ config MMC_SDHCI_BRCMSTB
|
||||
tristate "Broadcom SDIO/SD/MMC support"
|
||||
depends on ARCH_BRCMSTB || BMIPS_GENERIC
|
||||
depends on MMC_SDHCI_PLTFM
|
||||
+ select MMC_SDHCI_IO_ACCESSORS
|
||||
select MMC_CQHCI
|
||||
+ select OF_DYNAMIC
|
||||
default y
|
||||
help
|
||||
This selects support for the SDIO/SD/MMC Host Controller on
|
||||
--- a/drivers/mmc/host/sdhci-brcmstb.c
|
||||
+++ b/drivers/mmc/host/sdhci-brcmstb.c
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
+#include <linux/pinctrl/consumer.h>
|
||||
+#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "sdhci-cqhci.h"
|
||||
#include "sdhci-pltfm.h"
|
||||
@@ -26,18 +28,43 @@
|
||||
|
||||
#define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0)
|
||||
#define BRCMSTB_PRIV_FLAGS_GATE_CLOCK BIT(1)
|
||||
+#define BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS BIT(2)
|
||||
|
||||
#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
|
||||
|
||||
+#define SDIO_CFG_CTRL 0x0
|
||||
+#define SDIO_CFG_CTRL_SDCD_N_TEST_EN BIT(31)
|
||||
+#define SDIO_CFG_CTRL_SDCD_N_TEST_LEV BIT(30)
|
||||
+
|
||||
+#define SDIO_CFG_SD_PIN_SEL 0x44
|
||||
+#define SDIO_CFG_SD_PIN_SEL_MASK 0x3
|
||||
+#define SDIO_CFG_SD_PIN_SEL_CARD BIT(1)
|
||||
+
|
||||
+#define SDIO_CFG_MAX_50MHZ_MODE 0x1ac
|
||||
+#define SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE BIT(31)
|
||||
+#define SDIO_CFG_MAX_50MHZ_MODE_ENABLE BIT(0)
|
||||
+
|
||||
struct sdhci_brcmstb_priv {
|
||||
void __iomem *cfg_regs;
|
||||
unsigned int flags;
|
||||
struct clk *base_clk;
|
||||
u32 base_freq_hz;
|
||||
+ u32 shadow_cmd;
|
||||
+ u32 shadow_blk;
|
||||
+ bool is_cmd_shadowed;
|
||||
+ bool is_blk_shadowed;
|
||||
+ struct regulator *sde_1v8;
|
||||
+ struct device_node *sde_pcie;
|
||||
+ void *__iomem sde_ioaddr;
|
||||
+ void *__iomem sde_ioaddr2;
|
||||
+ struct pinctrl *pinctrl;
|
||||
+ struct pinctrl_state *pins_default;
|
||||
+ struct pinctrl_state *pins_sdex;
|
||||
};
|
||||
|
||||
struct brcmstb_match_priv {
|
||||
void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
|
||||
+ void (*cfginit)(struct sdhci_host *host);
|
||||
struct sdhci_ops *ops;
|
||||
const unsigned int flags;
|
||||
};
|
||||
@@ -94,6 +121,124 @@ static void sdhci_brcmstb_set_clock(stru
|
||||
sdhci_enable_clk(host, clk);
|
||||
}
|
||||
|
||||
+#define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18)
|
||||
+
|
||||
+static inline u32 sdhci_brcmstb_32only_readl(struct sdhci_host *host, int reg)
|
||||
+{
|
||||
+ u32 val = readl(host->ioaddr + reg);
|
||||
+
|
||||
+ pr_debug("%s: readl [0x%02x] 0x%08x\n",
|
||||
+ mmc_hostname(host->mmc), reg, val);
|
||||
+ return val;
|
||||
+}
|
||||
+
|
||||
+static u16 sdhci_brcmstb_32only_readw(struct sdhci_host *host, int reg)
|
||||
+{
|
||||
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
+ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
|
||||
+ u32 val;
|
||||
+ u16 word;
|
||||
+
|
||||
+ if ((reg == SDHCI_TRANSFER_MODE) && brcmstb_priv->is_cmd_shadowed) {
|
||||
+ /* Get the saved transfer mode */
|
||||
+ val = brcmstb_priv->shadow_cmd;
|
||||
+ } else if ((reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) &&
|
||||
+ brcmstb_priv->is_blk_shadowed) {
|
||||
+ /* Get the saved block info */
|
||||
+ val = brcmstb_priv->shadow_blk;
|
||||
+ } else {
|
||||
+ val = sdhci_brcmstb_32only_readl(host, (reg & ~3));
|
||||
+ }
|
||||
+ word = val >> REG_OFFSET_IN_BITS(reg) & 0xffff;
|
||||
+ return word;
|
||||
+}
|
||||
+
|
||||
+static u8 sdhci_brcmstb_32only_readb(struct sdhci_host *host, int reg)
|
||||
+{
|
||||
+ u32 val = sdhci_brcmstb_32only_readl(host, (reg & ~3));
|
||||
+ u8 byte = val >> REG_OFFSET_IN_BITS(reg) & 0xff;
|
||||
+ return byte;
|
||||
+}
|
||||
+
|
||||
+static inline void sdhci_brcmstb_32only_writel(struct sdhci_host *host, u32 val, int reg)
|
||||
+{
|
||||
+ pr_debug("%s: writel [0x%02x] 0x%08x\n",
|
||||
+ mmc_hostname(host->mmc), reg, val);
|
||||
+
|
||||
+ writel(val, host->ioaddr + reg);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * BCM2712 unfortunately carries with it a perennial bug with the SD controller
|
||||
+ * register interface present on previous chips (2711/2709/2708). Accesses must
|
||||
+ * be dword-sized and a read-modify-write cycle to the 32-bit registers
|
||||
+ * containing the COMMAND, TRANSFER_MODE, BLOCK_SIZE and BLOCK_COUNT registers
|
||||
+ * tramples the upper/lower 16 bits of data written. BCM2712 does not seem to
|
||||
+ * need the extreme delay between each write as on previous chips, just the
|
||||
+ * serialisation of writes to these registers in a single 32-bit operation.
|
||||
+ */
|
||||
+static void sdhci_brcmstb_32only_writew(struct sdhci_host *host, u16 val, int reg)
|
||||
+{
|
||||
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
+ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
|
||||
+ u32 word_shift = REG_OFFSET_IN_BITS(reg);
|
||||
+ u32 mask = 0xffff << word_shift;
|
||||
+ u32 oldval, newval;
|
||||
+
|
||||
+ if (reg == SDHCI_COMMAND) {
|
||||
+ /* Write the block now as we are issuing a command */
|
||||
+ if (brcmstb_priv->is_blk_shadowed) {
|
||||
+ sdhci_brcmstb_32only_writel(host, brcmstb_priv->shadow_blk,
|
||||
+ SDHCI_BLOCK_SIZE);
|
||||
+ brcmstb_priv->is_blk_shadowed = false;
|
||||
+ }
|
||||
+ oldval = brcmstb_priv->shadow_cmd;
|
||||
+ brcmstb_priv->is_cmd_shadowed = false;
|
||||
+ } else if ((reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) &&
|
||||
+ brcmstb_priv->is_blk_shadowed) {
|
||||
+ /* Block size and count are stored in shadow reg */
|
||||
+ oldval = brcmstb_priv->shadow_blk;
|
||||
+ } else {
|
||||
+ /* Read reg, all other registers are not shadowed */
|
||||
+ oldval = sdhci_brcmstb_32only_readl(host, (reg & ~3));
|
||||
+ }
|
||||
+ newval = (oldval & ~mask) | (val << word_shift);
|
||||
+
|
||||
+ if (reg == SDHCI_TRANSFER_MODE) {
|
||||
+ /* Save the transfer mode until the command is issued */
|
||||
+ brcmstb_priv->shadow_cmd = newval;
|
||||
+ brcmstb_priv->is_cmd_shadowed = true;
|
||||
+ } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) {
|
||||
+ /* Save the block info until the command is issued */
|
||||
+ brcmstb_priv->shadow_blk = newval;
|
||||
+ brcmstb_priv->is_blk_shadowed = true;
|
||||
+ } else {
|
||||
+ /* Command or other regular 32-bit write */
|
||||
+ sdhci_brcmstb_32only_writel(host, newval, reg & ~3);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void sdhci_brcmstb_32only_writeb(struct sdhci_host *host, u8 val, int reg)
|
||||
+{
|
||||
+ u32 oldval = sdhci_brcmstb_32only_readl(host, (reg & ~3));
|
||||
+ u32 byte_shift = REG_OFFSET_IN_BITS(reg);
|
||||
+ u32 mask = 0xff << byte_shift;
|
||||
+ u32 newval = (oldval & ~mask) | (val << byte_shift);
|
||||
+
|
||||
+ sdhci_brcmstb_32only_writel(host, newval, reg & ~3);
|
||||
+}
|
||||
+
|
||||
+static void sdhci_brcmstb_set_power(struct sdhci_host *host, unsigned char mode,
|
||||
+ unsigned short vdd)
|
||||
+{
|
||||
+ if (!IS_ERR(host->mmc->supply.vmmc)) {
|
||||
+ struct mmc_host *mmc = host->mmc;
|
||||
+
|
||||
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
|
||||
+ }
|
||||
+ sdhci_set_power_noreg(host, mode, vdd);
|
||||
+}
|
||||
+
|
||||
static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host,
|
||||
unsigned int timing)
|
||||
{
|
||||
@@ -123,6 +268,146 @@ static void sdhci_brcmstb_set_uhs_signal
|
||||
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
|
||||
}
|
||||
|
||||
+static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host)
|
||||
+{
|
||||
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
+ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
|
||||
+ bool want_dll = false;
|
||||
+ u32 uhs_mask = (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104);
|
||||
+ u32 hsemmc_mask = (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS200_1_2V_SDR |
|
||||
+ MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V);
|
||||
+ u32 reg;
|
||||
+
|
||||
+ if (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)) {
|
||||
+ if((host->mmc->caps & uhs_mask) || (host->mmc->caps2 & hsemmc_mask))
|
||||
+ want_dll = true;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * If we want a speed that requires tuning,
|
||||
+ * then select the delay line PHY as the clock source.
|
||||
+ */
|
||||
+ if (want_dll) {
|
||||
+ reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
|
||||
+ reg &= ~SDIO_CFG_MAX_50MHZ_MODE_ENABLE;
|
||||
+ reg |= SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE;
|
||||
+ writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE);
|
||||
+ }
|
||||
+
|
||||
+ if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) ||
|
||||
+ (host->mmc->caps & MMC_CAP_NEEDS_POLL)) {
|
||||
+ /* Force presence */
|
||||
+ reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
|
||||
+ reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV;
|
||||
+ reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN;
|
||||
+ writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CTRL);
|
||||
+ } else {
|
||||
+ /* Enable card detection line */
|
||||
+ reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
|
||||
+ reg &= ~SDIO_CFG_SD_PIN_SEL_MASK;
|
||||
+ reg |= SDIO_CFG_SD_PIN_SEL_CARD;
|
||||
+ writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int bcm2712_init_sd_express(struct sdhci_host *host, struct mmc_ios *ios)
|
||||
+{
|
||||
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
+ struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host);
|
||||
+ struct device *dev = host->mmc->parent;
|
||||
+ u32 ctrl_val;
|
||||
+ u32 present_state;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!brcmstb_priv->sde_ioaddr || !brcmstb_priv->sde_ioaddr2)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!brcmstb_priv->pinctrl)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Turn off the SD clock first */
|
||||
+ sdhci_set_clock(host, 0);
|
||||
+
|
||||
+ /* Disable SD DAT0-3 pulls */
|
||||
+ pinctrl_select_state(brcmstb_priv->pinctrl, brcmstb_priv->pins_sdex);
|
||||
+
|
||||
+ ctrl_val = readl(brcmstb_priv->sde_ioaddr);
|
||||
+ dev_dbg(dev, "ctrl_val 1 %08x\n", ctrl_val);
|
||||
+
|
||||
+ /* Tri-state the SD pins */
|
||||
+ ctrl_val |= 0x1ff8;
|
||||
+ writel(ctrl_val, brcmstb_priv->sde_ioaddr);
|
||||
+ dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr));
|
||||
+ /* Let voltages settle */
|
||||
+ udelay(100);
|
||||
+
|
||||
+ /* Enable the PCIe sideband pins */
|
||||
+ ctrl_val &= ~0x6000;
|
||||
+ writel(ctrl_val, brcmstb_priv->sde_ioaddr);
|
||||
+ dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr));
|
||||
+ /* Let voltages settle */
|
||||
+ udelay(100);
|
||||
+
|
||||
+ /* Turn on the 1v8 VDD2 regulator */
|
||||
+ ret = regulator_enable(brcmstb_priv->sde_1v8);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Wait for Tpvcrl */
|
||||
+ msleep(1);
|
||||
+
|
||||
+ /* Sample DAT2 (CLKREQ#) - if low, card is in PCIe mode */
|
||||
+ present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
|
||||
+ present_state = (present_state & SDHCI_DATA_LVL_MASK) >> SDHCI_DATA_LVL_SHIFT;
|
||||
+ dev_dbg(dev, "state = 0x%08x\n", present_state);
|
||||
+
|
||||
+ if (present_state & BIT(2)) {
|
||||
+ dev_err(dev, "DAT2 still high, abandoning SDex switch\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /* Turn on the LCPLL PTEST mux */
|
||||
+ ctrl_val = readl(brcmstb_priv->sde_ioaddr2 + 20); // misc5
|
||||
+ ctrl_val &= ~(0x7 << 7);
|
||||
+ ctrl_val |= 3 << 7;
|
||||
+ writel(ctrl_val, brcmstb_priv->sde_ioaddr2 + 20);
|
||||
+ dev_dbg(dev, "misc 5->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2 + 20));
|
||||
+
|
||||
+ /* PTEST diff driver enable */
|
||||
+ ctrl_val = readl(brcmstb_priv->sde_ioaddr2);
|
||||
+ ctrl_val |= BIT(21);
|
||||
+ writel(ctrl_val, brcmstb_priv->sde_ioaddr2);
|
||||
+
|
||||
+ dev_dbg(dev, "misc 0->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2));
|
||||
+
|
||||
+ /* Wait for more than the minimum Tpvpgl time */
|
||||
+ msleep(100);
|
||||
+
|
||||
+ if (brcmstb_priv->sde_pcie) {
|
||||
+ struct of_changeset changeset;
|
||||
+ static struct property okay_property = {
|
||||
+ .name = "status",
|
||||
+ .value = "okay",
|
||||
+ .length = 5,
|
||||
+ };
|
||||
+
|
||||
+ /* Enable the pcie controller */
|
||||
+ of_changeset_init(&changeset);
|
||||
+ ret = of_changeset_update_property(&changeset,
|
||||
+ brcmstb_priv->sde_pcie,
|
||||
+ &okay_property);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "%s: failed to update property - %d\n", __func__,
|
||||
+ ret);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ ret = of_changeset_apply(&changeset);
|
||||
+ }
|
||||
+
|
||||
+ dev_dbg(dev, "%s -> %d\n", __func__, ret);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc)
|
||||
{
|
||||
sdhci_dumpregs(mmc_priv(mmc));
|
||||
@@ -155,6 +440,21 @@ static struct sdhci_ops sdhci_brcmstb_op
|
||||
.set_uhs_signaling = sdhci_set_uhs_signaling,
|
||||
};
|
||||
|
||||
+static struct sdhci_ops sdhci_brcmstb_ops_2712 = {
|
||||
+ .read_l = sdhci_brcmstb_32only_readl,
|
||||
+ .read_w = sdhci_brcmstb_32only_readw,
|
||||
+ .read_b = sdhci_brcmstb_32only_readb,
|
||||
+ .write_l = sdhci_brcmstb_32only_writel,
|
||||
+ .write_w = sdhci_brcmstb_32only_writew,
|
||||
+ .write_b = sdhci_brcmstb_32only_writeb,
|
||||
+ .set_clock = sdhci_set_clock,
|
||||
+ .set_power = sdhci_brcmstb_set_power,
|
||||
+ .set_bus_width = sdhci_set_bus_width,
|
||||
+ .reset = sdhci_reset,
|
||||
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
|
||||
+ .init_sd_express = bcm2712_init_sd_express,
|
||||
+};
|
||||
+
|
||||
static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
|
||||
.set_clock = sdhci_brcmstb_set_clock,
|
||||
.set_bus_width = sdhci_set_bus_width,
|
||||
@@ -179,10 +479,16 @@ static const struct brcmstb_match_priv m
|
||||
.ops = &sdhci_brcmstb_ops_7216,
|
||||
};
|
||||
|
||||
+static const struct brcmstb_match_priv match_priv_2712 = {
|
||||
+ .cfginit = sdhci_brcmstb_cfginit_2712,
|
||||
+ .ops = &sdhci_brcmstb_ops_2712,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id sdhci_brcm_of_match[] = {
|
||||
{ .compatible = "brcm,bcm7425-sdhci", .data = &match_priv_7425 },
|
||||
{ .compatible = "brcm,bcm7445-sdhci", .data = &match_priv_7445 },
|
||||
{ .compatible = "brcm,bcm7216-sdhci", .data = &match_priv_7216 },
|
||||
+ { .compatible = "brcm,bcm2712-sdhci", .data = &match_priv_2712 },
|
||||
{},
|
||||
};
|
||||
|
||||
@@ -256,6 +562,7 @@ static int sdhci_brcmstb_probe(struct pl
|
||||
u32 actual_clock_mhz;
|
||||
struct sdhci_host *host;
|
||||
struct resource *iomem;
|
||||
+ bool no_pinctrl = false;
|
||||
struct clk *clk;
|
||||
struct clk *base_clk = NULL;
|
||||
int res;
|
||||
@@ -290,6 +597,11 @@ static int sdhci_brcmstb_probe(struct pl
|
||||
match_priv->ops->irq = sdhci_brcmstb_cqhci_irq;
|
||||
}
|
||||
|
||||
+ priv->sde_pcie = of_parse_phandle(pdev->dev.of_node,
|
||||
+ "sde-pcie", 0);
|
||||
+ if (priv->sde_pcie)
|
||||
+ priv->flags |= BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS;
|
||||
+
|
||||
/* Map in the non-standard CFG registers */
|
||||
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
priv->cfg_regs = devm_ioremap_resource(&pdev->dev, iomem);
|
||||
@@ -303,6 +615,43 @@ static int sdhci_brcmstb_probe(struct pl
|
||||
if (res)
|
||||
goto err;
|
||||
|
||||
+ priv->sde_1v8 = devm_regulator_get_optional(&pdev->dev, "sde-1v8");
|
||||
+ if (IS_ERR(priv->sde_1v8))
|
||||
+ priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS;
|
||||
+
|
||||
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 2);
|
||||
+ if (iomem) {
|
||||
+ priv->sde_ioaddr = devm_ioremap_resource(&pdev->dev, iomem);
|
||||
+ if (IS_ERR(priv->sde_ioaddr))
|
||||
+ priv->sde_ioaddr = NULL;
|
||||
+ }
|
||||
+
|
||||
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 3);
|
||||
+ if (iomem) {
|
||||
+ priv->sde_ioaddr2 = devm_ioremap_resource(&pdev->dev, iomem);
|
||||
+ if (IS_ERR(priv->sde_ioaddr2))
|
||||
+ priv->sde_ioaddr = NULL;
|
||||
+ }
|
||||
+
|
||||
+ priv->pinctrl = devm_pinctrl_get(&pdev->dev);
|
||||
+ if (IS_ERR(priv->pinctrl)) {
|
||||
+ no_pinctrl = true;
|
||||
+ }
|
||||
+ priv->pins_default = pinctrl_lookup_state(priv->pinctrl, "default");
|
||||
+ if (IS_ERR(priv->pins_default)) {
|
||||
+ dev_dbg(&pdev->dev, "No pinctrl default state\n");
|
||||
+ no_pinctrl = true;
|
||||
+ }
|
||||
+ priv->pins_sdex = pinctrl_lookup_state(priv->pinctrl, "sd-express");
|
||||
+ if (IS_ERR(priv->pins_sdex)) {
|
||||
+ dev_dbg(&pdev->dev, "No pinctrl sd-express state\n");
|
||||
+ no_pinctrl = true;
|
||||
+ }
|
||||
+ if (no_pinctrl || !priv->sde_ioaddr || !priv->sde_ioaddr2) {
|
||||
+ priv->pinctrl = NULL;
|
||||
+ priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Automatic clock gating does not work for SD cards that may
|
||||
* voltage switch so only enable it for non-removable devices.
|
||||
@@ -319,6 +668,13 @@ static int sdhci_brcmstb_probe(struct pl
|
||||
(host->mmc->caps2 & MMC_CAP2_HS400_ES))
|
||||
host->mmc_host_ops.hs400_enhanced_strobe = match_priv->hs400es;
|
||||
|
||||
+ if (host->ops->init_sd_express &&
|
||||
+ (priv->flags & BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS))
|
||||
+ host->mmc->caps2 |= MMC_CAP2_SD_EXP;
|
||||
+
|
||||
+ if(match_priv->cfginit)
|
||||
+ match_priv->cfginit(host);
|
||||
+
|
||||
/*
|
||||
* Supply the existing CAPS, but clear the UHS modes. This
|
||||
* will allow these modes to be specified by device tree
|
@ -0,0 +1,90 @@
|
||||
From 9564939f1a92e5f9807461539de28c50e5bee440 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Tue, 6 Jul 2021 09:45:36 +0100
|
||||
Subject: [PATCH] sdhci: Add SD Express hook
|
||||
|
||||
sdhci: remove PYA0_INTR_BUG quirk. Add quirks to disable some of the higher SDR speeds at 1.8v.
|
||||
---
|
||||
drivers/mmc/host/sdhci-of-dwcmshc.c | 5 ++++-
|
||||
drivers/mmc/host/sdhci.c | 19 +++++++++++++++++++
|
||||
drivers/mmc/host/sdhci.h | 6 ++++++
|
||||
3 files changed, 29 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
@@ -363,7 +363,10 @@ static const struct sdhci_pltfm_data sdh
|
||||
.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
|
||||
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
|
||||
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
|
||||
- SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
|
||||
+ SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN |
|
||||
+ SDHCI_QUIRK2_NO_SDR50 |
|
||||
+ SDHCI_QUIRK2_NO_SDR104 |
|
||||
+ SDHCI_QUIRK2_NO_SDR25,
|
||||
};
|
||||
|
||||
static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
|
||||
--- a/drivers/mmc/host/sdhci.c
|
||||
+++ b/drivers/mmc/host/sdhci.c
|
||||
@@ -3071,6 +3071,15 @@ static void sdhci_card_event(struct mmc_
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
}
|
||||
|
||||
+static int sdhci_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
+{
|
||||
+ struct sdhci_host *host = mmc_priv(mmc);
|
||||
+
|
||||
+ if (!host->ops->init_sd_express)
|
||||
+ return -EOPNOTSUPP;
|
||||
+ return host->ops->init_sd_express(host, ios);
|
||||
+}
|
||||
+
|
||||
static const struct mmc_host_ops sdhci_ops = {
|
||||
.request = sdhci_request,
|
||||
.post_req = sdhci_post_req,
|
||||
@@ -3086,6 +3095,7 @@ static const struct mmc_host_ops sdhci_o
|
||||
.execute_tuning = sdhci_execute_tuning,
|
||||
.card_event = sdhci_card_event,
|
||||
.card_busy = sdhci_card_busy,
|
||||
+ .init_sd_express = sdhci_init_sd_express,
|
||||
};
|
||||
|
||||
/*****************************************************************************\
|
||||
@@ -4605,6 +4615,15 @@ int sdhci_setup_host(struct sdhci_host *
|
||||
!(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50))
|
||||
mmc->caps |= MMC_CAP_UHS_DDR50;
|
||||
|
||||
+ if (host->quirks2 & SDHCI_QUIRK2_NO_SDR25)
|
||||
+ mmc->caps &= ~MMC_CAP_UHS_SDR25;
|
||||
+
|
||||
+ if (host->quirks2 & SDHCI_QUIRK2_NO_SDR50)
|
||||
+ mmc->caps &= ~MMC_CAP_UHS_SDR50;
|
||||
+
|
||||
+ if (host->quirks2 & SDHCI_QUIRK2_NO_SDR104)
|
||||
+ mmc->caps &= ~MMC_CAP_UHS_SDR104;
|
||||
+
|
||||
/* Does the host need tuning for SDR50? */
|
||||
if (host->caps1 & SDHCI_USE_SDR50_TUNING)
|
||||
host->flags |= SDHCI_SDR50_NEEDS_TUNING;
|
||||
--- a/drivers/mmc/host/sdhci.h
|
||||
+++ b/drivers/mmc/host/sdhci.h
|
||||
@@ -481,6 +481,11 @@ struct sdhci_host {
|
||||
/* Issue CMD and DATA reset together */
|
||||
#define SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER (1<<19)
|
||||
|
||||
+/* Quirks to ignore a speed if a that speed is unreliable */
|
||||
+#define SDHCI_QUIRK2_NO_SDR25 (1<<19)
|
||||
+#define SDHCI_QUIRK2_NO_SDR50 (1<<20)
|
||||
+#define SDHCI_QUIRK2_NO_SDR104 (1<<21)
|
||||
+
|
||||
int irq; /* Device IRQ */
|
||||
void __iomem *ioaddr; /* Mapped address */
|
||||
phys_addr_t mapbase; /* physical address base */
|
||||
@@ -663,6 +668,7 @@ struct sdhci_ops {
|
||||
void (*request_done)(struct sdhci_host *host,
|
||||
struct mmc_request *mrq);
|
||||
void (*dump_vendor_regs)(struct sdhci_host *host);
|
||||
+ int (*init_sd_express)(struct sdhci_host *host, struct mmc_ios *ios);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
|
3788
target/linux/bcm27xx/patches-6.1/950-0861-Add-new-pispbe-driver-though-not-yet-the-Makesfiles-.patch
Normal file
3788
target/linux/bcm27xx/patches-6.1/950-0861-Add-new-pispbe-driver-though-not-yet-the-Makesfiles-.patch
Normal file
File diff suppressed because it is too large
Load Diff
386
target/linux/bcm27xx/patches-6.1/950-0862-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch
Normal file
386
target/linux/bcm27xx/patches-6.1/950-0862-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch
Normal file
@ -0,0 +1,386 @@
|
||||
From 89b748416358e4e04765b9a4f20e1c3d256b9d9e Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Wed, 28 Jul 2021 11:13:39 +0100
|
||||
Subject: [PATCH] irqchip: irq-bcm2712-mip: Support for 2712's MIP
|
||||
|
||||
irqchip: irq-bcm2712-mip: specify bitmap search size as ilog2(N) not N
|
||||
|
||||
Freeing also has the same interface.
|
||||
|
||||
irqchip: irq-bcm2712-mip: Fix build warnings
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
|
||||
irqchip: bcm2712-mip: add a quick hack to optionally shift MSI vectors
|
||||
|
||||
There are two MIP peripherals in bcm2712, the first gets a first-class
|
||||
treatment where 64 consecutive GIC SPIs are assigned to all 64 output
|
||||
vectors. The second gets an agglomeration of 17 GIC SPIs, but only 8 of
|
||||
these are consecutive starting at the 8th output vector.
|
||||
|
||||
For now, allow the use of this smaller contiguous range within a larger
|
||||
whole.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
---
|
||||
drivers/irqchip/Kconfig | 8 +
|
||||
drivers/irqchip/Makefile | 1 +
|
||||
drivers/irqchip/irq-bcm2712-mip.c | 325 ++++++++++++++++++++++++++++++
|
||||
3 files changed, 334 insertions(+)
|
||||
create mode 100644 drivers/irqchip/irq-bcm2712-mip.c
|
||||
|
||||
--- a/drivers/irqchip/Kconfig
|
||||
+++ b/drivers/irqchip/Kconfig
|
||||
@@ -109,6 +109,14 @@ config I8259
|
||||
bool
|
||||
select IRQ_DOMAIN
|
||||
|
||||
+config BCM2712_MIP
|
||||
+ bool "Broadcom 2712 MSI-X Interrupt Peripheral support"
|
||||
+ depends on ARM_GIC
|
||||
+ select GENERIC_IRQ_CHIP
|
||||
+ select IRQ_DOMAIN
|
||||
+ help
|
||||
+ Enable support for the Broadcom BCM2712 MSI-X target peripheral.
|
||||
+
|
||||
config BCM6345_L1_IRQ
|
||||
bool
|
||||
select GENERIC_IRQ_CHIP
|
||||
--- a/drivers/irqchip/Makefile
|
||||
+++ b/drivers/irqchip/Makefile
|
||||
@@ -63,6 +63,7 @@ obj-$(CONFIG_XTENSA_MX) += irq-xtensa-
|
||||
obj-$(CONFIG_XILINX_INTC) += irq-xilinx-intc.o
|
||||
obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
|
||||
obj-$(CONFIG_SOC_VF610) += irq-vf610-mscm-ir.o
|
||||
+obj-$(CONFIG_BCM2712_MIP) += irq-bcm2712-mip.o
|
||||
obj-$(CONFIG_BCM6345_L1_IRQ) += irq-bcm6345-l1.o
|
||||
obj-$(CONFIG_BCM7038_L1_IRQ) += irq-bcm7038-l1.o
|
||||
obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/irqchip/irq-bcm2712-mip.c
|
||||
@@ -0,0 +1,325 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (C) 2021 Raspberry Pi Ltd., All Rights Reserved.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/pci.h>
|
||||
+#include <linux/msi.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/of_irq.h>
|
||||
+#include <linux/of_pci.h>
|
||||
+
|
||||
+#include <linux/irqchip.h>
|
||||
+
|
||||
+#define MIP_INT_RAISED 0x00
|
||||
+#define MIP_INT_CLEARED 0x10
|
||||
+#define MIP_INT_CFGL_HOST 0x20
|
||||
+#define MIP_INT_CFGH_HOST 0x30
|
||||
+#define MIP_INT_MASKL_HOST 0x40
|
||||
+#define MIP_INT_MASKH_HOST 0x50
|
||||
+#define MIP_INT_MASKL_VPU 0x60
|
||||
+#define MIP_INT_MASKH_VPU 0x70
|
||||
+#define MIP_INT_STATUSL_HOST 0x80
|
||||
+#define MIP_INT_STATUSH_HOST 0x90
|
||||
+#define MIP_INT_STATUSL_VPU 0xa0
|
||||
+#define MIP_INT_STATUSH_VPU 0xb0
|
||||
+
|
||||
+struct mip_priv {
|
||||
+ spinlock_t msi_map_lock;
|
||||
+ spinlock_t hw_lock;
|
||||
+ void * __iomem base;
|
||||
+ phys_addr_t msg_addr;
|
||||
+ u32 msi_base; /* The SGI number that MSIs start */
|
||||
+ u32 num_msis; /* The number of SGIs for MSIs */
|
||||
+ u32 msi_offset; /* Shift the allocated msi up by N */
|
||||
+ unsigned long *msi_map;
|
||||
+};
|
||||
+
|
||||
+static void mip_mask_msi_irq(struct irq_data *d)
|
||||
+{
|
||||
+ pci_msi_mask_irq(d);
|
||||
+ irq_chip_mask_parent(d);
|
||||
+}
|
||||
+
|
||||
+static void mip_unmask_msi_irq(struct irq_data *d)
|
||||
+{
|
||||
+ pci_msi_unmask_irq(d);
|
||||
+ irq_chip_unmask_parent(d);
|
||||
+}
|
||||
+
|
||||
+static void mip_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
|
||||
+{
|
||||
+ struct mip_priv *priv = irq_data_get_irq_chip_data(d);
|
||||
+
|
||||
+ msg->address_hi = upper_32_bits(priv->msg_addr);
|
||||
+ msg->address_lo = lower_32_bits(priv->msg_addr);
|
||||
+ msg->data = d->hwirq;
|
||||
+}
|
||||
+
|
||||
+// The "bus-specific" irq_chip (the MIP doesn't _have_ to be used with PCIe)
|
||||
+
|
||||
+static struct irq_chip mip_msi_irq_chip = {
|
||||
+ .name = "MIP-MSI",
|
||||
+ .irq_unmask = mip_unmask_msi_irq,
|
||||
+ .irq_mask = mip_mask_msi_irq,
|
||||
+ .irq_eoi = irq_chip_eoi_parent,
|
||||
+ .irq_set_affinity = irq_chip_set_affinity_parent,
|
||||
+};
|
||||
+
|
||||
+static struct msi_domain_info mip_msi_domain_info = {
|
||||
+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
|
||||
+ MSI_FLAG_PCI_MSIX),
|
||||
+ .chip = &mip_msi_irq_chip,
|
||||
+};
|
||||
+
|
||||
+// The "middle" irq_chip (the hardware control part)
|
||||
+
|
||||
+static struct irq_chip mip_irq_chip = {
|
||||
+ .name = "MIP",
|
||||
+ .irq_mask = irq_chip_mask_parent,
|
||||
+ .irq_unmask = irq_chip_unmask_parent,
|
||||
+ .irq_eoi = irq_chip_eoi_parent,
|
||||
+ .irq_set_affinity = irq_chip_set_affinity_parent,
|
||||
+ .irq_set_type = irq_chip_set_type_parent,
|
||||
+ .irq_compose_msi_msg = mip_compose_msi_msg,
|
||||
+};
|
||||
+
|
||||
+
|
||||
+// And a domain to connect it to its parent (the GIC)
|
||||
+
|
||||
+static int mip_irq_domain_alloc(struct irq_domain *domain,
|
||||
+ unsigned int virq, unsigned int nr_irqs,
|
||||
+ void *args)
|
||||
+{
|
||||
+ struct mip_priv *priv = domain->host_data;
|
||||
+ struct irq_fwspec fwspec;
|
||||
+ struct irq_data *irqd;
|
||||
+ int hwirq, ret, i;
|
||||
+
|
||||
+ spin_lock(&priv->msi_map_lock);
|
||||
+
|
||||
+ hwirq = bitmap_find_free_region(priv->msi_map, priv->num_msis, ilog2(nr_irqs));
|
||||
+
|
||||
+ spin_unlock(&priv->msi_map_lock);
|
||||
+
|
||||
+ if (hwirq < 0)
|
||||
+ return -ENOSPC;
|
||||
+
|
||||
+ hwirq += priv->msi_offset;
|
||||
+ fwspec.fwnode = domain->parent->fwnode;
|
||||
+ fwspec.param_count = 3;
|
||||
+ fwspec.param[0] = 0;
|
||||
+ fwspec.param[1] = hwirq + priv->msi_base;
|
||||
+ fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
|
||||
+
|
||||
+ ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &fwspec);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ for (i = 0; i < nr_irqs; i++) {
|
||||
+ irqd = irq_domain_get_irq_data(domain->parent, virq + i);
|
||||
+ irqd->chip->irq_set_type(irqd, IRQ_TYPE_EDGE_RISING);
|
||||
+
|
||||
+ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
|
||||
+ &mip_irq_chip, priv);
|
||||
+ irqd = irq_get_irq_data(virq + i);
|
||||
+ irqd_set_single_target(irqd);
|
||||
+ irqd_set_affinity_on_activate(irqd);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mip_irq_domain_free(struct irq_domain *domain,
|
||||
+ unsigned int virq, unsigned int nr_irqs)
|
||||
+{
|
||||
+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
|
||||
+ struct mip_priv *priv = irq_data_get_irq_chip_data(d);
|
||||
+
|
||||
+ irq_domain_free_irqs_parent(domain, virq, nr_irqs);
|
||||
+ d->hwirq -= priv->msi_offset;
|
||||
+
|
||||
+ spin_lock(&priv->msi_map_lock);
|
||||
+
|
||||
+ bitmap_release_region(priv->msi_map, d->hwirq, ilog2(nr_irqs));
|
||||
+
|
||||
+ spin_unlock(&priv->msi_map_lock);
|
||||
+}
|
||||
+
|
||||
+#if 0
|
||||
+static int mip_irq_domain_activate(struct irq_domain *domain,
|
||||
+ struct irq_data *d, bool reserve)
|
||||
+{
|
||||
+ struct mip_priv *priv = irq_data_get_irq_chip_data(d);
|
||||
+ unsigned long flags;
|
||||
+ unsigned int irq = d->hwirq;
|
||||
+ void *__iomem reg = priv->base +
|
||||
+ ((irq < 32) ? MIP_INT_MASKL_HOST : MIP_INT_MASKH_HOST);
|
||||
+ u32 val;
|
||||
+
|
||||
+ spin_lock_irqsave(&priv->hw_lock, flags);
|
||||
+ val = readl(reg);
|
||||
+ val &= ~(1 << (irq % 32)); // Clear the mask
|
||||
+ writel(val, reg);
|
||||
+ spin_unlock_irqrestore(&priv->hw_lock, flags);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mip_irq_domain_deactivate(struct irq_domain *domain,
|
||||
+ struct irq_data *d)
|
||||
+{
|
||||
+ struct mip_priv *priv = irq_data_get_irq_chip_data(d);
|
||||
+ unsigned long flags;
|
||||
+ unsigned int irq = d->hwirq - priv->msi_base;
|
||||
+ void *__iomem reg = priv->base +
|
||||
+ ((irq < 32) ? MIP_INT_MASKL_HOST : MIP_INT_MASKH_HOST);
|
||||
+ u32 val;
|
||||
+
|
||||
+ spin_lock_irqsave(&priv->hw_lock, flags);
|
||||
+ val = readl(reg);
|
||||
+ val |= (1 << (irq % 32)); // Mask it out
|
||||
+ writel(val, reg);
|
||||
+ spin_unlock_irqrestore(&priv->hw_lock, flags);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static const struct irq_domain_ops mip_irq_domain_ops = {
|
||||
+ .alloc = mip_irq_domain_alloc,
|
||||
+ .free = mip_irq_domain_free,
|
||||
+ //.activate = mip_irq_domain_activate,
|
||||
+ //.deactivate = mip_irq_domain_deactivate,
|
||||
+};
|
||||
+
|
||||
+static int mip_init_domains(struct mip_priv *priv,
|
||||
+ struct device_node *node)
|
||||
+{
|
||||
+ struct irq_domain *middle_domain, *msi_domain, *gic_domain;
|
||||
+ struct device_node *gic_node;
|
||||
+
|
||||
+ gic_node = of_irq_find_parent(node);
|
||||
+ if (!gic_node) {
|
||||
+ pr_err("Failed to find the GIC node\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ gic_domain = irq_find_host(gic_node);
|
||||
+ if (!gic_domain) {
|
||||
+ pr_err("Failed to find the GIC domain\n");
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ middle_domain = irq_domain_add_tree(NULL,
|
||||
+ &mip_irq_domain_ops,
|
||||
+ priv);
|
||||
+ if (!middle_domain) {
|
||||
+ pr_err("Failed to create the MIP middle domain\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ middle_domain->parent = gic_domain;
|
||||
+
|
||||
+ msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
|
||||
+ &mip_msi_domain_info,
|
||||
+ middle_domain);
|
||||
+ if (!msi_domain) {
|
||||
+ pr_err("Failed to create MSI domain\n");
|
||||
+ irq_domain_remove(middle_domain);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __init mip_of_msi_init(struct device_node *node,
|
||||
+ struct device_node *parent)
|
||||
+{
|
||||
+ struct mip_priv *priv;
|
||||
+ struct resource res;
|
||||
+ int ret;
|
||||
+
|
||||
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ spin_lock_init(&priv->msi_map_lock);
|
||||
+ spin_lock_init(&priv->hw_lock);
|
||||
+
|
||||
+ ret = of_address_to_resource(node, 0, &res);
|
||||
+ if (ret) {
|
||||
+ pr_err("Failed to allocate resource\n");
|
||||
+ goto err_priv;
|
||||
+ }
|
||||
+
|
||||
+ if (of_property_read_u32(node, "brcm,msi-base-spi", &priv->msi_base)) {
|
||||
+ pr_err("Unable to parse MSI base\n");
|
||||
+ ret = -EINVAL;
|
||||
+ goto err_priv;
|
||||
+ }
|
||||
+
|
||||
+ if (of_property_read_u32(node, "brcm,msi-num-spis", &priv->num_msis)) {
|
||||
+ pr_err("Unable to parse MSI numbers\n");
|
||||
+ ret = -EINVAL;
|
||||
+ goto err_priv;
|
||||
+ }
|
||||
+
|
||||
+ if (of_property_read_u32(node, "brcm,msi-offset", &priv->msi_offset))
|
||||
+ priv->msi_offset = 0;
|
||||
+
|
||||
+ if (of_property_read_u64(node, "brcm,msi-pci-addr", &priv->msg_addr)) {
|
||||
+ pr_err("Unable to parse MSI address\n");
|
||||
+ ret = -EINVAL;
|
||||
+ goto err_priv;
|
||||
+ }
|
||||
+
|
||||
+ priv->base = ioremap(res.start, resource_size(&res));
|
||||
+ if (!priv->base) {
|
||||
+ pr_err("Failed to ioremap regs\n");
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_priv;
|
||||
+ }
|
||||
+
|
||||
+ priv->msi_map = kcalloc(BITS_TO_LONGS(priv->num_msis),
|
||||
+ sizeof(*priv->msi_map),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!priv->msi_map) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_base;
|
||||
+ }
|
||||
+
|
||||
+ pr_debug("Registering %d msixs, starting at %d\n",
|
||||
+ priv->num_msis, priv->msi_base);
|
||||
+
|
||||
+ /*
|
||||
+ * Begin with all MSI-Xs masked in for the host, masked out for the
|
||||
+ * VPU, and edge-triggered.
|
||||
+ */
|
||||
+ writel(0, priv->base + MIP_INT_MASKL_HOST);
|
||||
+ writel(0, priv->base + MIP_INT_MASKH_HOST);
|
||||
+ writel(~0, priv->base + MIP_INT_MASKL_VPU);
|
||||
+ writel(~0, priv->base + MIP_INT_MASKH_VPU);
|
||||
+ writel(~0, priv->base + MIP_INT_CFGL_HOST);
|
||||
+ writel(~0, priv->base + MIP_INT_CFGH_HOST);
|
||||
+
|
||||
+ ret = mip_init_domains(priv, node);
|
||||
+ if (ret) {
|
||||
+ pr_err("Failed to allocate msi_map\n");
|
||||
+ goto err_map;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_map:
|
||||
+ kfree(priv->msi_map);
|
||||
+
|
||||
+err_base:
|
||||
+ iounmap(priv->base);
|
||||
+
|
||||
+err_priv:
|
||||
+ kfree(priv);
|
||||
+
|
||||
+ pr_err("%s: failed - err %d\n", __func__, ret);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+IRQCHIP_DECLARE(bcm_mip, "brcm,bcm2712-mip-intc", mip_of_msi_init);
|
47
target/linux/bcm27xx/patches-6.1/950-0863-reset-reset-brcmstb-rescal-Support-shared-use.patch
Normal file
47
target/linux/bcm27xx/patches-6.1/950-0863-reset-reset-brcmstb-rescal-Support-shared-use.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From 87b1126181f79fb2558652af0d7fafd9deaab5f3 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Tue, 7 Sep 2021 14:49:00 +0100
|
||||
Subject: [PATCH] reset: reset-brcmstb-rescal: Support shared use
|
||||
|
||||
reset_control_reset should not be used with shared reset controllers.
|
||||
Add support for reset_control_assert and _deassert to get the desired
|
||||
behaviour and avoid ugly warnings in the kernel log.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/reset/reset-brcmstb-rescal.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/drivers/reset/reset-brcmstb-rescal.c
|
||||
+++ b/drivers/reset/reset-brcmstb-rescal.c
|
||||
@@ -20,6 +20,7 @@ struct brcm_rescal_reset {
|
||||
struct reset_controller_dev rcdev;
|
||||
};
|
||||
|
||||
+/* Also doubles a deassert */
|
||||
static int brcm_rescal_reset_set(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
@@ -52,6 +53,13 @@ static int brcm_rescal_reset_set(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* A dummy function - deassert/reset does all the work */
|
||||
+static int brcm_rescal_reset_assert(struct reset_controller_dev *rcdev,
|
||||
+ unsigned long id)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int brcm_rescal_reset_xlate(struct reset_controller_dev *rcdev,
|
||||
const struct of_phandle_args *reset_spec)
|
||||
{
|
||||
@@ -61,6 +69,8 @@ static int brcm_rescal_reset_xlate(struc
|
||||
|
||||
static const struct reset_control_ops brcm_rescal_reset_ops = {
|
||||
.reset = brcm_rescal_reset_set,
|
||||
+ .deassert = brcm_rescal_reset_set,
|
||||
+ .assert = brcm_rescal_reset_assert,
|
||||
};
|
||||
|
||||
static int brcm_rescal_reset_probe(struct platform_device *pdev)
|
@ -0,0 +1,418 @@
|
||||
From bd36586dd9e05bde8e23dc3d99771269b48b65f8 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Fri, 10 Sep 2021 17:20:45 +0100
|
||||
Subject: [PATCH] net: macb: Also set DMA coherent mask
|
||||
|
||||
macb: Add device tree properties that allow configuration of the AXI max pipeline register
|
||||
|
||||
net: macb: add support for ethtool interrupt moderation configuration
|
||||
|
||||
Only global throttling of rx or tx by time quanta is supported.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
|
||||
macb: add platform device shutdown function. Prevents AXI master over PCIE from hanging when the host is rebooted.
|
||||
|
||||
net: macb: increase polling interval for MDIO completion
|
||||
|
||||
MDIO is a slow bus (single-digit MHz). Polling at 1us intervals
|
||||
is a bit aggressive, so increase to 100us as the transaction
|
||||
usually takes 100-200us to complete.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
|
||||
net: macb: Several patches for RP1
|
||||
|
||||
64-bit RX fix
|
||||
|
||||
Also set DMA coherent mask
|
||||
|
||||
Add device tree properties that allow configuration of the AXI max
|
||||
pipeline register
|
||||
|
||||
Add support for ethtool interrupt moderation configuration
|
||||
|
||||
Only global throttling of rx or tx by time quanta is supported.
|
||||
|
||||
Add platform device shutdown function. Prevents AXI master over PCIE
|
||||
from hanging when the host is rebooted.
|
||||
|
||||
Increase polling interval for MDIO completion
|
||||
|
||||
MDIO is a slow bus (single-digit MHz). Polling at 1us intervals
|
||||
is a bit aggressive, so increase to 100us as the transaction
|
||||
usually takes 100-200us to complete.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
|
||||
net: macb: Support the phy-reset-gpios property
|
||||
|
||||
Allow a PHY to be reset with an optional GPIO. The reset duration can
|
||||
be specified in milliseconds - the default is 10ms.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
|
||||
drivers: net: macb: close device on driver shutdown
|
||||
|
||||
Fix some suspicious locking and instead call into macb_close, which
|
||||
deregisters and frees all resources the corresponding macb_open
|
||||
claimed.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
|
||||
net: macb: add hack to prevent TX stalls in a quiet system
|
||||
|
||||
See https://github.com/raspberrypi/linux-2712/issues/89
|
||||
|
||||
There is some critical window during TX where a further write to the
|
||||
TSTART bit while TX is active does not cause newly queued TX descriptors
|
||||
to be consumed.
|
||||
|
||||
For now "wait a bit, then try anyway" seems to work.
|
||||
|
||||
Requires further investigation, but this unsticks NFS reliably.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
|
||||
net: macb: set default interrupt moderation for GEM hardware
|
||||
|
||||
Defaulting to intmod = 0 is antisocial, as the MAC can generate over
|
||||
130,000 interrupts per second. 50us is a sensible default.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
---
|
||||
drivers/net/ethernet/cadence/macb.h | 25 ++++
|
||||
drivers/net/ethernet/cadence/macb_main.c | 151 ++++++++++++++++++++++-
|
||||
2 files changed, 174 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/cadence/macb.h
|
||||
+++ b/drivers/net/ethernet/cadence/macb.h
|
||||
@@ -84,6 +84,8 @@
|
||||
#define GEM_DMACFG 0x0010 /* DMA Configuration */
|
||||
#define GEM_JML 0x0048 /* Jumbo Max Length */
|
||||
#define GEM_HS_MAC_CONFIG 0x0050 /* GEM high speed config */
|
||||
+#define GEM_AMP 0x0054 /* AXI Max Pipeline */
|
||||
+#define GEM_INTMOD 0x005c /* Interrupt moderation */
|
||||
#define GEM_HRB 0x0080 /* Hash Bottom */
|
||||
#define GEM_HRT 0x0084 /* Hash Top */
|
||||
#define GEM_SA1B 0x0088 /* Specific1 Bottom */
|
||||
@@ -346,6 +348,21 @@
|
||||
#define GEM_ADDR64_OFFSET 30 /* Address bus width - 64b or 32b */
|
||||
#define GEM_ADDR64_SIZE 1
|
||||
|
||||
+/* Bitfields in AMP */
|
||||
+#define GEM_AR2R_MAX_PIPE_OFFSET 0 /* Maximum number of outstanding AXI read requests */
|
||||
+#define GEM_AR2R_MAX_PIPE_SIZE 8
|
||||
+#define GEM_AW2W_MAX_PIPE_OFFSET 8 /* Maximum number of outstanding AXI write requests */
|
||||
+#define GEM_AW2W_MAX_PIPE_SIZE 8
|
||||
+#define GEM_AW2B_FILL_OFFSET 16 /* Select wether the max AW2W transactions operates between: */
|
||||
+#define GEM_AW2B_FILL_AW2W 0 /* 0: the AW to W AXI channel */
|
||||
+#define GEM_AW2B_FILL_AW2B 1 /* 1: AW to B channel */
|
||||
+#define GEM_AW2B_FILL_SIZE 1
|
||||
+
|
||||
+/* Bitfields in INTMOD */
|
||||
+#define GEM_RX_MODERATION_OFFSET 0 /* RX interrupt moderation */
|
||||
+#define GEM_RX_MODERATION_SIZE 8
|
||||
+#define GEM_TX_MODERATION_OFFSET 16 /* TX interrupt moderation */
|
||||
+#define GEM_TX_MODERATION_SIZE 8
|
||||
|
||||
/* Bitfields in NSR */
|
||||
#define MACB_NSR_LINK_OFFSET 0 /* pcs_link_state */
|
||||
@@ -798,6 +815,7 @@
|
||||
})
|
||||
|
||||
#define MACB_READ_NSR(bp) macb_readl(bp, NSR)
|
||||
+#define MACB_READ_TSR(bp) macb_readl(bp, TSR)
|
||||
|
||||
/* struct macb_dma_desc - Hardware DMA descriptor
|
||||
* @addr: DMA address of data buffer
|
||||
@@ -1217,6 +1235,7 @@ struct macb_queue {
|
||||
dma_addr_t tx_ring_dma;
|
||||
struct work_struct tx_error_task;
|
||||
bool txubr_pending;
|
||||
+ bool tx_pending;
|
||||
struct napi_struct napi_tx;
|
||||
|
||||
dma_addr_t rx_ring_dma;
|
||||
@@ -1286,9 +1305,15 @@ struct macb {
|
||||
|
||||
u32 caps;
|
||||
unsigned int dma_burst_length;
|
||||
+ u8 aw2w_max_pipe;
|
||||
+ u8 ar2r_max_pipe;
|
||||
+ bool use_aw2b_fill;
|
||||
|
||||
phy_interface_t phy_interface;
|
||||
|
||||
+ struct gpio_desc *phy_reset_gpio;
|
||||
+ int phy_reset_ms;
|
||||
+
|
||||
/* AT91RM9200 transmit queue (1 on wire + 1 queued) */
|
||||
struct macb_tx_skb rm9200_txq[2];
|
||||
unsigned int max_tx_length;
|
||||
--- a/drivers/net/ethernet/cadence/macb_main.c
|
||||
+++ b/drivers/net/ethernet/cadence/macb_main.c
|
||||
@@ -41,6 +41,9 @@
|
||||
#include <linux/firmware/xlnx-zynqmp.h>
|
||||
#include "macb.h"
|
||||
|
||||
+static unsigned int txdelay = 35;
|
||||
+module_param(txdelay, uint, 0644);
|
||||
+
|
||||
/* This structure is only used for MACB on SiFive FU540 devices */
|
||||
struct sifive_fu540_macb_mgmt {
|
||||
void __iomem *reg;
|
||||
@@ -336,7 +339,7 @@ static int macb_mdio_wait_for_idle(struc
|
||||
u32 val;
|
||||
|
||||
return readx_poll_timeout(MACB_READ_NSR, bp, val, val & MACB_BIT(IDLE),
|
||||
- 1, MACB_MDIO_TIMEOUT);
|
||||
+ 100, MACB_MDIO_TIMEOUT);
|
||||
}
|
||||
|
||||
static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
||||
@@ -442,6 +445,19 @@ mdio_pm_exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
+static int macb_mdio_reset(struct mii_bus *bus)
|
||||
+{
|
||||
+ struct macb *bp = bus->priv;
|
||||
+
|
||||
+ if (bp->phy_reset_gpio) {
|
||||
+ gpiod_set_value_cansleep(bp->phy_reset_gpio, 1);
|
||||
+ msleep(bp->phy_reset_ms);
|
||||
+ gpiod_set_value_cansleep(bp->phy_reset_gpio, 0);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void macb_init_buffers(struct macb *bp)
|
||||
{
|
||||
struct macb_queue *queue;
|
||||
@@ -915,6 +931,7 @@ static int macb_mii_init(struct macb *bp
|
||||
bp->mii_bus->name = "MACB_mii_bus";
|
||||
bp->mii_bus->read = &macb_mdio_read;
|
||||
bp->mii_bus->write = &macb_mdio_write;
|
||||
+ bp->mii_bus->reset = &macb_mdio_reset;
|
||||
snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
|
||||
bp->pdev->name, bp->pdev->id);
|
||||
bp->mii_bus->priv = bp;
|
||||
@@ -1584,6 +1601,11 @@ static int macb_rx(struct macb_queue *qu
|
||||
|
||||
macb_init_rx_ring(queue);
|
||||
queue_writel(queue, RBQP, queue->rx_ring_dma);
|
||||
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
+ if (bp->hw_dma_cap & HW_DMA_CAP_64B)
|
||||
+ macb_writel(bp, RBQPH,
|
||||
+ upper_32_bits(queue->rx_ring_dma));
|
||||
+#endif
|
||||
|
||||
macb_writel(bp, NCR, ctrl | MACB_BIT(RE));
|
||||
|
||||
@@ -1884,8 +1906,9 @@ static irqreturn_t macb_interrupt(int ir
|
||||
queue_writel(queue, ISR, MACB_BIT(TCOMP) |
|
||||
MACB_BIT(TXUBR));
|
||||
|
||||
- if (status & MACB_BIT(TXUBR)) {
|
||||
+ if (status & MACB_BIT(TXUBR) || queue->tx_pending) {
|
||||
queue->txubr_pending = true;
|
||||
+ queue->tx_pending = 0;
|
||||
wmb(); // ensure softirq can see update
|
||||
}
|
||||
|
||||
@@ -2332,6 +2355,11 @@ static netdev_tx_t macb_start_xmit(struc
|
||||
skb_tx_timestamp(skb);
|
||||
|
||||
spin_lock_irq(&bp->lock);
|
||||
+
|
||||
+ /* TSTART write might get dropped, so make the IRQ retrigger a buffer read */
|
||||
+ if (macb_readl(bp, TSR) & MACB_BIT(TGO))
|
||||
+ queue->tx_pending = 1;
|
||||
+
|
||||
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
|
||||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
@@ -2699,6 +2727,37 @@ static void macb_configure_dma(struct ma
|
||||
}
|
||||
}
|
||||
|
||||
+static void gem_init_axi(struct macb *bp)
|
||||
+{
|
||||
+ u32 amp;
|
||||
+
|
||||
+ /* AXI pipeline setup - don't touch values unless specified in device
|
||||
+ * tree. Some hardware could have reset values > 1.
|
||||
+ */
|
||||
+ amp = gem_readl(bp, AMP);
|
||||
+
|
||||
+ if (bp->use_aw2b_fill)
|
||||
+ amp = GEM_BFINS(AW2B_FILL, bp->use_aw2b_fill, amp);
|
||||
+ if (bp->aw2w_max_pipe)
|
||||
+ amp = GEM_BFINS(AW2W_MAX_PIPE, bp->aw2w_max_pipe, amp);
|
||||
+ if (bp->ar2r_max_pipe)
|
||||
+ amp = GEM_BFINS(AR2R_MAX_PIPE, bp->ar2r_max_pipe, amp);
|
||||
+
|
||||
+ gem_writel(bp, AMP, amp);
|
||||
+}
|
||||
+
|
||||
+static void gem_init_intmod(struct macb *bp)
|
||||
+{
|
||||
+ unsigned int throttle;
|
||||
+ u32 intmod = 0;
|
||||
+
|
||||
+ /* Use sensible interrupt moderation thresholds (50us rx and tx) */
|
||||
+ throttle = (1000 * 50) / 800;
|
||||
+ intmod = GEM_BFINS(TX_MODERATION, throttle, intmod);
|
||||
+ intmod = GEM_BFINS(RX_MODERATION, throttle, intmod);
|
||||
+ gem_writel(bp, INTMOD, intmod);
|
||||
+}
|
||||
+
|
||||
static void macb_init_hw(struct macb *bp)
|
||||
{
|
||||
u32 config;
|
||||
@@ -2727,6 +2786,11 @@ static void macb_init_hw(struct macb *bp
|
||||
if (bp->caps & MACB_CAPS_JUMBO)
|
||||
bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK;
|
||||
|
||||
+ if (macb_is_gem(bp)) {
|
||||
+ gem_init_axi(bp);
|
||||
+ gem_init_intmod(bp);
|
||||
+ }
|
||||
+
|
||||
macb_configure_dma(bp);
|
||||
}
|
||||
|
||||
@@ -3072,6 +3136,52 @@ static void gem_get_ethtool_strings(stru
|
||||
}
|
||||
}
|
||||
|
||||
+static int gem_set_coalesce(struct net_device *dev,
|
||||
+ struct ethtool_coalesce *ec,
|
||||
+ struct kernel_ethtool_coalesce *kernel_coal,
|
||||
+ struct netlink_ext_ack *extack)
|
||||
+{
|
||||
+ struct macb *bp = netdev_priv(dev);
|
||||
+ unsigned int tx_throttle;
|
||||
+ unsigned int rx_throttle;
|
||||
+ u32 intmod = 0;
|
||||
+
|
||||
+ /* GEM has simple IRQ throttling support. RX and TX interrupts
|
||||
+ * are separately moderated on 800ns quantums, with no support
|
||||
+ * for frame coalescing.
|
||||
+ */
|
||||
+
|
||||
+ /* Max is 255 * 0.8us = 204us. Zero implies no moderation. */
|
||||
+ if (ec->rx_coalesce_usecs > 204 || ec->tx_coalesce_usecs > 204)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ tx_throttle = (1000 * ec->tx_coalesce_usecs) / 800;
|
||||
+ rx_throttle = (1000 * ec->rx_coalesce_usecs) / 800;
|
||||
+
|
||||
+ intmod = GEM_BFINS(TX_MODERATION, tx_throttle, intmod);
|
||||
+ intmod = GEM_BFINS(RX_MODERATION, rx_throttle, intmod);
|
||||
+
|
||||
+ gem_writel(bp, INTMOD, intmod);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int gem_get_coalesce(struct net_device *dev,
|
||||
+ struct ethtool_coalesce *ec,
|
||||
+ struct kernel_ethtool_coalesce *kernel_coal,
|
||||
+ struct netlink_ext_ack *extack)
|
||||
+{
|
||||
+ struct macb *bp = netdev_priv(dev);
|
||||
+ u32 intmod;
|
||||
+
|
||||
+ intmod = gem_readl(bp, INTMOD);
|
||||
+
|
||||
+ ec->tx_coalesce_usecs = (GEM_BFEXT(TX_MODERATION, intmod) * 800) / 1000;
|
||||
+ ec->rx_coalesce_usecs = (GEM_BFEXT(RX_MODERATION, intmod) * 800) / 1000;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static struct net_device_stats *macb_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
@@ -3664,6 +3774,8 @@ static const struct ethtool_ops macb_eth
|
||||
};
|
||||
|
||||
static const struct ethtool_ops gem_ethtool_ops = {
|
||||
+ .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
|
||||
+ ETHTOOL_COALESCE_TX_USECS,
|
||||
.get_regs_len = macb_get_regs_len,
|
||||
.get_regs = macb_get_regs,
|
||||
.get_wol = macb_get_wol,
|
||||
@@ -3673,6 +3785,8 @@ static const struct ethtool_ops gem_etht
|
||||
.get_ethtool_stats = gem_get_ethtool_stats,
|
||||
.get_strings = gem_get_ethtool_strings,
|
||||
.get_sset_count = gem_get_sset_count,
|
||||
+ .get_coalesce = gem_get_coalesce,
|
||||
+ .set_coalesce = gem_set_coalesce,
|
||||
.get_link_ksettings = macb_get_link_ksettings,
|
||||
.set_link_ksettings = macb_set_link_ksettings,
|
||||
.get_ringparam = macb_get_ringparam,
|
||||
@@ -4940,6 +5054,10 @@ static int macb_probe(struct platform_de
|
||||
|
||||
bp->usrio = macb_config->usrio;
|
||||
|
||||
+ device_property_read_u8(&pdev->dev, "cdns,aw2w-max-pipe", &bp->aw2w_max_pipe);
|
||||
+ device_property_read_u8(&pdev->dev, "cdns,ar2r-max-pipe", &bp->ar2r_max_pipe);
|
||||
+ bp->use_aw2b_fill = device_property_read_bool(&pdev->dev, "cdns,use-aw2b-fill");
|
||||
+
|
||||
spin_lock_init(&bp->lock);
|
||||
|
||||
/* setup capabilities */
|
||||
@@ -4995,6 +5113,21 @@ static int macb_probe(struct platform_de
|
||||
else
|
||||
bp->phy_interface = interface;
|
||||
|
||||
+ /* optional PHY reset-related properties */
|
||||
+ bp->phy_reset_gpio = devm_gpiod_get_optional(&pdev->dev, "phy-reset",
|
||||
+ GPIOD_OUT_LOW);
|
||||
+ if (IS_ERR(bp->phy_reset_gpio)) {
|
||||
+ dev_err(&pdev->dev, "Failed to obtain phy-reset gpio\n");
|
||||
+ err = PTR_ERR(bp->phy_reset_gpio);
|
||||
+ goto err_out_free_netdev;
|
||||
+ }
|
||||
+
|
||||
+ bp->phy_reset_ms = 10;
|
||||
+ of_property_read_u32(np, "phy-reset-duration", &bp->phy_reset_ms);
|
||||
+ /* A sane reset duration should not be longer than 1s */
|
||||
+ if (bp->phy_reset_ms > 1000)
|
||||
+ bp->phy_reset_ms = 1000;
|
||||
+
|
||||
/* IP specific init */
|
||||
err = init(pdev);
|
||||
if (err)
|
||||
@@ -5071,6 +5204,19 @@ static int macb_remove(struct platform_d
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void macb_shutdown(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct net_device *dev;
|
||||
+
|
||||
+ dev = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ rtnl_lock();
|
||||
+ netif_device_detach(dev);
|
||||
+ if (netif_running(dev))
|
||||
+ dev_close(dev);
|
||||
+ rtnl_unlock();
|
||||
+}
|
||||
+
|
||||
static int __maybe_unused macb_suspend(struct device *dev)
|
||||
{
|
||||
struct net_device *netdev = dev_get_drvdata(dev);
|
||||
@@ -5285,6 +5431,7 @@ static const struct dev_pm_ops macb_pm_o
|
||||
static struct platform_driver macb_driver = {
|
||||
.probe = macb_probe,
|
||||
.remove = macb_remove,
|
||||
+ .shutdown = macb_shutdown,
|
||||
.driver = {
|
||||
.name = "macb",
|
||||
.of_match_table = of_match_ptr(macb_dt_ids),
|
384
target/linux/bcm27xx/patches-6.1/950-0865-usb-dwc3-Set-DMA-and-coherent-masks-early.patch
Normal file
384
target/linux/bcm27xx/patches-6.1/950-0865-usb-dwc3-Set-DMA-and-coherent-masks-early.patch
Normal file
@ -0,0 +1,384 @@
|
||||
From 4ffa5f2c5fc7854683964bb2f2bf23907c18213f Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
Date: Mon, 13 Sep 2021 11:14:32 +0100
|
||||
Subject: [PATCH] usb: dwc3: Set DMA and coherent masks early
|
||||
|
||||
dwc3 allocates scratch and event buffers in the top-level driver. Hack the
|
||||
probe function to set the DMA mask before trying to allocate these.
|
||||
|
||||
I think the event buffers are only used in device mode, but the scratch
|
||||
buffers may be used if core hibernation is enabled.
|
||||
|
||||
usb: dwc3: add support for new DT quirks
|
||||
|
||||
Apply the optional axi-pipe-limit and dis-in-autoretry-quirk properties
|
||||
during driver probe.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
|
||||
phy: phy-brcm-usb: Add 2712 support
|
||||
|
||||
usb: dwc3: if the host controller instance number is present in DT, use it
|
||||
|
||||
If two instances of a dwc3 host controller are specified in devicetree,
|
||||
then the probe order may be arbitrary which results in the device names
|
||||
swapping on a per-boot basis.
|
||||
|
||||
If a "usb" alias with the instance number is specified, then use
|
||||
that to construct the device name instead of autogenerating one.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
|
||||
rp1 dwc3 changes
|
||||
|
||||
drivers: usb: dwc3: allow setting GTXTHRCFG on dwc_usb3.0 hardware
|
||||
|
||||
Equivalent register fields exist in the SuperSpeed Host version of the
|
||||
hardware, so allow the use of TX thresholds if specified in devicetree.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
|
||||
drivers: usb: dwc3: remove downstream quirk dis-in-autoretry
|
||||
|
||||
Upstream have unilaterally disabled the feature.
|
||||
|
||||
Partially reverts 6e9142a26ee0fdc3a5adc49ed6cedc0b16ec2ed1 (downstream)
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
---
|
||||
drivers/phy/broadcom/Kconfig | 2 +-
|
||||
.../phy/broadcom/phy-brcm-usb-init-synopsys.c | 59 +++++++++++++++++++
|
||||
drivers/phy/broadcom/phy-brcm-usb-init.h | 2 +
|
||||
drivers/phy/broadcom/phy-brcm-usb.c | 18 +++++-
|
||||
drivers/usb/dwc3/core.c | 52 ++++++++++++++++
|
||||
drivers/usb/dwc3/core.h | 10 ++++
|
||||
drivers/usb/dwc3/host.c | 17 ++++--
|
||||
7 files changed, 153 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/phy/broadcom/Kconfig
|
||||
+++ b/drivers/phy/broadcom/Kconfig
|
||||
@@ -93,7 +93,7 @@ config PHY_BRCM_SATA
|
||||
|
||||
config PHY_BRCM_USB
|
||||
tristate "Broadcom STB USB PHY driver"
|
||||
- depends on ARCH_BCMBCA || ARCH_BRCMSTB || COMPILE_TEST
|
||||
+ depends on ARCH_BCMBCA || ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
|
||||
depends on OF
|
||||
select GENERIC_PHY
|
||||
select SOC_BRCMSTB if ARCH_BRCMSTB
|
||||
--- a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
|
||||
+++ b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
|
||||
@@ -318,6 +318,36 @@ static void usb_init_common_7216(struct
|
||||
usb_init_common(params);
|
||||
}
|
||||
|
||||
+static void usb_init_common_2712(struct brcm_usb_init_params *params)
|
||||
+{
|
||||
+ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
|
||||
+ void __iomem *bdc_ec = params->regs[BRCM_REGS_BDC_EC];
|
||||
+ u32 reg;
|
||||
+
|
||||
+ if (params->syscon_piarbctl)
|
||||
+ syscon_piarbctl_init(params->syscon_piarbctl);
|
||||
+
|
||||
+ USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
|
||||
+
|
||||
+ usb_wake_enable_7211b0(params, false);
|
||||
+
|
||||
+ usb_init_common(params);
|
||||
+
|
||||
+ /*
|
||||
+ * The BDC controller will get occasional failures with
|
||||
+ * the default "Read Transaction Size" of 6 (1024 bytes).
|
||||
+ * Set it to 4 (256 bytes).
|
||||
+ */
|
||||
+ if ((params->mode != USB_CTLR_MODE_HOST) && bdc_ec) {
|
||||
+ reg = brcm_usb_readl(bdc_ec + BDC_EC_AXIRDA);
|
||||
+ reg &= ~BDC_EC_AXIRDA_RTS_MASK;
|
||||
+ reg |= (0x4 << BDC_EC_AXIRDA_RTS_SHIFT);
|
||||
+ brcm_usb_writel(reg, bdc_ec + BDC_EC_AXIRDA);
|
||||
+ }
|
||||
+
|
||||
+ usb2_eye_fix_7211b0(params);
|
||||
+}
|
||||
+
|
||||
static void usb_init_xhci(struct brcm_usb_init_params *params)
|
||||
{
|
||||
pr_debug("%s\n", __func__);
|
||||
@@ -363,6 +393,18 @@ static void usb_uninit_common_7211b0(str
|
||||
|
||||
}
|
||||
|
||||
+static void usb_uninit_common_2712(struct brcm_usb_init_params *params)
|
||||
+{
|
||||
+ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
|
||||
+
|
||||
+ if (params->wake_enabled) {
|
||||
+ USB_CTRL_SET(ctrl, TEST_PORT_CTL, TPOUT_SEL_PME_GEN);
|
||||
+ usb_wake_enable_7211b0(params, true);
|
||||
+ } else {
|
||||
+ USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void usb_uninit_xhci(struct brcm_usb_init_params *params)
|
||||
{
|
||||
|
||||
@@ -417,6 +459,16 @@ static const struct brcm_usb_init_ops bc
|
||||
.set_dual_select = usb_set_dual_select,
|
||||
};
|
||||
|
||||
+static const struct brcm_usb_init_ops bcm2712_ops = {
|
||||
+ .init_ipp = usb_init_ipp,
|
||||
+ .init_common = usb_init_common_2712,
|
||||
+ .init_xhci = usb_init_xhci,
|
||||
+ .uninit_common = usb_uninit_common_2712,
|
||||
+ .uninit_xhci = usb_uninit_xhci,
|
||||
+ .get_dual_select = usb_get_dual_select,
|
||||
+ .set_dual_select = usb_set_dual_select,
|
||||
+};
|
||||
+
|
||||
void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params)
|
||||
{
|
||||
|
||||
@@ -434,3 +486,10 @@ void brcm_usb_dvr_init_7211b0(struct brc
|
||||
params->family_name = "7211";
|
||||
params->ops = &bcm7211b0_ops;
|
||||
}
|
||||
+
|
||||
+void brcm_usb_dvr_init_2712(struct brcm_usb_init_params *params)
|
||||
+{
|
||||
+ params->family_name = "2712";
|
||||
+ params->ops = &bcm2712_ops;
|
||||
+ params->suspend_with_clocks = true;
|
||||
+}
|
||||
--- a/drivers/phy/broadcom/phy-brcm-usb-init.h
|
||||
+++ b/drivers/phy/broadcom/phy-brcm-usb-init.h
|
||||
@@ -61,12 +61,14 @@ struct brcm_usb_init_params {
|
||||
const struct brcm_usb_init_ops *ops;
|
||||
struct regmap *syscon_piarbctl;
|
||||
bool wake_enabled;
|
||||
+ bool suspend_with_clocks;
|
||||
};
|
||||
|
||||
void brcm_usb_dvr_init_4908(struct brcm_usb_init_params *params);
|
||||
void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params);
|
||||
void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params);
|
||||
void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params);
|
||||
+void brcm_usb_dvr_init_2712(struct brcm_usb_init_params *params);
|
||||
|
||||
static inline u32 brcm_usb_readl(void __iomem *addr)
|
||||
{
|
||||
--- a/drivers/phy/broadcom/phy-brcm-usb.c
|
||||
+++ b/drivers/phy/broadcom/phy-brcm-usb.c
|
||||
@@ -76,7 +76,7 @@ struct brcm_usb_phy_data {
|
||||
};
|
||||
|
||||
static s8 *node_reg_names[BRCM_REGS_MAX] = {
|
||||
- "crtl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec"
|
||||
+ "ctrl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec"
|
||||
};
|
||||
|
||||
static int brcm_pm_notifier(struct notifier_block *notifier,
|
||||
@@ -315,6 +315,18 @@ static const struct match_chip_info chip
|
||||
.optional_reg = BRCM_REGS_BDC_EC,
|
||||
};
|
||||
|
||||
+static const struct match_chip_info chip_info_2712 = {
|
||||
+ .init_func = &brcm_usb_dvr_init_2712,
|
||||
+ .required_regs = {
|
||||
+ BRCM_REGS_CTRL,
|
||||
+ BRCM_REGS_XHCI_EC,
|
||||
+ BRCM_REGS_XHCI_GBL,
|
||||
+ BRCM_REGS_USB_MDIO,
|
||||
+ -1,
|
||||
+ },
|
||||
+ .optional_reg = BRCM_REGS_BDC_EC,
|
||||
+};
|
||||
+
|
||||
static const struct match_chip_info chip_info_7445 = {
|
||||
.init_func = &brcm_usb_dvr_init_7445,
|
||||
.required_regs = {
|
||||
@@ -338,6 +350,10 @@ static const struct of_device_id brcm_us
|
||||
.data = &chip_info_7211b0,
|
||||
},
|
||||
{
|
||||
+ .compatible = "brcm,bcm2712-usb-phy",
|
||||
+ .data = &chip_info_2712,
|
||||
+ },
|
||||
+ {
|
||||
.compatible = "brcm,brcmstb-usb-phy",
|
||||
.data = &chip_info_7445,
|
||||
},
|
||||
--- a/drivers/usb/dwc3/core.c
|
||||
+++ b/drivers/usb/dwc3/core.c
|
||||
@@ -1216,6 +1216,24 @@ static void dwc3_config_threshold(struct
|
||||
}
|
||||
}
|
||||
|
||||
+static void dwc3_set_axi_pipe_limit(struct dwc3 *dwc)
|
||||
+{
|
||||
+ struct device *dev = dwc->dev;
|
||||
+ u32 cfg;
|
||||
+
|
||||
+ if (!dwc->axi_pipe_limit)
|
||||
+ return;
|
||||
+ if (dwc->axi_pipe_limit > 16) {
|
||||
+ dev_err(dev, "Invalid axi_pipe_limit property\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG1);
|
||||
+ cfg &= ~DWC3_GSBUSCFG1_PIPETRANSLIMIT(15);
|
||||
+ cfg |= DWC3_GSBUSCFG1_PIPETRANSLIMIT(dwc->axi_pipe_limit - 1);
|
||||
+
|
||||
+ dwc3_writel(dwc->regs, DWC3_GSBUSCFG1, cfg);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* dwc3_core_init - Low-level initialization of DWC3 Core
|
||||
* @dwc: Pointer to our controller context structure
|
||||
@@ -1308,6 +1326,8 @@ static int dwc3_core_init(struct dwc3 *d
|
||||
|
||||
dwc3_set_incr_burst_type(dwc);
|
||||
|
||||
+ dwc3_set_axi_pipe_limit(dwc);
|
||||
+
|
||||
usb_phy_set_suspend(dwc->usb2_phy, 0);
|
||||
usb_phy_set_suspend(dwc->usb3_phy, 0);
|
||||
ret = phy_power_on(dwc->usb2_generic_phy);
|
||||
@@ -1541,6 +1561,7 @@ static void dwc3_get_properties(struct d
|
||||
u8 tx_thr_num_pkt_prd = 0;
|
||||
u8 tx_max_burst_prd = 0;
|
||||
u8 tx_fifo_resize_max_num;
|
||||
+ u8 axi_pipe_limit;
|
||||
const char *usb_psy_name;
|
||||
int ret;
|
||||
|
||||
@@ -1563,6 +1584,9 @@ static void dwc3_get_properties(struct d
|
||||
*/
|
||||
tx_fifo_resize_max_num = 6;
|
||||
|
||||
+ /* Default to 0 (don't override hardware defaults) */
|
||||
+ axi_pipe_limit = 0;
|
||||
+
|
||||
dwc->maximum_speed = usb_get_maximum_speed(dev);
|
||||
dwc->max_ssp_rate = usb_get_maximum_ssp_rate(dev);
|
||||
dwc->dr_mode = usb_get_dr_mode(dev);
|
||||
@@ -1678,6 +1702,9 @@ static void dwc3_get_properties(struct d
|
||||
dwc->dis_split_quirk = device_property_read_bool(dev,
|
||||
"snps,dis-split-quirk");
|
||||
|
||||
+ device_property_read_u8(dev, "snps,axi-pipe-limit",
|
||||
+ &axi_pipe_limit);
|
||||
+
|
||||
dwc->lpm_nyet_threshold = lpm_nyet_threshold;
|
||||
dwc->tx_de_emphasis = tx_de_emphasis;
|
||||
|
||||
@@ -1695,6 +1722,8 @@ static void dwc3_get_properties(struct d
|
||||
dwc->tx_thr_num_pkt_prd = tx_thr_num_pkt_prd;
|
||||
dwc->tx_max_burst_prd = tx_max_burst_prd;
|
||||
|
||||
+ dwc->axi_pipe_limit = axi_pipe_limit;
|
||||
+
|
||||
dwc->imod_interval = 0;
|
||||
|
||||
dwc->tx_fifo_resize_max_num = tx_fifo_resize_max_num;
|
||||
@@ -1903,6 +1932,12 @@ static int dwc3_probe(struct platform_de
|
||||
|
||||
dwc3_get_properties(dwc);
|
||||
|
||||
+ if (!dwc->sysdev_is_parent) {
|
||||
+ ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
dwc->reset = devm_reset_control_array_get_optional_shared(dev);
|
||||
if (IS_ERR(dwc->reset)) {
|
||||
ret = PTR_ERR(dwc->reset);
|
||||
--- a/drivers/usb/dwc3/core.h
|
||||
+++ b/drivers/usb/dwc3/core.h
|
||||
@@ -183,6 +183,9 @@
|
||||
#define DWC3_GSBUSCFG0_INCRBRSTENA (1 << 0) /* undefined length enable */
|
||||
#define DWC3_GSBUSCFG0_INCRBRST_MASK 0xff
|
||||
|
||||
+/* Global SoC Bus Configuration Register 1 */
|
||||
+#define DWC3_GSBUSCFG1_PIPETRANSLIMIT(n) (((n) & 0xf) << 8)
|
||||
+
|
||||
/* Global Debug LSP MUX Select */
|
||||
#define DWC3_GDBGLSPMUX_ENDBC BIT(15) /* Host only */
|
||||
#define DWC3_GDBGLSPMUX_HOSTSELECT(n) ((n) & 0x3fff)
|
||||
@@ -1056,6 +1059,7 @@ struct dwc3_scratchpad_array {
|
||||
* @tx_max_burst_prd: max periodic ESS transmit burst size
|
||||
* @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize
|
||||
* @clear_stall_protocol: endpoint number that requires a delayed status phase
|
||||
+ * @axi_max_pipe: set to override the maximum number of pipelined AXI transfers
|
||||
* @hsphy_interface: "utmi" or "ulpi"
|
||||
* @connected: true when we're connected to a host, false otherwise
|
||||
* @softconnect: true when gadget connect is called, false when disconnect runs
|
||||
@@ -1287,6 +1291,7 @@ struct dwc3 {
|
||||
u8 tx_max_burst_prd;
|
||||
u8 tx_fifo_resize_max_num;
|
||||
u8 clear_stall_protocol;
|
||||
+ u8 axi_pipe_limit;
|
||||
|
||||
const char *hsphy_interface;
|
||||
|
||||
--- a/drivers/usb/dwc3/host.c
|
||||
+++ b/drivers/usb/dwc3/host.c
|
||||
@@ -30,10 +30,10 @@ static void dwc3_host_fill_xhci_irq_res(
|
||||
|
||||
static int dwc3_host_get_irq(struct dwc3 *dwc)
|
||||
{
|
||||
- struct platform_device *dwc3_pdev = to_platform_device(dwc->dev);
|
||||
+ struct platform_device *pdev = to_platform_device(dwc->dev);
|
||||
int irq;
|
||||
|
||||
- irq = platform_get_irq_byname_optional(dwc3_pdev, "host");
|
||||
+ irq = platform_get_irq_byname_optional(pdev, "host");
|
||||
if (irq > 0) {
|
||||
dwc3_host_fill_xhci_irq_res(dwc, irq, "host");
|
||||
goto out;
|
||||
@@ -42,7 +42,7 @@ static int dwc3_host_get_irq(struct dwc3
|
||||
if (irq == -EPROBE_DEFER)
|
||||
goto out;
|
||||
|
||||
- irq = platform_get_irq_byname_optional(dwc3_pdev, "dwc_usb3");
|
||||
+ irq = platform_get_irq_byname_optional(pdev, "dwc_usb3");
|
||||
if (irq > 0) {
|
||||
dwc3_host_fill_xhci_irq_res(dwc, irq, "dwc_usb3");
|
||||
goto out;
|
||||
@@ -51,7 +51,7 @@ static int dwc3_host_get_irq(struct dwc3
|
||||
if (irq == -EPROBE_DEFER)
|
||||
goto out;
|
||||
|
||||
- irq = platform_get_irq(dwc3_pdev, 0);
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
if (irq > 0) {
|
||||
dwc3_host_fill_xhci_irq_res(dwc, irq, NULL);
|
||||
goto out;
|
||||
@@ -66,16 +66,23 @@ out:
|
||||
|
||||
int dwc3_host_init(struct dwc3 *dwc)
|
||||
{
|
||||
+ struct platform_device *pdev = to_platform_device(dwc->dev);
|
||||
struct property_entry props[4];
|
||||
struct platform_device *xhci;
|
||||
int ret, irq;
|
||||
int prop_idx = 0;
|
||||
+ int id;
|
||||
|
||||
irq = dwc3_host_get_irq(dwc);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
- xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
|
||||
+ id = of_alias_get_id(pdev->dev.of_node, "usb");
|
||||
+ if (id >= 0)
|
||||
+ xhci = platform_device_alloc("xhci-hcd", id);
|
||||
+ else
|
||||
+ xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
|
||||
+
|
||||
if (!xhci) {
|
||||
dev_err(dwc->dev, "couldn't allocate xHCI device\n");
|
||||
return -ENOMEM;
|
37
target/linux/bcm27xx/patches-6.1/950-0866-drm-panel-raspberrypi-touchscreen-Insert-more-delays.patch
Normal file
37
target/linux/bcm27xx/patches-6.1/950-0866-drm-panel-raspberrypi-touchscreen-Insert-more-delays.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 480c8e9f48f8a96c457eb3dc0079a73598fb7477 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.org>
|
||||
Date: Wed, 1 Dec 2021 19:43:08 +0000
|
||||
Subject: [PATCH] drm/panel/raspberrypi-touchscreen: Insert more delays.
|
||||
|
||||
This avoids failures in cases where the panel is enabled
|
||||
or re-probed very soon after being disabled or probed.
|
||||
These can occur because the Atmel device can mis-behave
|
||||
over I2C for a few ms after any write to the POWERON register.
|
||||
---
|
||||
drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
|
||||
+++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
|
||||
@@ -299,6 +299,13 @@ static int rpi_touchscreen_prepare(struc
|
||||
struct rpi_touchscreen *ts = panel_to_ts(panel);
|
||||
int i, data;
|
||||
|
||||
+ /*
|
||||
+ * Power up the Toshiba bridge. The Atmel device can misbehave
|
||||
+ * over I2C for a few ms after writes to REG_POWERON (including the
|
||||
+ * write in rpi_touchscreen_disable()), so sleep before and after.
|
||||
+ * Also to ensure that the bridge has been off for at least 100ms.
|
||||
+ */
|
||||
+ msleep(100);
|
||||
rpi_touchscreen_i2c_write(ts, REG_POWERON, 1);
|
||||
usleep_range(20000, 25000);
|
||||
/* Wait for nPWRDWN to go low to indicate poweron is done. */
|
||||
@@ -431,6 +438,7 @@ static int rpi_touchscreen_probe(struct
|
||||
|
||||
/* Turn off at boot, so we can cleanly sequence powering on. */
|
||||
rpi_touchscreen_i2c_write(ts, REG_POWERON, 0);
|
||||
+ usleep_range(20000, 25000);
|
||||
|
||||
/* Look up the DSI host. It needs to probe before we do. */
|
||||
endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,42 @@
|
||||
From 9a11300e46344917226b986a8740e7581d66adf3 Mon Sep 17 00:00:00 2001
|
||||
From: Naushir Patuck <naush@raspberrypi.com>
|
||||
Date: Mon, 7 Feb 2022 09:20:49 +0000
|
||||
Subject: [PATCH] V4L2: Add PiSP opaque formats to V4L2
|
||||
|
||||
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
|
||||
---
|
||||
drivers/media/v4l2-core/v4l2-ioctl.c | 4 +++-
|
||||
include/uapi/linux/videodev2.h | 7 +++++++
|
||||
2 files changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||
@@ -1452,7 +1452,9 @@ static void v4l_fill_fmtdesc(struct v4l2
|
||||
case V4L2_PIX_FMT_NV12M_10BE_8L128: descr = "10-bit NV12M (8x128 Linear, BE)"; break;
|
||||
case V4L2_META_FMT_SENSOR_DATA: descr = "Sensor Ancillary Metadata"; break;
|
||||
case V4L2_META_FMT_BCM2835_ISP_STATS: descr = "BCM2835 ISP Image Statistics"; break;
|
||||
- case V4L2_META_FMT_RPI_BE_CFG: descr = "PiSP Config format"; break;
|
||||
+ case V4L2_META_FMT_RPI_BE_CFG: descr = "PiSP BE Config format"; break;
|
||||
+ case V4L2_META_FMT_RPI_FE_CFG: descr = "PiSP FE Config format"; break;
|
||||
+ case V4L2_META_FMT_RPI_FE_STATS: descr = "PiSP FE Statistics format"; break;
|
||||
|
||||
default:
|
||||
/* Compressed formats */
|
||||
--- a/include/uapi/linux/videodev2.h
|
||||
+++ b/include/uapi/linux/videodev2.h
|
||||
@@ -826,8 +826,15 @@ struct v4l2_pix_format {
|
||||
#define V4L2_META_FMT_RK_ISP1_STAT_3A v4l2_fourcc('R', 'K', '1', 'S') /* Rockchip ISP1 3A Statistics */
|
||||
|
||||
/* The metadata format identifier for our configuration buffers. */
|
||||
+/* The metadata format identifier for BE configuration buffers. */
|
||||
#define V4L2_META_FMT_RPI_BE_CFG v4l2_fourcc('R', 'P', 'B', 'C')
|
||||
|
||||
+/* The metadata format identifier for FE configuration buffers. */
|
||||
+#define V4L2_META_FMT_RPI_FE_CFG v4l2_fourcc('R', 'P', 'F', 'C')
|
||||
+
|
||||
+/* The metadata format identifier for FE configuration buffers. */
|
||||
+#define V4L2_META_FMT_RPI_FE_STATS v4l2_fourcc('R', 'P', 'F', 'S')
|
||||
+
|
||||
/* priv field value to indicates that subsequent fields are valid. */
|
||||
#define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe
|
||||
|
39
target/linux/bcm27xx/patches-6.1/950-0869-V4L2-Add-PiSP-compressed-formats-to-V4L2.patch
Normal file
39
target/linux/bcm27xx/patches-6.1/950-0869-V4L2-Add-PiSP-compressed-formats-to-V4L2.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 01f31f4145d49a30eb553c65ea755dde8dba1de0 Mon Sep 17 00:00:00 2001
|
||||
From: Naushir Patuck <naush@raspberrypi.com>
|
||||
Date: Wed, 2 Mar 2022 16:10:50 +0000
|
||||
Subject: [PATCH] V4L2: Add PiSP compressed formats to V4L2
|
||||
|
||||
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
|
||||
---
|
||||
drivers/media/v4l2-core/v4l2-ioctl.c | 4 ++++
|
||||
include/uapi/linux/videodev2.h | 6 +++++-
|
||||
2 files changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||
@@ -1507,6 +1507,10 @@ static void v4l_fill_fmtdesc(struct v4l2
|
||||
case V4L2_PIX_FMT_QC08C: descr = "QCOM Compressed 8-bit Format"; break;
|
||||
case V4L2_PIX_FMT_QC10C: descr = "QCOM Compressed 10-bit Format"; break;
|
||||
case V4L2_PIX_FMT_RPI_BE: descr = "PiSP Opaque Format"; break;
|
||||
+ case V4L2_PIX_FMT_PISP_COMP_RGGB:
|
||||
+ case V4L2_PIX_FMT_PISP_COMP_GRBG:
|
||||
+ case V4L2_PIX_FMT_PISP_COMP_GBRG:
|
||||
+ case V4L2_PIX_FMT_PISP_COMP_BGGR: descr = "PiSP Bayer Compressed Format"; break;
|
||||
default:
|
||||
if (fmt->description[0])
|
||||
return;
|
||||
--- a/include/uapi/linux/videodev2.h
|
||||
+++ b/include/uapi/linux/videodev2.h
|
||||
@@ -794,7 +794,11 @@ struct v4l2_pix_format {
|
||||
#define V4L2_PIX_FMT_IPU3_SRGGB10 v4l2_fourcc('i', 'p', '3', 'r') /* IPU3 packed 10-bit RGGB bayer */
|
||||
|
||||
/* The pixel format for all our buffers (the precise format is found in the config buffer). */
|
||||
-#define V4L2_PIX_FMT_RPI_BE v4l2_fourcc('R', 'P', 'B', 'P')
|
||||
+#define V4L2_PIX_FMT_RPI_BE v4l2_fourcc('R', 'P', 'B', 'P')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP_RGGB v4l2_fourcc('P', 'C', 'R', 'G')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP_GRBG v4l2_fourcc('P', 'C', 'G', 'R')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP_GBRG v4l2_fourcc('P', 'C', 'G', 'B')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP_BGGR v4l2_fourcc('P', 'C', 'B', 'G')
|
||||
|
||||
/* SDR formats - used only for Software Defined Radio devices */
|
||||
#define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */
|
249
target/linux/bcm27xx/patches-6.1/950-0871-dt-binding-mfd-Add-binding-for-Raspberry-Pi-RP1.patch
Normal file
249
target/linux/bcm27xx/patches-6.1/950-0871-dt-binding-mfd-Add-binding-for-Raspberry-Pi-RP1.patch
Normal file
@ -0,0 +1,249 @@
|
||||
From c93f469dabdbed822e5abeb5283d79fc9faa858c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Fri, 28 Oct 2022 14:10:34 +0100
|
||||
Subject: [PATCH] dt-binding: mfd: Add binding for Raspberry Pi RP1
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
include/dt-bindings/mfd/rp1.h | 235 ++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 235 insertions(+)
|
||||
create mode 100644 include/dt-bindings/mfd/rp1.h
|
||||
|
||||
--- /dev/null
|
||||
+++ b/include/dt-bindings/mfd/rp1.h
|
||||
@@ -0,0 +1,235 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0 */
|
||||
+/*
|
||||
+ * This header provides constants for the PY MFD.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _RP1_H
|
||||
+#define _RP1_H
|
||||
+
|
||||
+/* Address map */
|
||||
+#define RP1_SYSINFO_BASE 0x000000
|
||||
+#define RP1_TBMAN_BASE 0x004000
|
||||
+#define RP1_SYSCFG_BASE 0x008000
|
||||
+#define RP1_OTP_BASE 0x00c000
|
||||
+#define RP1_POWER_BASE 0x010000
|
||||
+#define RP1_RESETS_BASE 0x014000
|
||||
+#define RP1_CLOCKS_BANK_DEFAULT_BASE 0x018000
|
||||
+#define RP1_CLOCKS_BANK_VIDEO_BASE 0x01c000
|
||||
+#define RP1_PLL_SYS_BASE 0x020000
|
||||
+#define RP1_PLL_AUDIO_BASE 0x024000
|
||||
+#define RP1_PLL_VIDEO_BASE 0x028000
|
||||
+#define RP1_UART0_BASE 0x030000
|
||||
+#define RP1_UART1_BASE 0x034000
|
||||
+#define RP1_UART2_BASE 0x038000
|
||||
+#define RP1_UART3_BASE 0x03c000
|
||||
+#define RP1_UART4_BASE 0x040000
|
||||
+#define RP1_UART5_BASE 0x044000
|
||||
+#define RP1_SPI8_BASE 0x04c000
|
||||
+#define RP1_SPI0_BASE 0x050000
|
||||
+#define RP1_SPI1_BASE 0x054000
|
||||
+#define RP1_SPI2_BASE 0x058000
|
||||
+#define RP1_SPI3_BASE 0x05c000
|
||||
+#define RP1_SPI4_BASE 0x060000
|
||||
+#define RP1_SPI5_BASE 0x064000
|
||||
+#define RP1_SPI6_BASE 0x068000
|
||||
+#define RP1_SPI7_BASE 0x06c000
|
||||
+#define RP1_I2C0_BASE 0x070000
|
||||
+#define RP1_I2C1_BASE 0x074000
|
||||
+#define RP1_I2C2_BASE 0x078000
|
||||
+#define RP1_I2C3_BASE 0x07c000
|
||||
+#define RP1_I2C4_BASE 0x080000
|
||||
+#define RP1_I2C5_BASE 0x084000
|
||||
+#define RP1_I2C6_BASE 0x088000
|
||||
+#define RP1_AUDIO_IN_BASE 0x090000
|
||||
+#define RP1_AUDIO_OUT_BASE 0x094000
|
||||
+#define RP1_PWM0_BASE 0x098000
|
||||
+#define RP1_PWM1_BASE 0x09c000
|
||||
+#define RP1_I2S0_BASE 0x0a0000
|
||||
+#define RP1_I2S1_BASE 0x0a4000
|
||||
+#define RP1_I2S2_BASE 0x0a8000
|
||||
+#define RP1_TIMER_BASE 0x0ac000
|
||||
+#define RP1_SDIO0_APBS_BASE 0x0b0000
|
||||
+#define RP1_SDIO1_APBS_BASE 0x0b4000
|
||||
+#define RP1_BUSFABRIC_MONITOR_BASE 0x0c0000
|
||||
+#define RP1_BUSFABRIC_AXISHIM_BASE 0x0c4000
|
||||
+#define RP1_ADC_BASE 0x0c8000
|
||||
+#define RP1_IO_BANK0_BASE 0x0d0000
|
||||
+#define RP1_IO_BANK1_BASE 0x0d4000
|
||||
+#define RP1_IO_BANK2_BASE 0x0d8000
|
||||
+#define RP1_SYS_RIO0_BASE 0x0e0000
|
||||
+#define RP1_SYS_RIO1_BASE 0x0e4000
|
||||
+#define RP1_SYS_RIO2_BASE 0x0e8000
|
||||
+#define RP1_PADS_BANK0_BASE 0x0f0000
|
||||
+#define RP1_PADS_BANK1_BASE 0x0f4000
|
||||
+#define RP1_PADS_BANK2_BASE 0x0f8000
|
||||
+#define RP1_PADS_ETH_BASE 0x0fc000
|
||||
+#define RP1_ETH_IP_BASE 0x100000
|
||||
+#define RP1_ETH_CFG_BASE 0x104000
|
||||
+#define RP1_PCIE_APBS_BASE 0x108000
|
||||
+#define RP1_MIPI0_CSIDMA_BASE 0x110000
|
||||
+#define RP1_MIPI0_CSIHOST_BASE 0x114000
|
||||
+#define RP1_MIPI0_DSIDMA_BASE 0x118000
|
||||
+#define RP1_MIPI0_DSIHOST_BASE 0x11c000
|
||||
+#define RP1_MIPI0_MIPICFG_BASE 0x120000
|
||||
+#define RP1_MIPI0_ISP_BASE 0x124000
|
||||
+#define RP1_MIPI1_CSIDMA_BASE 0x128000
|
||||
+#define RP1_MIPI1_CSIHOST_BASE 0x12c000
|
||||
+#define RP1_MIPI1_DSIDMA_BASE 0x130000
|
||||
+#define RP1_MIPI1_DSIHOST_BASE 0x134000
|
||||
+#define RP1_MIPI1_MIPICFG_BASE 0x138000
|
||||
+#define RP1_MIPI1_ISP_BASE 0x13c000
|
||||
+#define RP1_VIDEO_OUT_CFG_BASE 0x140000
|
||||
+#define RP1_VIDEO_OUT_VEC_BASE 0x144000
|
||||
+#define RP1_VIDEO_OUT_DPI_BASE 0x148000
|
||||
+#define RP1_XOSC_BASE 0x150000
|
||||
+#define RP1_WATCHDOG_BASE 0x154000
|
||||
+#define RP1_DMA_TICK_BASE 0x158000
|
||||
+#define RP1_SDIO_CLOCKS_BASE 0x15c000
|
||||
+#define RP1_USBHOST0_APBS_BASE 0x160000
|
||||
+#define RP1_USBHOST1_APBS_BASE 0x164000
|
||||
+#define RP1_ROSC0_BASE 0x168000
|
||||
+#define RP1_ROSC1_BASE 0x16c000
|
||||
+#define RP1_VBUSCTRL_BASE 0x170000
|
||||
+#define RP1_TICKS_BASE 0x174000
|
||||
+#define RP1_PIO_APBS_BASE 0x178000
|
||||
+#define RP1_SDIO0_AHBLS_BASE 0x180000
|
||||
+#define RP1_SDIO1_AHBLS_BASE 0x184000
|
||||
+#define RP1_DMA_BASE 0x188000
|
||||
+#define RP1_RAM_BASE 0x1c0000
|
||||
+#define RP1_RAM_SIZE 0x020000
|
||||
+#define RP1_USBHOST0_AXIS_BASE 0x200000
|
||||
+#define RP1_USBHOST1_AXIS_BASE 0x300000
|
||||
+#define RP1_EXAC_BASE 0x400000
|
||||
+
|
||||
+/* Interrupts */
|
||||
+
|
||||
+#define RP1_INT_IO_BANK0 0
|
||||
+#define RP1_INT_IO_BANK1 1
|
||||
+#define RP1_INT_IO_BANK2 2
|
||||
+#define RP1_INT_AUDIO_IN 3
|
||||
+#define RP1_INT_AUDIO_OUT 4
|
||||
+#define RP1_INT_PWM0 5
|
||||
+#define RP1_INT_ETH 6
|
||||
+#define RP1_INT_I2C0 7
|
||||
+#define RP1_INT_I2C1 8
|
||||
+#define RP1_INT_I2C2 9
|
||||
+#define RP1_INT_I2C3 10
|
||||
+#define RP1_INT_I2C4 11
|
||||
+#define RP1_INT_I2C5 12
|
||||
+#define RP1_INT_I2C6 13
|
||||
+#define RP1_INT_I2S0 14
|
||||
+#define RP1_INT_I2S1 15
|
||||
+#define RP1_INT_I2S2 16
|
||||
+#define RP1_INT_SDIO0 17
|
||||
+#define RP1_INT_SDIO1 18
|
||||
+#define RP1_INT_SPI0 19
|
||||
+#define RP1_INT_SPI1 20
|
||||
+#define RP1_INT_SPI2 21
|
||||
+#define RP1_INT_SPI3 22
|
||||
+#define RP1_INT_SPI4 23
|
||||
+#define RP1_INT_SPI5 24
|
||||
+#define RP1_INT_UART0 25
|
||||
+#define RP1_INT_TIMER_0 26
|
||||
+#define RP1_INT_TIMER_1 27
|
||||
+#define RP1_INT_TIMER_2 28
|
||||
+#define RP1_INT_TIMER_3 29
|
||||
+#define RP1_INT_USBHOST0 30
|
||||
+#define RP1_INT_USBHOST0_0 31
|
||||
+#define RP1_INT_USBHOST0_1 32
|
||||
+#define RP1_INT_USBHOST0_2 33
|
||||
+#define RP1_INT_USBHOST0_3 34
|
||||
+#define RP1_INT_USBHOST1 35
|
||||
+#define RP1_INT_USBHOST1_0 36
|
||||
+#define RP1_INT_USBHOST1_1 37
|
||||
+#define RP1_INT_USBHOST1_2 38
|
||||
+#define RP1_INT_USBHOST1_3 39
|
||||
+#define RP1_INT_DMA 40
|
||||
+#define RP1_INT_PWM1 41
|
||||
+#define RP1_INT_UART1 42
|
||||
+#define RP1_INT_UART2 43
|
||||
+#define RP1_INT_UART3 44
|
||||
+#define RP1_INT_UART4 45
|
||||
+#define RP1_INT_UART5 46
|
||||
+#define RP1_INT_MIPI0 47
|
||||
+#define RP1_INT_MIPI1 48
|
||||
+#define RP1_INT_VIDEO_OUT 49
|
||||
+#define RP1_INT_PIO_0 50
|
||||
+#define RP1_INT_PIO_1 51
|
||||
+#define RP1_INT_ADC_FIFO 52
|
||||
+#define RP1_INT_PCIE_OUT 53
|
||||
+#define RP1_INT_SPI6 54
|
||||
+#define RP1_INT_SPI7 55
|
||||
+#define RP1_INT_SPI8 56
|
||||
+#define RP1_INT_SYSCFG 58
|
||||
+#define RP1_INT_CLOCKS_DEFAULT 59
|
||||
+#define RP1_INT_VBUSCTRL 60
|
||||
+#define RP1_INT_PROC_MISC 57
|
||||
+#define RP1_INT_END 61
|
||||
+
|
||||
+/* DMA peripherals (for pacing) */
|
||||
+#define RP1_DMA_I2C0_RX 0x0
|
||||
+#define RP1_DMA_I2C0_TX 0x1
|
||||
+#define RP1_DMA_I2C1_RX 0x2
|
||||
+#define RP1_DMA_I2C1_TX 0x3
|
||||
+#define RP1_DMA_I2C2_RX 0x4
|
||||
+#define RP1_DMA_I2C2_TX 0x5
|
||||
+#define RP1_DMA_I2C3_RX 0x6
|
||||
+#define RP1_DMA_I2C3_TX 0x7
|
||||
+#define RP1_DMA_I2C4_RX 0x8
|
||||
+#define RP1_DMA_I2C4_TX 0x9
|
||||
+#define RP1_DMA_I2C5_RX 0xa
|
||||
+#define RP1_DMA_I2C5_TX 0xb
|
||||
+#define RP1_DMA_SPI0_RX 0xc
|
||||
+#define RP1_DMA_SPI0_TX 0xd
|
||||
+#define RP1_DMA_SPI1_RX 0xe
|
||||
+#define RP1_DMA_SPI1_TX 0xf
|
||||
+#define RP1_DMA_SPI2_RX 0x10
|
||||
+#define RP1_DMA_SPI2_TX 0x11
|
||||
+#define RP1_DMA_SPI3_RX 0x12
|
||||
+#define RP1_DMA_SPI3_TX 0x13
|
||||
+#define RP1_DMA_SPI4_RX 0x14
|
||||
+#define RP1_DMA_SPI4_TX 0x15
|
||||
+#define RP1_DMA_SPI5_RX 0x16
|
||||
+#define RP1_DMA_SPI5_TX 0x17
|
||||
+#define RP1_DMA_PWM0 0x18
|
||||
+#define RP1_DMA_UART0_RX 0x19
|
||||
+#define RP1_DMA_UART0_TX 0x1a
|
||||
+#define RP1_DMA_AUDIO_IN_CH0 0x1b
|
||||
+#define RP1_DMA_AUDIO_IN_CH1 0x1c
|
||||
+#define RP1_DMA_AUDIO_OUT 0x1d
|
||||
+#define RP1_DMA_PWM1 0x1e
|
||||
+#define RP1_DMA_I2S0_RX 0x1f
|
||||
+#define RP1_DMA_I2S0_TX 0x20
|
||||
+#define RP1_DMA_I2S1_RX 0x21
|
||||
+#define RP1_DMA_I2S1_TX 0x22
|
||||
+#define RP1_DMA_I2S2_RX 0x23
|
||||
+#define RP1_DMA_I2S2_TX 0x24
|
||||
+#define RP1_DMA_UART1_RX 0x25
|
||||
+#define RP1_DMA_UART1_TX 0x26
|
||||
+#define RP1_DMA_UART2_RX 0x27
|
||||
+#define RP1_DMA_UART2_TX 0x28
|
||||
+#define RP1_DMA_UART3_RX 0x29
|
||||
+#define RP1_DMA_UART3_TX 0x2a
|
||||
+#define RP1_DMA_UART4_RX 0x2b
|
||||
+#define RP1_DMA_UART4_TX 0x2c
|
||||
+#define RP1_DMA_UART5_RX 0x2d
|
||||
+#define RP1_DMA_UART5_TX 0x2e
|
||||
+#define RP1_DMA_ADC 0x2f
|
||||
+#define RP1_DMA_DMA_TICK_TICK0 0x30
|
||||
+#define RP1_DMA_DMA_TICK_TICK1 0x31
|
||||
+#define RP1_DMA_SPI6_RX 0x32
|
||||
+#define RP1_DMA_SPI6_TX 0x33
|
||||
+#define RP1_DMA_SPI7_RX 0x34
|
||||
+#define RP1_DMA_SPI7_TX 0x35
|
||||
+#define RP1_DMA_SPI8_RX 0x36
|
||||
+#define RP1_DMA_SPI8_TX 0x37
|
||||
+#define RP1_DMA_PIO_CH0_TX 0x38
|
||||
+#define RP1_DMA_PIO_CH0_RX 0x39
|
||||
+#define RP1_DMA_PIO_CH1_TX 0x3a
|
||||
+#define RP1_DMA_PIO_CH1_RX 0x3b
|
||||
+#define RP1_DMA_PIO_CH2_TX 0x3c
|
||||
+#define RP1_DMA_PIO_CH2_RX 0x3d
|
||||
+#define RP1_DMA_PIO_CH3_TX 0x3e
|
||||
+#define RP1_DMA_PIO_CH3_RX 0x3f
|
||||
+
|
||||
+#endif
|
@ -0,0 +1,442 @@
|
||||
From 7196a12b94e90225686e6c34cdf65a583214f7a5 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Mon, 10 Oct 2022 14:21:50 +0100
|
||||
Subject: [PATCH] mfd: Add rp1 driver
|
||||
|
||||
RP1 is a multifunction PCIe device that exposes a range of
|
||||
peripherals.
|
||||
Add the parent driver to manage these.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/mfd/Kconfig | 11 ++
|
||||
drivers/mfd/Makefile | 1 +
|
||||
drivers/mfd/rp1.c | 367 +++++++++++++++++++++++++++++++++++
|
||||
include/linux/rp1_platform.h | 20 ++
|
||||
4 files changed, 399 insertions(+)
|
||||
create mode 100644 drivers/mfd/rp1.c
|
||||
create mode 100644 include/linux/rp1_platform.h
|
||||
|
||||
--- a/drivers/mfd/Kconfig
|
||||
+++ b/drivers/mfd/Kconfig
|
||||
@@ -2252,6 +2252,17 @@ config MFD_INTEL_M10_BMC
|
||||
additional drivers must be enabled in order to use the functionality
|
||||
of the device.
|
||||
|
||||
+config MFD_RP1
|
||||
+ tristate "RP1 MFD driver"
|
||||
+ depends on PCI
|
||||
+ select MFD_CORE
|
||||
+ help
|
||||
+ Support for the RP1 peripheral chip.
|
||||
+
|
||||
+ This driver provides support for the Raspberry Pi RP1 peripheral chip.
|
||||
+ It is responsible for enabling the Device Tree node once the PCIe endpoint
|
||||
+ has been configured, and handling interrupts.
|
||||
+
|
||||
config MFD_RSMU_I2C
|
||||
tristate "Renesas Synchronization Management Unit with I2C"
|
||||
depends on I2C && OF
|
||||
--- a/drivers/mfd/Makefile
|
||||
+++ b/drivers/mfd/Makefile
|
||||
@@ -273,6 +273,7 @@ obj-$(CONFIG_MFD_RPISENSE_CORE) += rpise
|
||||
obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o
|
||||
obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o
|
||||
obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o
|
||||
+obj-$(CONFIG_MFD_RP1) += rp1.o
|
||||
|
||||
obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o
|
||||
obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/mfd/rp1.c
|
||||
@@ -0,0 +1,367 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (c) 2018-22 Raspberry Pi Ltd.
|
||||
+ * All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/clkdev.h>
|
||||
+#include <linux/clk-provider.h>
|
||||
+#include <linux/completion.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/irqchip/chained_irq.h>
|
||||
+#include <linux/irqdomain.h>
|
||||
+#include <linux/mfd/core.h>
|
||||
+#include <linux/mmc/host.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/msi.h>
|
||||
+#include <linux/of_platform.h>
|
||||
+#include <linux/pci.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/rp1_platform.h>
|
||||
+#include <linux/reset.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+#include <dt-bindings/mfd/rp1.h>
|
||||
+
|
||||
+/* TO DO:
|
||||
+ * 1. Occasional shutdown crash - RP1 being closed before its children?
|
||||
+ * 2. DT mode interrupt handling.
|
||||
+ */
|
||||
+
|
||||
+#define RP1_DRIVER_NAME "rp1"
|
||||
+
|
||||
+#define PCI_VENDOR_ID_RPI 0x1de4
|
||||
+#define PCI_DEVICE_ID_RP1_C0 0x0001
|
||||
+#define PCI_DEVICE_REV_RP1_C0 2
|
||||
+
|
||||
+#define RP1_ACTUAL_IRQS RP1_INT_END
|
||||
+#define RP1_IRQS RP1_ACTUAL_IRQS
|
||||
+
|
||||
+#define RP1_SYSCLK_RATE 200000000
|
||||
+#define RP1_SYSCLK_FPGA_RATE 60000000
|
||||
+
|
||||
+// Don't want to include the whole sysinfo reg header
|
||||
+#define SYSINFO_CHIP_ID_OFFSET 0x00000000
|
||||
+#define SYSINFO_PLATFORM_OFFSET 0x00000004
|
||||
+
|
||||
+#define REG_RW 0x000
|
||||
+#define REG_SET 0x800
|
||||
+#define REG_CLR 0xc00
|
||||
+
|
||||
+// MSIX CFG registers start at 0x8
|
||||
+#define MSIX_CFG(x) (0x8 + (4 * (x)))
|
||||
+
|
||||
+#define MSIX_CFG_IACK_EN BIT(3)
|
||||
+#define MSIX_CFG_IACK BIT(2)
|
||||
+#define MSIX_CFG_TEST BIT(1)
|
||||
+#define MSIX_CFG_ENABLE BIT(0)
|
||||
+
|
||||
+#define INTSTATL 0x108
|
||||
+#define INTSTATH 0x10c
|
||||
+
|
||||
+struct rp1_dev {
|
||||
+ struct pci_dev *pdev;
|
||||
+ struct device *dev;
|
||||
+ resource_size_t bar_start;
|
||||
+ resource_size_t bar_end;
|
||||
+ struct clk *sys_clk;
|
||||
+ struct irq_domain *domain;
|
||||
+ struct irq_data *pcie_irqds[64];
|
||||
+ void __iomem *msix_cfg_regs;
|
||||
+};
|
||||
+
|
||||
+static bool rp1_level_triggered_irq[RP1_ACTUAL_IRQS] = { 0 };
|
||||
+
|
||||
+static struct rp1_dev *g_rp1;
|
||||
+static u32 g_chip_id, g_platform;
|
||||
+
|
||||
+static void dump_bar(struct pci_dev *pdev, unsigned int bar)
|
||||
+{
|
||||
+ dev_info(&pdev->dev,
|
||||
+ "bar%d len 0x%llx, start 0x%llx, end 0x%llx, flags, 0x%lx\n",
|
||||
+ bar,
|
||||
+ pci_resource_len(pdev, bar),
|
||||
+ pci_resource_start(pdev, bar),
|
||||
+ pci_resource_end(pdev, bar),
|
||||
+ pci_resource_flags(pdev, bar));
|
||||
+}
|
||||
+
|
||||
+static void msix_cfg_set(struct rp1_dev *rp1, unsigned int hwirq, u32 value)
|
||||
+{
|
||||
+ writel(value, rp1->msix_cfg_regs + REG_SET + MSIX_CFG(hwirq));
|
||||
+}
|
||||
+
|
||||
+static void msix_cfg_clr(struct rp1_dev *rp1, unsigned int hwirq, u32 value)
|
||||
+{
|
||||
+ writel(value, rp1->msix_cfg_regs + REG_CLR + MSIX_CFG(hwirq));
|
||||
+}
|
||||
+
|
||||
+static void rp1_mask_irq(struct irq_data *irqd)
|
||||
+{
|
||||
+ struct rp1_dev *rp1 = irqd->domain->host_data;
|
||||
+ struct irq_data *pcie_irqd = rp1->pcie_irqds[irqd->hwirq];
|
||||
+
|
||||
+ pci_msi_mask_irq(pcie_irqd);
|
||||
+}
|
||||
+
|
||||
+static void rp1_unmask_irq(struct irq_data *irqd)
|
||||
+{
|
||||
+ struct rp1_dev *rp1 = irqd->domain->host_data;
|
||||
+ struct irq_data *pcie_irqd = rp1->pcie_irqds[irqd->hwirq];
|
||||
+
|
||||
+ pci_msi_unmask_irq(pcie_irqd);
|
||||
+}
|
||||
+
|
||||
+static int rp1_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
+{
|
||||
+ struct rp1_dev *rp1 = irqd->domain->host_data;
|
||||
+ unsigned int hwirq = (unsigned int)irqd->hwirq;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case IRQ_TYPE_LEVEL_HIGH:
|
||||
+ dev_dbg(rp1->dev, "MSIX IACK EN for irq %d\n", hwirq);
|
||||
+ msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK_EN);
|
||||
+ rp1_level_triggered_irq[hwirq] = true;
|
||||
+ break;
|
||||
+ case IRQ_TYPE_EDGE_RISING:
|
||||
+ msix_cfg_clr(rp1, hwirq, MSIX_CFG_IACK_EN);
|
||||
+ rp1_level_triggered_irq[hwirq] = false;
|
||||
+ break;
|
||||
+ default:
|
||||
+ ret = -EINVAL;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static struct irq_chip rp1_irq_chip = {
|
||||
+ .name = "rp1_irq_chip",
|
||||
+ .irq_mask = rp1_mask_irq,
|
||||
+ .irq_unmask = rp1_unmask_irq,
|
||||
+ .irq_set_type = rp1_irq_set_type,
|
||||
+};
|
||||
+
|
||||
+static void rp1_chained_handle_irq(struct irq_desc *desc)
|
||||
+{
|
||||
+ struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
+ struct rp1_dev *rp1 = desc->irq_data.chip_data;
|
||||
+ unsigned int hwirq = desc->irq_data.hwirq & 0x3f;
|
||||
+ int new_irq;
|
||||
+
|
||||
+ rp1 = g_rp1;
|
||||
+
|
||||
+ chained_irq_enter(chip, desc);
|
||||
+
|
||||
+ new_irq = irq_linear_revmap(rp1->domain, hwirq);
|
||||
+ generic_handle_irq(new_irq);
|
||||
+ if (rp1_level_triggered_irq[hwirq])
|
||||
+ msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK);
|
||||
+
|
||||
+ chained_irq_exit(chip, desc);
|
||||
+}
|
||||
+
|
||||
+static int rp1_irq_xlate(struct irq_domain *d, struct device_node *node,
|
||||
+ const u32 *intspec, unsigned int intsize,
|
||||
+ unsigned long *out_hwirq, unsigned int *out_type)
|
||||
+{
|
||||
+ struct rp1_dev *rp1 = d->host_data;
|
||||
+ struct irq_data *pcie_irqd;
|
||||
+ unsigned long hwirq;
|
||||
+ int pcie_irq;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = irq_domain_xlate_twocell(d, node, intspec, intsize,
|
||||
+ &hwirq, out_type);
|
||||
+ if (!ret) {
|
||||
+ pcie_irq = pci_irq_vector(rp1->pdev, hwirq);
|
||||
+ pcie_irqd = irq_get_irq_data(pcie_irq);
|
||||
+ rp1->pcie_irqds[hwirq] = pcie_irqd;
|
||||
+ *out_hwirq = hwirq;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int rp1_irq_activate(struct irq_domain *d, struct irq_data *irqd,
|
||||
+ bool reserve)
|
||||
+{
|
||||
+ struct rp1_dev *rp1 = d->host_data;
|
||||
+ struct irq_data *pcie_irqd;
|
||||
+
|
||||
+ pcie_irqd = rp1->pcie_irqds[irqd->hwirq];
|
||||
+ msix_cfg_set(rp1, (unsigned int)irqd->hwirq, MSIX_CFG_ENABLE);
|
||||
+ return irq_domain_activate_irq(pcie_irqd, reserve);
|
||||
+}
|
||||
+
|
||||
+static void rp1_irq_deactivate(struct irq_domain *d, struct irq_data *irqd)
|
||||
+{
|
||||
+ struct rp1_dev *rp1 = d->host_data;
|
||||
+ struct irq_data *pcie_irqd;
|
||||
+
|
||||
+ pcie_irqd = rp1->pcie_irqds[irqd->hwirq];
|
||||
+ msix_cfg_clr(rp1, (unsigned int)irqd->hwirq, MSIX_CFG_ENABLE);
|
||||
+ return irq_domain_deactivate_irq(pcie_irqd);
|
||||
+}
|
||||
+
|
||||
+static const struct irq_domain_ops rp1_domain_ops = {
|
||||
+ .xlate = rp1_irq_xlate,
|
||||
+ .activate = rp1_irq_activate,
|
||||
+ .deactivate = rp1_irq_deactivate,
|
||||
+};
|
||||
+
|
||||
+static inline dma_addr_t rp1_io_to_phys(struct rp1_dev *rp1, unsigned int offset)
|
||||
+{
|
||||
+ return rp1->bar_start + offset;
|
||||
+}
|
||||
+
|
||||
+static u32 rp1_reg_read(struct rp1_dev *rp1, unsigned int base_addr, u32 offset)
|
||||
+{
|
||||
+ dma_addr_t phys = rp1_io_to_phys(rp1, base_addr);
|
||||
+ void __iomem *regblock = ioremap(phys, 0x1000);
|
||||
+ u32 value = readl(regblock + offset);
|
||||
+
|
||||
+ iounmap(regblock);
|
||||
+ return value;
|
||||
+}
|
||||
+
|
||||
+void rp1_get_platform(u32 *chip_id, u32 *platform)
|
||||
+{
|
||||
+ if (chip_id)
|
||||
+ *chip_id = g_chip_id;
|
||||
+ if (platform)
|
||||
+ *platform = g_platform;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rp1_get_platform);
|
||||
+
|
||||
+static int rp1_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
+{
|
||||
+ struct reset_control *reset;
|
||||
+ struct platform_device *pcie_pdev;
|
||||
+ struct device_node *rp1_node;
|
||||
+ struct rp1_dev *rp1;
|
||||
+ int err = 0;
|
||||
+ int i;
|
||||
+
|
||||
+ reset = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
|
||||
+ if (IS_ERR(reset))
|
||||
+ return PTR_ERR(reset);
|
||||
+ reset_control_reset(reset);
|
||||
+
|
||||
+ dump_bar(pdev, 0);
|
||||
+ dump_bar(pdev, 1);
|
||||
+
|
||||
+ if (pci_resource_len(pdev, 1) <= 0x10000) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "Not initialised - is the firmware running?\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* enable pci device */
|
||||
+ err = pcim_enable_device(pdev);
|
||||
+ if (err < 0) {
|
||||
+ dev_err(&pdev->dev, "Enabling PCI device has failed: %d",
|
||||
+ err);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ pci_set_master(pdev);
|
||||
+
|
||||
+ err = pci_alloc_irq_vectors(pdev, RP1_IRQS, RP1_IRQS,
|
||||
+ PCI_IRQ_MSIX);
|
||||
+ if (err != RP1_IRQS) {
|
||||
+ dev_err(&pdev->dev, "pci_alloc_irq_vectors failed - %d\n", err);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ rp1 = devm_kzalloc(&pdev->dev, sizeof(*rp1), GFP_KERNEL);
|
||||
+ if (!rp1)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ rp1->pdev = pdev;
|
||||
+ rp1->dev = &pdev->dev;
|
||||
+
|
||||
+ pci_set_drvdata(pdev, rp1);
|
||||
+
|
||||
+ rp1->bar_start = pci_resource_start(pdev, 1);
|
||||
+ rp1->bar_end = pci_resource_end(pdev, 1);
|
||||
+
|
||||
+ // Get chip id
|
||||
+ g_chip_id = rp1_reg_read(rp1, RP1_SYSINFO_BASE, SYSINFO_CHIP_ID_OFFSET);
|
||||
+ g_platform = rp1_reg_read(rp1, RP1_SYSINFO_BASE, SYSINFO_PLATFORM_OFFSET);
|
||||
+ dev_info(&pdev->dev, "chip_id 0x%x%s\n", g_chip_id,
|
||||
+ (g_platform & RP1_PLATFORM_FPGA) ? " FPGA" : "");
|
||||
+ if (g_chip_id != RP1_C0_CHIP_ID) {
|
||||
+ dev_err(&pdev->dev, "wrong chip id (%x)\n", g_chip_id);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ rp1_node = of_find_node_by_name(NULL, "rp1");
|
||||
+ if (!rp1_node) {
|
||||
+ dev_err(&pdev->dev, "failed to find RP1 DT node\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ pcie_pdev = of_find_device_by_node(rp1_node->parent);
|
||||
+ rp1->domain = irq_domain_add_linear(rp1_node, RP1_IRQS,
|
||||
+ &rp1_domain_ops, rp1);
|
||||
+
|
||||
+ g_rp1 = rp1;
|
||||
+
|
||||
+ /* TODO can this go in the rp1 device tree entry? */
|
||||
+ rp1->msix_cfg_regs = ioremap(rp1_io_to_phys(rp1, RP1_PCIE_APBS_BASE), 0x1000);
|
||||
+
|
||||
+ for (i = 0; i < RP1_IRQS; i++) {
|
||||
+ int irq = irq_create_mapping(rp1->domain, i);
|
||||
+
|
||||
+ if (irq < 0) {
|
||||
+ dev_err(&pdev->dev, "failed to create irq mapping\n");
|
||||
+ return irq;
|
||||
+ }
|
||||
+
|
||||
+ irq_set_chip_data(irq, rp1);
|
||||
+ irq_set_chip_and_handler(irq, &rp1_irq_chip, handle_level_irq);
|
||||
+ irq_set_probe(irq);
|
||||
+ irq_set_chained_handler(pci_irq_vector(pdev, i),
|
||||
+ rp1_chained_handle_irq);
|
||||
+ }
|
||||
+
|
||||
+ if (rp1_node)
|
||||
+ of_platform_populate(rp1_node, NULL, NULL, &pcie_pdev->dev);
|
||||
+
|
||||
+ of_node_put(rp1_node);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void rp1_remove(struct pci_dev *pdev)
|
||||
+{
|
||||
+ struct rp1_dev *rp1 = pci_get_drvdata(pdev);
|
||||
+
|
||||
+ mfd_remove_devices(&pdev->dev);
|
||||
+
|
||||
+ clk_unregister(rp1->sys_clk);
|
||||
+}
|
||||
+
|
||||
+static const struct pci_device_id dev_id_table[] = {
|
||||
+ { PCI_DEVICE(PCI_VENDOR_ID_RPI, PCI_DEVICE_ID_RP1_C0), },
|
||||
+ { 0, }
|
||||
+};
|
||||
+
|
||||
+static struct pci_driver rp1_driver = {
|
||||
+ .name = RP1_DRIVER_NAME,
|
||||
+ .id_table = dev_id_table,
|
||||
+ .probe = rp1_probe,
|
||||
+ .remove = rp1_remove,
|
||||
+};
|
||||
+
|
||||
+module_pci_driver(rp1_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.com>");
|
||||
+MODULE_DESCRIPTION("RP1 wrapper");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--- /dev/null
|
||||
+++ b/include/linux/rp1_platform.h
|
||||
@@ -0,0 +1,20 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0 */
|
||||
+/*
|
||||
+ * Copyright (c) 2021-2022 Raspberry Pi Ltd.
|
||||
+ * All rights reserved.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _RP1_PLATFORM_H
|
||||
+#define _RP1_PLATFORM_H
|
||||
+
|
||||
+#include <vdso/bits.h>
|
||||
+
|
||||
+#define RP1_B0_CHIP_ID 0x10001927
|
||||
+#define RP1_C0_CHIP_ID 0x20001927
|
||||
+
|
||||
+#define RP1_PLATFORM_ASIC BIT(1)
|
||||
+#define RP1_PLATFORM_FPGA BIT(0)
|
||||
+
|
||||
+void rp1_get_platform(u32 *chip_id, u32 *platform);
|
||||
+
|
||||
+#endif
|
65
target/linux/bcm27xx/patches-6.1/950-0873-dt-bindings-clock-Add-bindings-for-Raspberry-Pi-RP1.patch
Normal file
65
target/linux/bcm27xx/patches-6.1/950-0873-dt-bindings-clock-Add-bindings-for-Raspberry-Pi-RP1.patch
Normal file
@ -0,0 +1,65 @@
|
||||
From 00ff2819eb852b54fe22e7181646e40d560576dc Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Fri, 28 Oct 2022 14:12:18 +0100
|
||||
Subject: [PATCH] dt-bindings: clock: Add bindings for Raspberry Pi RP1
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
include/dt-bindings/clock/rp1.h | 51 +++++++++++++++++++++++++++++++++
|
||||
1 file changed, 51 insertions(+)
|
||||
create mode 100644 include/dt-bindings/clock/rp1.h
|
||||
|
||||
--- /dev/null
|
||||
+++ b/include/dt-bindings/clock/rp1.h
|
||||
@@ -0,0 +1,51 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0 */
|
||||
+/*
|
||||
+ * Copyright (C) 2021 Raspberry Pi Ltd.
|
||||
+ */
|
||||
+
|
||||
+#define RP1_PLL_SYS_CORE 0
|
||||
+#define RP1_PLL_AUDIO_CORE 1
|
||||
+#define RP1_PLL_VIDEO_CORE 2
|
||||
+
|
||||
+#define RP1_PLL_SYS 3
|
||||
+#define RP1_PLL_AUDIO 4
|
||||
+#define RP1_PLL_VIDEO 5
|
||||
+
|
||||
+#define RP1_PLL_SYS_PRI_PH 6
|
||||
+#define RP1_PLL_SYS_SEC_PH 7
|
||||
+
|
||||
+#define RP1_PLL_SYS_SEC 8
|
||||
+#define RP1_PLL_AUDIO_SEC 9
|
||||
+#define RP1_PLL_VIDEO_SEC 10
|
||||
+
|
||||
+#define RP1_CLK_SYS 11
|
||||
+#define RP1_CLK_SLOW_SYS 12
|
||||
+#define RP1_CLK_DMA 13
|
||||
+#define RP1_CLK_UART 14
|
||||
+#define RP1_CLK_ETH 15
|
||||
+#define RP1_CLK_PWM0 16
|
||||
+#define RP1_CLK_PWM1 17
|
||||
+#define RP1_CLK_AUDIO_IN 18
|
||||
+#define RP1_CLK_AUDIO_OUT 19
|
||||
+#define RP1_CLK_I2S 20
|
||||
+#define RP1_CLK_MIPI0_CFG 21
|
||||
+#define RP1_CLK_MIPI1_CFG 22
|
||||
+#define RP1_CLK_PCIE_AUX 23
|
||||
+#define RP1_CLK_USBH0_MICROFRAME 24
|
||||
+#define RP1_CLK_USBH1_MICROFRAME 25
|
||||
+#define RP1_CLK_USBH0_SUSPEND 26
|
||||
+#define RP1_CLK_USBH1_SUSPEND 27
|
||||
+#define RP1_CLK_ETH_TSU 28
|
||||
+#define RP1_CLK_ADC 29
|
||||
+#define RP1_CLK_SDIO_TIMER 30
|
||||
+#define RP1_CLK_SDIO_ALT_SRC 31
|
||||
+#define RP1_CLK_GP0 32
|
||||
+#define RP1_CLK_GP1 33
|
||||
+#define RP1_CLK_GP2 34
|
||||
+#define RP1_CLK_GP3 35
|
||||
+#define RP1_CLK_GP4 36
|
||||
+#define RP1_CLK_GP5 37
|
||||
+#define RP1_CLK_VEC 38
|
||||
+#define RP1_CLK_DPI 39
|
||||
+#define RP1_CLK_MIPI0_DPI 40
|
||||
+#define RP1_CLK_MIPI1_DPI 41
|
File diff suppressed because it is too large
Load Diff
60
target/linux/bcm27xx/patches-6.1/950-0875-dt-bindings-pinctrl-Add-bindings-for-Raspberry-Pi-RP.patch
Normal file
60
target/linux/bcm27xx/patches-6.1/950-0875-dt-bindings-pinctrl-Add-bindings-for-Raspberry-Pi-RP.patch
Normal file
@ -0,0 +1,60 @@
|
||||
From 19b934ce3763c9465c5c80302f7c142d30b75869 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Fri, 28 Oct 2022 14:13:30 +0100
|
||||
Subject: [PATCH] dt-bindings: pinctrl: Add bindings for Raspberry Pi RP1
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
include/dt-bindings/pinctrl/rp1.h | 46 +++++++++++++++++++++++++++++++
|
||||
1 file changed, 46 insertions(+)
|
||||
create mode 100644 include/dt-bindings/pinctrl/rp1.h
|
||||
|
||||
--- /dev/null
|
||||
+++ b/include/dt-bindings/pinctrl/rp1.h
|
||||
@@ -0,0 +1,46 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0 */
|
||||
+/*
|
||||
+ * Header providing constants for RP1 pinctrl bindings.
|
||||
+ *
|
||||
+ * Copyright (C) 2019-2022 Raspberry Pi Ltd.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __DT_BINDINGS_PINCTRL_RP1_H__
|
||||
+#define __DT_BINDINGS_PINCTRL_RP1_H__
|
||||
+
|
||||
+/* brcm,function property */
|
||||
+#define RP1_FSEL_GPIO_IN 0
|
||||
+#define RP1_FSEL_GPIO_OUT 1
|
||||
+#define RP1_FSEL_ALT0_LEGACY 4
|
||||
+#define RP1_FSEL_ALT1_LEGACY 5
|
||||
+#define RP1_FSEL_ALT2_LEGACY 6
|
||||
+#define RP1_FSEL_ALT3_LEGACY 7
|
||||
+#define RP1_FSEL_ALT4_LEGACY 3
|
||||
+#define RP1_FSEL_ALT5_LEGACY 2
|
||||
+#define RP1_FSEL_ALT0 0x08
|
||||
+#define RP1_FSEL_ALT0INV 0x09
|
||||
+#define RP1_FSEL_ALT1 0x0a
|
||||
+#define RP1_FSEL_ALT1INV 0x0b
|
||||
+#define RP1_FSEL_ALT2 0x0c
|
||||
+#define RP1_FSEL_ALT2INV 0x0d
|
||||
+#define RP1_FSEL_ALT3 0x0e
|
||||
+#define RP1_FSEL_ALT3INV 0x0f
|
||||
+#define RP1_FSEL_ALT4 0x10
|
||||
+#define RP1_FSEL_ALT4INV 0x11
|
||||
+#define RP1_FSEL_ALT5 0x12
|
||||
+#define RP1_FSEL_ALT5INV 0x13
|
||||
+#define RP1_FSEL_ALT6 0x14
|
||||
+#define RP1_FSEL_ALT6INV 0x15
|
||||
+#define RP1_FSEL_ALT7 0x16
|
||||
+#define RP1_FSEL_ALT7INV 0x17
|
||||
+#define RP1_FSEL_ALT8 0x18
|
||||
+#define RP1_FSEL_ALT8INV 0x19
|
||||
+#define RP1_FSEL_NONE 0x1a
|
||||
+
|
||||
+/* brcm,pull property */
|
||||
+#define RP1_PUD_OFF 0
|
||||
+#define RP1_PUD_DOWN 1
|
||||
+#define RP1_PUD_UP 2
|
||||
+#define RP1_PUD_KEEP 3
|
||||
+
|
||||
+#endif /* __DT_BINDINGS_PINCTRL_RP1_H__ */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,129 @@
|
||||
From f88da9e21d8eff58eeb9280ae96bf9593121d8eb Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Wed, 12 Oct 2022 13:24:51 +0100
|
||||
Subject: [PATCH] serial: pl011: rp1 uart support
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/tty/serial/amba-pl011.c | 96 +++++++++++++++++++++++++++++++++
|
||||
1 file changed, 96 insertions(+)
|
||||
|
||||
--- a/drivers/tty/serial/amba-pl011.c
|
||||
+++ b/drivers/tty/serial/amba-pl011.c
|
||||
@@ -152,6 +152,20 @@ static const struct vendor_data vendor_s
|
||||
.fixed_options = true,
|
||||
};
|
||||
|
||||
+static struct vendor_data vendor_arm_axi = {
|
||||
+ .reg_offset = pl011_std_offsets,
|
||||
+ .ifls = UART011_IFLS_RX4_8 | UART011_IFLS_TX4_8,
|
||||
+ .fr_busy = UART01x_FR_BUSY,
|
||||
+ .fr_dsr = UART01x_FR_DSR,
|
||||
+ .fr_cts = UART01x_FR_CTS,
|
||||
+ .fr_ri = UART011_FR_RI,
|
||||
+ .oversampling = false,
|
||||
+ .dma_threshold = false,
|
||||
+ .cts_event_workaround = false,
|
||||
+ .always_enabled = false,
|
||||
+ .fixed_options = false,
|
||||
+};
|
||||
+
|
||||
#ifdef CONFIG_ACPI_SPCR_TABLE
|
||||
static const struct vendor_data vendor_qdt_qdf2400_e44 = {
|
||||
.reg_offset = pl011_std_offsets,
|
||||
@@ -2972,6 +2986,86 @@ static struct platform_driver arm_sbsa_u
|
||||
},
|
||||
};
|
||||
|
||||
+static int pl011_axi_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct uart_amba_port *uap;
|
||||
+ struct vendor_data *vendor = &vendor_arm_axi;
|
||||
+ struct resource *r;
|
||||
+ unsigned int periphid;
|
||||
+ int portnr, ret, irq;
|
||||
+
|
||||
+ portnr = pl011_find_free_port();
|
||||
+ if (portnr < 0)
|
||||
+ return portnr;
|
||||
+
|
||||
+ uap = devm_kzalloc(&pdev->dev, sizeof(struct uart_amba_port),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!uap)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ uap->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
+ if (IS_ERR(uap->clk))
|
||||
+ return PTR_ERR(uap->clk);
|
||||
+
|
||||
+ if (of_property_read_bool(pdev->dev.of_node, "cts-event-workaround")) {
|
||||
+ vendor->cts_event_workaround = true;
|
||||
+ dev_info(&pdev->dev, "cts_event_workaround enabled\n");
|
||||
+ }
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ if (irq < 0)
|
||||
+ return irq;
|
||||
+
|
||||
+ periphid = 0x00241011; /* A safe default */
|
||||
+ of_property_read_u32(pdev->dev.of_node, "arm,primecell-periphid",
|
||||
+ &periphid);
|
||||
+
|
||||
+ uap->reg_offset = vendor->reg_offset;
|
||||
+ uap->vendor = vendor;
|
||||
+ uap->fifosize = (AMBA_REV_BITS(periphid) < 3) ? 16 : 32;
|
||||
+ uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM;
|
||||
+ uap->port.irq = irq;
|
||||
+ uap->port.ops = &amba_pl011_pops;
|
||||
+
|
||||
+ snprintf(uap->type, sizeof(uap->type), "PL011 AXI");
|
||||
+
|
||||
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+
|
||||
+ ret = pl011_setup_port(&pdev->dev, uap, r, portnr);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, uap);
|
||||
+
|
||||
+ return pl011_register_port(uap);
|
||||
+}
|
||||
+
|
||||
+static int pl011_axi_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct uart_amba_port *uap = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ uart_remove_one_port(&amba_reg, &uap->port);
|
||||
+ pl011_unregister_port(uap);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id pl011_axi_of_match[] = {
|
||||
+ { .compatible = "arm,pl011-axi" },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, pl011_axi_of_match);
|
||||
+
|
||||
+static struct platform_driver pl011_axi_platform_driver = {
|
||||
+ .probe = pl011_axi_probe,
|
||||
+ .remove = pl011_axi_remove,
|
||||
+ .driver = {
|
||||
+ .name = "pl011-axi",
|
||||
+ .pm = &pl011_dev_pm_ops,
|
||||
+ .of_match_table = of_match_ptr(pl011_axi_of_match),
|
||||
+ .suppress_bind_attrs = IS_BUILTIN(CONFIG_SERIAL_AMBA_PL011),
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static const struct amba_id pl011_ids[] = {
|
||||
{
|
||||
.id = 0x00041011,
|
||||
@@ -3005,6 +3099,8 @@ static int __init pl011_init(void)
|
||||
|
||||
if (platform_driver_register(&arm_sbsa_uart_platform_driver))
|
||||
pr_warn("could not register SBSA UART platform driver\n");
|
||||
+ if (platform_driver_register(&pl011_axi_platform_driver))
|
||||
+ pr_warn("could not register PL011 AXI platform driver\n");
|
||||
return amba_driver_register(&pl011_driver);
|
||||
}
|
||||
|
83
target/linux/bcm27xx/patches-6.1/950-0878-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch
Normal file
83
target/linux/bcm27xx/patches-6.1/950-0878-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch
Normal file
@ -0,0 +1,83 @@
|
||||
From 4a5ac516ca0a820e7c006ae408872009e37e114b Mon Sep 17 00:00:00 2001
|
||||
From: Liam Fraser <liam@raspberrypi.com>
|
||||
Date: Thu, 14 Mar 2019 16:01:26 +0000
|
||||
Subject: [PATCH] mmc: sdhci-of-dwcmshc: define sdio timeout clocks
|
||||
|
||||
Signed-off-by: Liam Fraser <liam@raspberrypi.com>
|
||||
---
|
||||
drivers/mmc/host/sdhci-of-dwcmshc.c | 12 ++++++++++++
|
||||
drivers/mmc/host/sdhci-pltfm.c | 8 ++++++++
|
||||
drivers/mmc/host/sdhci-pltfm.h | 3 +++
|
||||
3 files changed, 23 insertions(+)
|
||||
|
||||
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
@@ -330,6 +330,7 @@ static const struct sdhci_ops sdhci_dwcm
|
||||
.set_bus_width = sdhci_set_bus_width,
|
||||
.set_uhs_signaling = dwcmshc_set_uhs_signaling,
|
||||
.get_max_clock = dwcmshc_get_max_clock,
|
||||
+ .get_timeout_clock = sdhci_pltfm_clk_get_timeout_clock,
|
||||
.reset = sdhci_reset,
|
||||
.adma_write_desc = dwcmshc_adma_write_desc,
|
||||
};
|
||||
@@ -500,6 +501,16 @@ static int dwcmshc_probe(struct platform
|
||||
clk_prepare_enable(priv->bus_clk);
|
||||
}
|
||||
|
||||
+ pltfm_host->timeout_clk = devm_clk_get(&pdev->dev, "timeout");
|
||||
+ if (IS_ERR(pltfm_host->timeout_clk)) {
|
||||
+ err = PTR_ERR(pltfm_host->timeout_clk);
|
||||
+ dev_err(&pdev->dev, "failed to get timeout clk: %d\n", err);
|
||||
+ goto free_pltfm;
|
||||
+ }
|
||||
+ err = clk_prepare_enable(pltfm_host->timeout_clk);
|
||||
+ if (err)
|
||||
+ goto free_pltfm;
|
||||
+
|
||||
err = mmc_of_parse(host->mmc);
|
||||
if (err)
|
||||
goto err_clk;
|
||||
@@ -550,6 +561,7 @@ err_setup_host:
|
||||
sdhci_cleanup_host(host);
|
||||
err_clk:
|
||||
clk_disable_unprepare(pltfm_host->clk);
|
||||
+ clk_disable_unprepare(pltfm_host->timeout_clk);
|
||||
clk_disable_unprepare(priv->bus_clk);
|
||||
if (rk_priv)
|
||||
clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
|
||||
--- a/drivers/mmc/host/sdhci-pltfm.c
|
||||
+++ b/drivers/mmc/host/sdhci-pltfm.c
|
||||
@@ -33,6 +33,14 @@ unsigned int sdhci_pltfm_clk_get_max_clo
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
|
||||
|
||||
+unsigned int sdhci_pltfm_clk_get_timeout_clock(struct sdhci_host *host)
|
||||
+{
|
||||
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
+
|
||||
+ return clk_get_rate(pltfm_host->timeout_clk);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_timeout_clock);
|
||||
+
|
||||
static const struct sdhci_ops sdhci_pltfm_ops = {
|
||||
.set_clock = sdhci_set_clock,
|
||||
.set_bus_width = sdhci_set_bus_width,
|
||||
--- a/drivers/mmc/host/sdhci-pltfm.h
|
||||
+++ b/drivers/mmc/host/sdhci-pltfm.h
|
||||
@@ -20,6 +20,7 @@ struct sdhci_pltfm_data {
|
||||
|
||||
struct sdhci_pltfm_host {
|
||||
struct clk *clk;
|
||||
+ struct clk *timeout_clk;
|
||||
|
||||
/* migrate from sdhci_of_host */
|
||||
unsigned int clock;
|
||||
@@ -106,6 +107,8 @@ extern int sdhci_pltfm_unregister(struct
|
||||
|
||||
extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host);
|
||||
|
||||
+extern unsigned int sdhci_pltfm_clk_get_timeout_clock(struct sdhci_host *host);
|
||||
+
|
||||
static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host)
|
||||
{
|
||||
return host->private;
|
83
target/linux/bcm27xx/patches-6.1/950-0879-mmc-sdhci-of-dwcmshc-rp1-sdio-changes.patch
Normal file
83
target/linux/bcm27xx/patches-6.1/950-0879-mmc-sdhci-of-dwcmshc-rp1-sdio-changes.patch
Normal file
@ -0,0 +1,83 @@
|
||||
From 14a43b3fd43bf9b230f93d1eba276d40aac969ba Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Wed, 12 Oct 2022 14:07:32 +0100
|
||||
Subject: [PATCH] mmc: sdhci-of-dwcmshc: rp1 sdio changes
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/mmc/host/sdhci-of-dwcmshc.c | 29 ++++++++++++++++++++++++++---
|
||||
1 file changed, 26 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
@@ -87,6 +87,7 @@ struct rk35xx_priv {
|
||||
|
||||
struct dwcmshc_priv {
|
||||
struct clk *bus_clk;
|
||||
+ struct clk *sdio_clk;
|
||||
int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */
|
||||
void *priv; /* pointer to SoC private stuff */
|
||||
};
|
||||
@@ -114,6 +115,17 @@ static void dwcmshc_adma_write_desc(stru
|
||||
sdhci_adma_write_desc(host, desc, addr, len, cmd);
|
||||
}
|
||||
|
||||
+static void dwcmshc_set_clock(struct sdhci_host *host, unsigned int clock)
|
||||
+{
|
||||
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
+ struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
|
||||
+
|
||||
+ if (priv->sdio_clk)
|
||||
+ clk_set_rate(priv->sdio_clk, clock);
|
||||
+
|
||||
+ sdhci_set_clock(host, clock);
|
||||
+}
|
||||
+
|
||||
static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host)
|
||||
{
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
@@ -326,7 +338,7 @@ static void rk35xx_sdhci_reset(struct sd
|
||||
}
|
||||
|
||||
static const struct sdhci_ops sdhci_dwcmshc_ops = {
|
||||
- .set_clock = sdhci_set_clock,
|
||||
+ .set_clock = dwcmshc_set_clock,
|
||||
.set_bus_width = sdhci_set_bus_width,
|
||||
.set_uhs_signaling = dwcmshc_set_uhs_signaling,
|
||||
.get_max_clock = dwcmshc_get_max_clock,
|
||||
@@ -346,8 +358,10 @@ static const struct sdhci_ops sdhci_dwcm
|
||||
|
||||
static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
|
||||
.ops = &sdhci_dwcmshc_ops,
|
||||
- .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
|
||||
- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
|
||||
+ .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
|
||||
+ SDHCI_QUIRK_BROKEN_CARD_DETECTION,
|
||||
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
|
||||
+ SDHCI_QUIRK2_BROKEN_HS200,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
@@ -499,6 +513,14 @@ static int dwcmshc_probe(struct platform
|
||||
priv->bus_clk = devm_clk_get(dev, "bus");
|
||||
if (!IS_ERR(priv->bus_clk))
|
||||
clk_prepare_enable(priv->bus_clk);
|
||||
+
|
||||
+ pltfm_host->timeout_clk = devm_clk_get(dev, "timeout");
|
||||
+ if (!IS_ERR(pltfm_host->timeout_clk))
|
||||
+ err = clk_prepare_enable(pltfm_host->timeout_clk);
|
||||
+ if (err)
|
||||
+ goto free_pltfm;
|
||||
+
|
||||
+ priv->sdio_clk = devm_clk_get_optional(&pdev->dev, "sdio");
|
||||
}
|
||||
|
||||
pltfm_host->timeout_clk = devm_clk_get(&pdev->dev, "timeout");
|
||||
@@ -516,6 +538,7 @@ static int dwcmshc_probe(struct platform
|
||||
goto err_clk;
|
||||
|
||||
sdhci_get_of_property(pdev);
|
||||
+ sdhci_enable_v4_mode(host);
|
||||
|
||||
priv->vendor_specific_area1 =
|
||||
sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK;
|
@ -0,0 +1,641 @@
|
||||
From b427cc1a83404f48b12dec2efbef076b38df6218 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Wed, 12 Oct 2022 14:20:07 +0100
|
||||
Subject: [PATCH] clk: rp1: Add sdio-clk driver
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/clk/Kconfig | 6 +
|
||||
drivers/clk/Makefile | 1 +
|
||||
drivers/clk/clk-rp1-sdio.c | 600 +++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 607 insertions(+)
|
||||
create mode 100644 drivers/clk/clk-rp1-sdio.c
|
||||
|
||||
--- a/drivers/clk/Kconfig
|
||||
+++ b/drivers/clk/Kconfig
|
||||
@@ -96,6 +96,12 @@ config COMMON_CLK_RP1
|
||||
help
|
||||
Enable common clock framework support for Raspberry Pi RP1
|
||||
|
||||
+config COMMON_CLK_RP1_SDIO
|
||||
+ tristate "Clock driver for the RP1 SDIO interfaces"
|
||||
+ depends on MFD_RP1
|
||||
+ help
|
||||
+ SDIO clock driver for the RP1 support chip
|
||||
+
|
||||
config COMMON_CLK_HI655X
|
||||
tristate "Clock driver for Hi655x" if EXPERT
|
||||
depends on (MFD_HI655X_PMIC || COMPILE_TEST)
|
||||
--- a/drivers/clk/Makefile
|
||||
+++ b/drivers/clk/Makefile
|
||||
@@ -59,6 +59,7 @@ obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm
|
||||
obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o
|
||||
obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
|
||||
obj-$(CONFIG_COMMON_CLK_RP1) += clk-rp1.o
|
||||
+obj-$(CONFIG_COMMON_CLK_RP1_SDIO) += clk-rp1-sdio.o
|
||||
obj-$(CONFIG_COMMON_CLK_HI655X) += clk-hi655x.o
|
||||
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
|
||||
obj-$(CONFIG_COMMON_CLK_SCMI) += clk-scmi.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/clk/clk-rp1-sdio.c
|
||||
@@ -0,0 +1,600 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+/*
|
||||
+ * SDIO clock driver for RP1
|
||||
+ *
|
||||
+ * Copyright (C) 2023 Raspberry Pi Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/clk-provider.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+// Register : MODE
|
||||
+#define MODE 0x00000000
|
||||
+#define MODE_BITS 0x70030000
|
||||
+#define MODE_RESET 0x00000000
|
||||
+// Field : MODE_STEPS_PER_CYCLE
|
||||
+#define MODE_STEPS_PER_CYCLE_RESET 0x0
|
||||
+#define MODE_STEPS_PER_CYCLE_BITS 0x70000000
|
||||
+#define MODE_STEPS_PER_CYCLE_MSB 30
|
||||
+#define MODE_STEPS_PER_CYCLE_LSB 28
|
||||
+#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_20 0x0
|
||||
+#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_10 0x1
|
||||
+#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_16 0x2
|
||||
+#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_8 0x3
|
||||
+#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_12 0x4
|
||||
+#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_6 0x5
|
||||
+#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_5 0x6
|
||||
+#define MODE_STEPS_PER_CYCLE_VALUE_STEPS_4 0x7
|
||||
+// Field : MODE_SRC_SEL
|
||||
+#define MODE_SRC_SEL_RESET 0x0
|
||||
+#define MODE_SRC_SEL_BITS 0x00030000
|
||||
+#define MODE_SRC_SEL_MSB 17
|
||||
+#define MODE_SRC_SEL_LSB 16
|
||||
+#define MODE_SRC_SEL_VALUE_STOP 0x0
|
||||
+#define MODE_SRC_SEL_VALUE_CLK_ALT_SRC 0x1
|
||||
+#define MODE_SRC_SEL_VALUE_PLL_SYS_VCO 0x2
|
||||
+#define MODE_SRC_SEL_VALUE_PLL_SYS_VCO_AGAIN 0x3
|
||||
+// Register : FROMIP
|
||||
+#define FROMIP 0x00000004
|
||||
+#define FROMIP_BITS 0x0f9713ff
|
||||
+#define FROMIP_RESET 0x00000000
|
||||
+// Field : FROMIP_TUNING_CCLK_SEL
|
||||
+#define FROMIP_TUNING_CCLK_SEL_RESET 0x0
|
||||
+#define FROMIP_TUNING_CCLK_SEL_BITS 0x0f000000
|
||||
+#define FROMIP_TUNING_CCLK_SEL_MSB 27
|
||||
+#define FROMIP_TUNING_CCLK_SEL_LSB 24
|
||||
+// Field : FROMIP_TUNING_CCLK_UPDATE
|
||||
+#define FROMIP_TUNING_CCLK_UPDATE_RESET 0x0
|
||||
+#define FROMIP_TUNING_CCLK_UPDATE_BITS 0x00800000
|
||||
+#define FROMIP_TUNING_CCLK_UPDATE_MSB 23
|
||||
+#define FROMIP_TUNING_CCLK_UPDATE_LSB 23
|
||||
+// Field : FROMIP_SAMPLE_CCLK_SEL
|
||||
+#define FROMIP_SAMPLE_CCLK_SEL_RESET 0x0
|
||||
+#define FROMIP_SAMPLE_CCLK_SEL_BITS 0x00100000
|
||||
+#define FROMIP_SAMPLE_CCLK_SEL_MSB 20
|
||||
+#define FROMIP_SAMPLE_CCLK_SEL_LSB 20
|
||||
+// Field : FROMIP_CLK2CARD_ON
|
||||
+#define FROMIP_CLK2CARD_ON_RESET 0x0
|
||||
+#define FROMIP_CLK2CARD_ON_BITS 0x00040000
|
||||
+#define FROMIP_CLK2CARD_ON_MSB 18
|
||||
+#define FROMIP_CLK2CARD_ON_LSB 18
|
||||
+// Field : FROMIP_CARD_CLK_STABLE
|
||||
+#define FROMIP_CARD_CLK_STABLE_RESET 0x0
|
||||
+#define FROMIP_CARD_CLK_STABLE_BITS 0x00020000
|
||||
+#define FROMIP_CARD_CLK_STABLE_MSB 17
|
||||
+#define FROMIP_CARD_CLK_STABLE_LSB 17
|
||||
+// Field : FROMIP_CARD_CLK_EN
|
||||
+#define FROMIP_CARD_CLK_EN_RESET 0x0
|
||||
+#define FROMIP_CARD_CLK_EN_BITS 0x00010000
|
||||
+#define FROMIP_CARD_CLK_EN_MSB 16
|
||||
+#define FROMIP_CARD_CLK_EN_LSB 16
|
||||
+// Field : FROMIP_CLK_GEN_SEL
|
||||
+#define FROMIP_CLK_GEN_SEL_RESET 0x0
|
||||
+#define FROMIP_CLK_GEN_SEL_BITS 0x00001000
|
||||
+#define FROMIP_CLK_GEN_SEL_MSB 12
|
||||
+#define FROMIP_CLK_GEN_SEL_LSB 12
|
||||
+// Field : FROMIP_FREQ_SEL
|
||||
+#define FROMIP_FREQ_SEL_RESET 0x000
|
||||
+#define FROMIP_FREQ_SEL_BITS 0x000003ff
|
||||
+#define FROMIP_FREQ_SEL_MSB 9
|
||||
+#define FROMIP_FREQ_SEL_LSB 0
|
||||
+// Register : LOCAL
|
||||
+#define LOCAL 0x00000008
|
||||
+#define LOCAL_BITS 0x1f9713ff
|
||||
+#define LOCAL_RESET 0x00000000
|
||||
+// Field : LOCAL_TUNING_CCLK_SEL
|
||||
+#define LOCAL_TUNING_CCLK_SEL_RESET 0x00
|
||||
+#define LOCAL_TUNING_CCLK_SEL_BITS 0x1f000000
|
||||
+#define LOCAL_TUNING_CCLK_SEL_MSB 28
|
||||
+#define LOCAL_TUNING_CCLK_SEL_LSB 24
|
||||
+// Field : LOCAL_TUNING_CCLK_UPDATE
|
||||
+#define LOCAL_TUNING_CCLK_UPDATE_RESET 0x0
|
||||
+#define LOCAL_TUNING_CCLK_UPDATE_BITS 0x00800000
|
||||
+#define LOCAL_TUNING_CCLK_UPDATE_MSB 23
|
||||
+#define LOCAL_TUNING_CCLK_UPDATE_LSB 23
|
||||
+// Field : LOCAL_SAMPLE_CCLK_SEL
|
||||
+#define LOCAL_SAMPLE_CCLK_SEL_RESET 0x0
|
||||
+#define LOCAL_SAMPLE_CCLK_SEL_BITS 0x00100000
|
||||
+#define LOCAL_SAMPLE_CCLK_SEL_MSB 20
|
||||
+#define LOCAL_SAMPLE_CCLK_SEL_LSB 20
|
||||
+// Field : LOCAL_CLK2CARD_ON
|
||||
+#define LOCAL_CLK2CARD_ON_RESET 0x0
|
||||
+#define LOCAL_CLK2CARD_ON_BITS 0x00040000
|
||||
+#define LOCAL_CLK2CARD_ON_MSB 18
|
||||
+#define LOCAL_CLK2CARD_ON_LSB 18
|
||||
+// Field : LOCAL_CARD_CLK_STABLE
|
||||
+#define LOCAL_CARD_CLK_STABLE_RESET 0x0
|
||||
+#define LOCAL_CARD_CLK_STABLE_BITS 0x00020000
|
||||
+#define LOCAL_CARD_CLK_STABLE_MSB 17
|
||||
+#define LOCAL_CARD_CLK_STABLE_LSB 17
|
||||
+// Field : LOCAL_CARD_CLK_EN
|
||||
+#define LOCAL_CARD_CLK_EN_RESET 0x0
|
||||
+#define LOCAL_CARD_CLK_EN_BITS 0x00010000
|
||||
+#define LOCAL_CARD_CLK_EN_MSB 16
|
||||
+#define LOCAL_CARD_CLK_EN_LSB 16
|
||||
+// Field : LOCAL_CLK_GEN_SEL
|
||||
+#define LOCAL_CLK_GEN_SEL_RESET 0x0
|
||||
+#define LOCAL_CLK_GEN_SEL_BITS 0x00001000
|
||||
+#define LOCAL_CLK_GEN_SEL_MSB 12
|
||||
+#define LOCAL_CLK_GEN_SEL_LSB 12
|
||||
+#define LOCAL_CLK_GEN_SEL_VALUE_PROGCLOCKMODE 0x0
|
||||
+#define LOCAL_CLK_GEN_SEL_VALUE_DIVCLOCKMODE 0x1
|
||||
+// Field : LOCAL_FREQ_SEL
|
||||
+#define LOCAL_FREQ_SEL_RESET 0x000
|
||||
+#define LOCAL_FREQ_SEL_BITS 0x000003ff
|
||||
+#define LOCAL_FREQ_SEL_MSB 9
|
||||
+#define LOCAL_FREQ_SEL_LSB 0
|
||||
+// Register : USE_LOCAL
|
||||
+#define USE_LOCAL 0x0000000c
|
||||
+#define USE_LOCAL_BITS 0x01951001
|
||||
+#define USE_LOCAL_RESET 0x00000000
|
||||
+// Field : USE_LOCAL_TUNING_CCLK_SEL
|
||||
+#define USE_LOCAL_TUNING_CCLK_SEL_RESET 0x0
|
||||
+#define USE_LOCAL_TUNING_CCLK_SEL_BITS 0x01000000
|
||||
+#define USE_LOCAL_TUNING_CCLK_SEL_MSB 24
|
||||
+#define USE_LOCAL_TUNING_CCLK_SEL_LSB 24
|
||||
+// Field : USE_LOCAL_TUNING_CCLK_UPDATE
|
||||
+#define USE_LOCAL_TUNING_CCLK_UPDATE_RESET 0x0
|
||||
+#define USE_LOCAL_TUNING_CCLK_UPDATE_BITS 0x00800000
|
||||
+#define USE_LOCAL_TUNING_CCLK_UPDATE_MSB 23
|
||||
+#define USE_LOCAL_TUNING_CCLK_UPDATE_LSB 23
|
||||
+// Field : USE_LOCAL_SAMPLE_CCLK_SEL
|
||||
+#define USE_LOCAL_SAMPLE_CCLK_SEL_RESET 0x0
|
||||
+#define USE_LOCAL_SAMPLE_CCLK_SEL_BITS 0x00100000
|
||||
+#define USE_LOCAL_SAMPLE_CCLK_SEL_MSB 20
|
||||
+#define USE_LOCAL_SAMPLE_CCLK_SEL_LSB 20
|
||||
+// Field : USE_LOCAL_CLK2CARD_ON
|
||||
+#define USE_LOCAL_CLK2CARD_ON_RESET 0x0
|
||||
+#define USE_LOCAL_CLK2CARD_ON_BITS 0x00040000
|
||||
+#define USE_LOCAL_CLK2CARD_ON_MSB 18
|
||||
+#define USE_LOCAL_CLK2CARD_ON_LSB 18
|
||||
+// Field : USE_LOCAL_CARD_CLK_EN
|
||||
+#define USE_LOCAL_CARD_CLK_EN_RESET 0x0
|
||||
+#define USE_LOCAL_CARD_CLK_EN_BITS 0x00010000
|
||||
+#define USE_LOCAL_CARD_CLK_EN_MSB 16
|
||||
+#define USE_LOCAL_CARD_CLK_EN_LSB 16
|
||||
+// Field : USE_LOCAL_CLK_GEN_SEL
|
||||
+#define USE_LOCAL_CLK_GEN_SEL_RESET 0x0
|
||||
+#define USE_LOCAL_CLK_GEN_SEL_BITS 0x00001000
|
||||
+#define USE_LOCAL_CLK_GEN_SEL_MSB 12
|
||||
+#define USE_LOCAL_CLK_GEN_SEL_LSB 12
|
||||
+// Field : USE_LOCAL_FREQ_SEL
|
||||
+#define USE_LOCAL_FREQ_SEL_RESET 0x0
|
||||
+#define USE_LOCAL_FREQ_SEL_BITS 0x00000001
|
||||
+#define USE_LOCAL_FREQ_SEL_MSB 0
|
||||
+#define USE_LOCAL_FREQ_SEL_LSB 0
|
||||
+// Register : SD_DELAY
|
||||
+#define SD_DELAY 0x00000010
|
||||
+#define SD_DELAY_BITS 0x0000001f
|
||||
+#define SD_DELAY_RESET 0x00000000
|
||||
+// Field : SD_DELAY_STEPS
|
||||
+#define SD_DELAY_STEPS_RESET 0x00
|
||||
+#define SD_DELAY_STEPS_BITS 0x0000001f
|
||||
+#define SD_DELAY_STEPS_MSB 4
|
||||
+#define SD_DELAY_STEPS_LSB 0
|
||||
+// Register : RX_DELAY
|
||||
+#define RX_DELAY 0x00000014
|
||||
+#define RX_DELAY_BITS 0x19f3331f
|
||||
+#define RX_DELAY_RESET 0x00000000
|
||||
+// Field : RX_DELAY_BYPASS
|
||||
+#define RX_DELAY_BYPASS_RESET 0x0
|
||||
+#define RX_DELAY_BYPASS_BITS 0x10000000
|
||||
+#define RX_DELAY_BYPASS_MSB 28
|
||||
+#define RX_DELAY_BYPASS_LSB 28
|
||||
+// Field : RX_DELAY_FAIL_ACTUAL
|
||||
+#define RX_DELAY_FAIL_ACTUAL_RESET 0x0
|
||||
+#define RX_DELAY_FAIL_ACTUAL_BITS 0x08000000
|
||||
+#define RX_DELAY_FAIL_ACTUAL_MSB 27
|
||||
+#define RX_DELAY_FAIL_ACTUAL_LSB 27
|
||||
+// Field : RX_DELAY_ACTUAL
|
||||
+#define RX_DELAY_ACTUAL_RESET 0x00
|
||||
+#define RX_DELAY_ACTUAL_BITS 0x01f00000
|
||||
+#define RX_DELAY_ACTUAL_MSB 24
|
||||
+#define RX_DELAY_ACTUAL_LSB 20
|
||||
+// Field : RX_DELAY_OFFSET
|
||||
+#define RX_DELAY_OFFSET_RESET 0x0
|
||||
+#define RX_DELAY_OFFSET_BITS 0x00030000
|
||||
+#define RX_DELAY_OFFSET_MSB 17
|
||||
+#define RX_DELAY_OFFSET_LSB 16
|
||||
+// Field : RX_DELAY_OVERFLOW
|
||||
+#define RX_DELAY_OVERFLOW_RESET 0x0
|
||||
+#define RX_DELAY_OVERFLOW_BITS 0x00003000
|
||||
+#define RX_DELAY_OVERFLOW_MSB 13
|
||||
+#define RX_DELAY_OVERFLOW_LSB 12
|
||||
+#define RX_DELAY_OVERFLOW_VALUE_ALLOW 0x0
|
||||
+#define RX_DELAY_OVERFLOW_VALUE_CLAMP 0x1
|
||||
+#define RX_DELAY_OVERFLOW_VALUE_FAIL 0x2
|
||||
+// Field : RX_DELAY_MAP
|
||||
+#define RX_DELAY_MAP_RESET 0x0
|
||||
+#define RX_DELAY_MAP_BITS 0x00000300
|
||||
+#define RX_DELAY_MAP_MSB 9
|
||||
+#define RX_DELAY_MAP_LSB 8
|
||||
+#define RX_DELAY_MAP_VALUE_DIRECT 0x0
|
||||
+#define RX_DELAY_MAP_VALUE 0x1
|
||||
+#define RX_DELAY_MAP_VALUE_STRETCH 0x2
|
||||
+// Field : RX_DELAY_FIXED
|
||||
+#define RX_DELAY_FIXED_RESET 0x00
|
||||
+#define RX_DELAY_FIXED_BITS 0x0000001f
|
||||
+#define RX_DELAY_FIXED_MSB 4
|
||||
+#define RX_DELAY_FIXED_LSB 0
|
||||
+// Register : NDIV
|
||||
+#define NDIV 0x00000018
|
||||
+#define NDIV_BITS 0x1fff0000
|
||||
+#define NDIV_RESET 0x00110000
|
||||
+// Field : NDIV_DIVB
|
||||
+#define NDIV_DIVB_RESET 0x001
|
||||
+#define NDIV_DIVB_BITS 0x1ff00000
|
||||
+#define NDIV_DIVB_MSB 28
|
||||
+#define NDIV_DIVB_LSB 20
|
||||
+// Field : NDIV_DIVA
|
||||
+#define NDIV_DIVA_RESET 0x1
|
||||
+#define NDIV_DIVA_BITS 0x000f0000
|
||||
+#define NDIV_DIVA_MSB 19
|
||||
+#define NDIV_DIVA_LSB 16
|
||||
+// Register : CS
|
||||
+#define CS 0x0000001c
|
||||
+#define CS_BITS 0x00111101
|
||||
+#define CS_RESET 0x00000001
|
||||
+// Field : CS_RX_DEL_UPDATED
|
||||
+#define CS_RX_DEL_UPDATED_RESET 0x0
|
||||
+#define CS_RX_DEL_UPDATED_BITS 0x00100000
|
||||
+#define CS_RX_DEL_UPDATED_MSB 20
|
||||
+#define CS_RX_DEL_UPDATED_LSB 20
|
||||
+// Field : CS_RX_CLK_RUNNING
|
||||
+#define CS_RX_CLK_RUNNING_RESET 0x0
|
||||
+#define CS_RX_CLK_RUNNING_BITS 0x00010000
|
||||
+#define CS_RX_CLK_RUNNING_MSB 16
|
||||
+#define CS_RX_CLK_RUNNING_LSB 16
|
||||
+// Field : CS_SD_CLK_RUNNING
|
||||
+#define CS_SD_CLK_RUNNING_RESET 0x0
|
||||
+#define CS_SD_CLK_RUNNING_BITS 0x00001000
|
||||
+#define CS_SD_CLK_RUNNING_MSB 12
|
||||
+#define CS_SD_CLK_RUNNING_LSB 12
|
||||
+// Field : CS_TX_CLK_RUNNING
|
||||
+#define CS_TX_CLK_RUNNING_RESET 0x0
|
||||
+#define CS_TX_CLK_RUNNING_BITS 0x00000100
|
||||
+#define CS_TX_CLK_RUNNING_MSB 8
|
||||
+#define CS_TX_CLK_RUNNING_LSB 8
|
||||
+// Field : CS_RESET
|
||||
+#define CS_RESET_RESET 0x1
|
||||
+#define CS_RESET_BITS 0x00000001
|
||||
+#define CS_RESET_MSB 0
|
||||
+#define CS_RESET_LSB 0
|
||||
+
|
||||
+#define FPGA_SRC_RATE 400000000
|
||||
+
|
||||
+/* Base number of steps to delay in relation to tx clk.
|
||||
+ * The relationship of the 3 clocks are as follows:
|
||||
+ * tx_clk: This clock is provided to the controller. Data is sent out
|
||||
+ * to the pads using this clock.
|
||||
+ * sd_clk: This clock is sent out to the card.
|
||||
+ * rx_clk: This clock is used to sample the data coming back from the card.
|
||||
+ * This may need to be several steps ahead of the tx_clk. The default rx delay
|
||||
+ * is used as a base delay, and can be further adjusted by the sd host
|
||||
+ * controller during the tuning process if using a DDR50 or faster SD card
|
||||
+ */
|
||||
+/*
|
||||
+ * PRJY-1813 - the default SD clock delay needs to be set to ~60% of the total
|
||||
+ * number of steps to meet tISU (>6ns) and tIH (>2ns) in high-speed mode.
|
||||
+ * On FPGA this means delay SDCLK by 5, and sample RX with a delay of 6.
|
||||
+ */
|
||||
+#define DEFAULT_RX_DELAY 6
|
||||
+#define DEFAULT_SD_DELAY 5
|
||||
+
|
||||
+struct rp1_sdio_clkgen {
|
||||
+ struct device *dev;
|
||||
+
|
||||
+ /* Source clock. Either PLL VCO or fixed freq on FPGA */
|
||||
+ struct clk *src_clk;
|
||||
+ /* Desired base frequency. Max freq card can go */
|
||||
+ struct clk *base_clk;
|
||||
+
|
||||
+ struct clk_hw hw;
|
||||
+ void __iomem *regs;
|
||||
+
|
||||
+ /* Starting value of local register before changing freq */
|
||||
+ u32 local_base;
|
||||
+};
|
||||
+
|
||||
+static inline void clkgen_write(struct rp1_sdio_clkgen *clkgen, u32 reg, u32 val)
|
||||
+{
|
||||
+ dev_dbg(clkgen->dev, "%s: write reg 0x%x: 0x%x\n", __func__, reg, val);
|
||||
+ writel(val, clkgen->regs + reg);
|
||||
+}
|
||||
+
|
||||
+static inline u32 clkgen_read(struct rp1_sdio_clkgen *clkgen, u32 reg)
|
||||
+{
|
||||
+ u32 val = readl(clkgen->regs + reg);
|
||||
+
|
||||
+ dev_dbg(clkgen->dev, "%s: read reg 0x%x: 0x%x\n", __func__, reg, val);
|
||||
+ return val;
|
||||
+}
|
||||
+
|
||||
+static int get_steps(unsigned int steps)
|
||||
+{
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ if (steps == 4)
|
||||
+ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_4;
|
||||
+ else if (steps == 5)
|
||||
+ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_5;
|
||||
+ else if (steps == 6)
|
||||
+ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_6;
|
||||
+ else if (steps == 8)
|
||||
+ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_8;
|
||||
+ else if (steps == 10)
|
||||
+ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_10;
|
||||
+ else if (steps == 12)
|
||||
+ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_12;
|
||||
+ else if (steps == 16)
|
||||
+ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_16;
|
||||
+ else if (steps == 20)
|
||||
+ ret = MODE_STEPS_PER_CYCLE_VALUE_STEPS_20;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int rp1_sdio_clk_init(struct rp1_sdio_clkgen *clkgen)
|
||||
+{
|
||||
+ unsigned long src_rate = clk_get_rate(clkgen->src_clk);
|
||||
+ unsigned long base_rate = clk_get_rate(clkgen->base_clk);
|
||||
+ unsigned int steps = src_rate / base_rate;
|
||||
+ u32 reg = 0;
|
||||
+ int steps_value = 0;
|
||||
+
|
||||
+ dev_dbg(clkgen->dev, "init: src_rate %lu, base_rate %lu, steps %d\n",
|
||||
+ src_rate, base_rate, steps);
|
||||
+
|
||||
+ /* Assert reset while we set up clkgen */
|
||||
+ clkgen_write(clkgen, CS, CS_RESET_BITS);
|
||||
+
|
||||
+ /* Pick clock source */
|
||||
+ if (src_rate == FPGA_SRC_RATE) {
|
||||
+ /* Using ALT SRC */
|
||||
+ reg |= MODE_SRC_SEL_VALUE_CLK_ALT_SRC << MODE_SRC_SEL_LSB;
|
||||
+ } else {
|
||||
+ /* Assume we are using PLL SYS VCO */
|
||||
+ reg |= MODE_SRC_SEL_VALUE_PLL_SYS_VCO << MODE_SRC_SEL_LSB;
|
||||
+ }
|
||||
+
|
||||
+ /* How many delay steps are available in one cycle for this source */
|
||||
+ steps_value = get_steps(steps);
|
||||
+ if (steps_value < 0) {
|
||||
+ dev_err(clkgen->dev, "Invalid step value: %d\n", steps);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ reg |= steps_value << MODE_STEPS_PER_CYCLE_LSB;
|
||||
+
|
||||
+ /* Mode register is done now*/
|
||||
+ clkgen_write(clkgen, MODE, reg);
|
||||
+
|
||||
+ /* Now set delay mode */
|
||||
+ /* Clamp value if out of range rx delay is used */
|
||||
+ reg = RX_DELAY_OVERFLOW_VALUE_CLAMP << RX_DELAY_OVERFLOW_LSB;
|
||||
+ /* SD tuning bus goes from 0x0 to 0xf but we don't necessarily have that
|
||||
+ * many steps available depending on the source so map 0x0 -> 0xf to one
|
||||
+ * cycle of rx delay
|
||||
+ */
|
||||
+ reg |= RX_DELAY_MAP_VALUE_STRETCH << RX_DELAY_MAP_LSB;
|
||||
+
|
||||
+ /* Default RX delay */
|
||||
+ dev_dbg(clkgen->dev, "default rx delay %d\n", DEFAULT_RX_DELAY);
|
||||
+ reg |= (DEFAULT_RX_DELAY & RX_DELAY_FIXED_BITS) << RX_DELAY_FIXED_LSB;
|
||||
+ clkgen_write(clkgen, RX_DELAY, reg);
|
||||
+
|
||||
+ /* Default SD delay */
|
||||
+ dev_dbg(clkgen->dev, "default sd delay %d\n", DEFAULT_SD_DELAY);
|
||||
+ reg = (DEFAULT_SD_DELAY & SD_DELAY_STEPS_BITS) << SD_DELAY_STEPS_LSB;
|
||||
+ clkgen_write(clkgen, SD_DELAY, reg);
|
||||
+
|
||||
+ /* We select freq, we turn on tx clock, we turn on sd clk,
|
||||
+ * we pick clock generator mode
|
||||
+ */
|
||||
+ reg = USE_LOCAL_FREQ_SEL_BITS | USE_LOCAL_CARD_CLK_EN_BITS |
|
||||
+ USE_LOCAL_CLK2CARD_ON_BITS | USE_LOCAL_CLK_GEN_SEL_BITS;
|
||||
+ clkgen_write(clkgen, USE_LOCAL, reg);
|
||||
+
|
||||
+ /* Deassert reset. Reset bit is only writable bit of CS
|
||||
+ * reg so fine to write a 0.
|
||||
+ */
|
||||
+ clkgen_write(clkgen, CS, 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define RUNNING \
|
||||
+ (CS_TX_CLK_RUNNING_BITS | CS_RX_CLK_RUNNING_BITS | \
|
||||
+ CS_SD_CLK_RUNNING_BITS)
|
||||
+static int rp1_sdio_clk_is_prepared(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct rp1_sdio_clkgen *clkgen =
|
||||
+ container_of(hw, struct rp1_sdio_clkgen, hw);
|
||||
+ u32 status;
|
||||
+
|
||||
+ dev_dbg(clkgen->dev, "is_prepared\n");
|
||||
+ status = clkgen_read(clkgen, CS);
|
||||
+ return ((status & RUNNING) == RUNNING);
|
||||
+}
|
||||
+
|
||||
+/* Can define an additional divider if an sd card isn't working at full speed */
|
||||
+/* #define SLOWDOWN 3 */
|
||||
+
|
||||
+static unsigned long rp1_sdio_clk_get_rate(struct clk_hw *hw,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ /* Get the current rate */
|
||||
+ struct rp1_sdio_clkgen *clkgen =
|
||||
+ container_of(hw, struct rp1_sdio_clkgen, hw);
|
||||
+ unsigned long actual_rate = 0;
|
||||
+ u32 ndiv_diva;
|
||||
+ u32 ndiv_divb;
|
||||
+ u32 tmp;
|
||||
+ u32 div;
|
||||
+
|
||||
+ tmp = clkgen_read(clkgen, LOCAL);
|
||||
+ if ((tmp & LOCAL_CLK2CARD_ON_BITS) == 0) {
|
||||
+ dev_dbg(clkgen->dev, "get_rate 0\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ tmp = clkgen_read(clkgen, NDIV);
|
||||
+ ndiv_diva = (tmp & NDIV_DIVA_BITS) >> NDIV_DIVA_LSB;
|
||||
+ ndiv_divb = (tmp & NDIV_DIVB_BITS) >> NDIV_DIVB_LSB;
|
||||
+ div = ndiv_diva * ndiv_divb;
|
||||
+ actual_rate = (clk_get_rate(clkgen->base_clk) / div);
|
||||
+
|
||||
+#ifdef SLOWDOWN
|
||||
+ actual_rate *= SLOWDOWN;
|
||||
+#endif
|
||||
+
|
||||
+ dev_dbg(clkgen->dev, "get_rate. ndiv_diva %d, ndiv_divb %d = %lu\n",
|
||||
+ ndiv_diva, ndiv_divb, actual_rate);
|
||||
+
|
||||
+ return actual_rate;
|
||||
+}
|
||||
+
|
||||
+static int rp1_sdio_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ struct rp1_sdio_clkgen *clkgen =
|
||||
+ container_of(hw, struct rp1_sdio_clkgen, hw);
|
||||
+ u32 div;
|
||||
+ u32 reg;
|
||||
+
|
||||
+ dev_dbg(clkgen->dev, "set_rate %lu\n", rate);
|
||||
+
|
||||
+ if (rate == 0) {
|
||||
+ /* Keep tx clock running */
|
||||
+ clkgen_write(clkgen, LOCAL, LOCAL_CARD_CLK_EN_BITS);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+#ifdef SLOWDOWN
|
||||
+ rate /= SLOWDOWN;
|
||||
+#endif
|
||||
+
|
||||
+ div = (clk_get_rate(clkgen->base_clk) / rate) - 1;
|
||||
+ reg = LOCAL_CLK_GEN_SEL_BITS | LOCAL_CARD_CLK_EN_BITS |
|
||||
+ LOCAL_CLK2CARD_ON_BITS | (div << LOCAL_FREQ_SEL_LSB);
|
||||
+ clkgen_write(clkgen, LOCAL, reg);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define MAX_NDIV (256 * 8)
|
||||
+static int rp1_sdio_clk_determine_rate(struct clk_hw *hw,
|
||||
+ struct clk_rate_request *req)
|
||||
+{
|
||||
+ unsigned long rate;
|
||||
+ struct rp1_sdio_clkgen *clkgen =
|
||||
+ container_of(hw, struct rp1_sdio_clkgen, hw);
|
||||
+ unsigned long base_rate = clk_get_rate(clkgen->base_clk);
|
||||
+ u32 div;
|
||||
+
|
||||
+ /* What is the actual rate I can get if I request xyz */
|
||||
+ if (req->rate) {
|
||||
+ div = min((u32)(base_rate / req->rate), (u32)MAX_NDIV);
|
||||
+ rate = base_rate / div;
|
||||
+ req->rate = rate;
|
||||
+ dev_dbg(clkgen->dev, "determine_rate %lu: %lu / %d = %lu\n",
|
||||
+ req->rate, base_rate, div, rate);
|
||||
+ } else {
|
||||
+ rate = 0;
|
||||
+ dev_dbg(clkgen->dev, "determine_rate %lu: %lu\n", req->rate,
|
||||
+ rate);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct clk_ops rp1_sdio_clk_ops = {
|
||||
+ .is_prepared = rp1_sdio_clk_is_prepared,
|
||||
+ .recalc_rate = rp1_sdio_clk_get_rate,
|
||||
+ .set_rate = rp1_sdio_clk_set_rate,
|
||||
+ .determine_rate = rp1_sdio_clk_determine_rate,
|
||||
+};
|
||||
+
|
||||
+static int rp1_sdio_clk_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device_node *node = pdev->dev.of_node;
|
||||
+ struct rp1_sdio_clkgen *clkgen;
|
||||
+ void __iomem *regs;
|
||||
+ struct clk_init_data init = {};
|
||||
+ int ret;
|
||||
+
|
||||
+ clkgen = devm_kzalloc(&pdev->dev, sizeof(*clkgen), GFP_KERNEL);
|
||||
+ if (!clkgen)
|
||||
+ return -ENOMEM;
|
||||
+ platform_set_drvdata(pdev, clkgen);
|
||||
+
|
||||
+ clkgen->dev = &pdev->dev;
|
||||
+
|
||||
+ /* Source freq */
|
||||
+ clkgen->src_clk = devm_clk_get(&pdev->dev, "src");
|
||||
+ if (IS_ERR(clkgen->src_clk)) {
|
||||
+ int err = PTR_ERR(clkgen->src_clk);
|
||||
+
|
||||
+ dev_err(&pdev->dev, "failed to get src clk: %d\n", err);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ /* Desired maximum output freq (i.e. base freq) */
|
||||
+ clkgen->base_clk = devm_clk_get(&pdev->dev, "base");
|
||||
+ if (IS_ERR(clkgen->base_clk)) {
|
||||
+ int err = PTR_ERR(clkgen->base_clk);
|
||||
+
|
||||
+ dev_err(&pdev->dev, "failed to get base clk: %d\n", err);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(regs))
|
||||
+ return PTR_ERR(regs);
|
||||
+
|
||||
+ init.name = node->name;
|
||||
+ init.ops = &rp1_sdio_clk_ops;
|
||||
+ init.flags = CLK_GET_RATE_NOCACHE;
|
||||
+
|
||||
+ clkgen->hw.init = &init;
|
||||
+ clkgen->regs = regs;
|
||||
+
|
||||
+ dev_info(&pdev->dev, "loaded %s\n", init.name);
|
||||
+
|
||||
+ ret = devm_clk_hw_register(&pdev->dev, &clkgen->hw);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &clkgen->hw);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = rp1_sdio_clk_init(clkgen);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int rp1_sdio_clk_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id rp1_sdio_clk_dt_ids[] = {
|
||||
+ { .compatible = "raspberrypi,rp1-sdio-clk", },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, rp1_sdio_clk_dt_ids);
|
||||
+
|
||||
+static struct platform_driver rp1_sdio_clk_driver = {
|
||||
+ .probe = rp1_sdio_clk_probe,
|
||||
+ .remove = rp1_sdio_clk_remove,
|
||||
+ .driver = {
|
||||
+ .name = "rp1-sdio-clk",
|
||||
+ .of_match_table = rp1_sdio_clk_dt_ids,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(rp1_sdio_clk_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Liam Fraser <liam@raspberrypi.com>");
|
||||
+MODULE_DESCRIPTION("RP1 SDIO clock driver");
|
||||
+MODULE_LICENSE("GPL");
|
76
target/linux/bcm27xx/patches-6.1/950-0881-i2c-designware-Add-SMBUS-quick-command-support.patch
Normal file
76
target/linux/bcm27xx/patches-6.1/950-0881-i2c-designware-Add-SMBUS-quick-command-support.patch
Normal file
@ -0,0 +1,76 @@
|
||||
From 50adadfaf324ed5cbb59ce2b85eda59de4e3801a Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Fri, 4 Dec 2020 15:20:36 +0000
|
||||
Subject: [PATCH] i2c: designware: Add SMBUS quick command support
|
||||
|
||||
The SMBUS emulation code turns an SMBUS quick command into a zero-
|
||||
length read. This controller can't do zero length accesses, but it
|
||||
can do quick commands, so reverse the emulation. The alternative
|
||||
would be to properly implement the SMBUS support but that is a lot
|
||||
more work, and unnecessary just to get i2cdetect working.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/i2c/busses/i2c-designware-core.h | 2 ++
|
||||
drivers/i2c/busses/i2c-designware-master.c | 17 +++++++++++++++--
|
||||
2 files changed, 17 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/i2c/busses/i2c-designware-core.h
|
||||
+++ b/drivers/i2c/busses/i2c-designware-core.h
|
||||
@@ -117,7 +117,9 @@
|
||||
|
||||
#define DW_IC_ERR_TX_ABRT 0x1
|
||||
|
||||
+#define DW_IC_TAR_SPECIAL BIT(11)
|
||||
#define DW_IC_TAR_10BITADDR_MASTER BIT(12)
|
||||
+#define DW_IC_TAR_SMBUS_QUICK_CMD BIT(16)
|
||||
|
||||
#define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH (BIT(2) | BIT(3))
|
||||
#define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK GENMASK(3, 2)
|
||||
--- a/drivers/i2c/busses/i2c-designware-master.c
|
||||
+++ b/drivers/i2c/busses/i2c-designware-master.c
|
||||
@@ -228,6 +228,10 @@ static void i2c_dw_xfer_init(struct dw_i
|
||||
ic_tar = DW_IC_TAR_10BITADDR_MASTER;
|
||||
}
|
||||
|
||||
+ /* Convert a zero-length read into an SMBUS quick command */
|
||||
+ if (!msgs[dev->msg_write_idx].len)
|
||||
+ ic_tar = DW_IC_TAR_SPECIAL | DW_IC_TAR_SMBUS_QUICK_CMD;
|
||||
+
|
||||
regmap_update_bits(dev->map, DW_IC_CON, DW_IC_CON_10BITADDR_MASTER,
|
||||
ic_con);
|
||||
|
||||
@@ -409,6 +413,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
|
||||
regmap_read(dev->map, DW_IC_RXFLR, &flr);
|
||||
rx_limit = dev->rx_fifo_depth - flr;
|
||||
|
||||
+ /* Handle SMBUS quick commands */
|
||||
+ if (!buf_len) {
|
||||
+ if (msgs[dev->msg_write_idx].flags & I2C_M_RD)
|
||||
+ regmap_write(dev->map, DW_IC_DATA_CMD, 0x300);
|
||||
+ else
|
||||
+ regmap_write(dev->map, DW_IC_DATA_CMD, 0x200);
|
||||
+ }
|
||||
+
|
||||
while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
|
||||
u32 cmd = 0;
|
||||
|
||||
@@ -673,7 +685,7 @@ static const struct i2c_algorithm i2c_dw
|
||||
};
|
||||
|
||||
static const struct i2c_adapter_quirks i2c_dw_quirks = {
|
||||
- .flags = I2C_AQ_NO_ZERO_LEN,
|
||||
+ .flags = 0,
|
||||
};
|
||||
|
||||
static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
|
||||
@@ -813,7 +825,8 @@ void i2c_dw_configure_master(struct dw_i
|
||||
{
|
||||
struct i2c_timings *t = &dev->timings;
|
||||
|
||||
- dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
|
||||
+ dev->functionality = I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_QUICK |
|
||||
+ DW_IC_DEFAULT_FUNCTIONALITY;
|
||||
|
||||
dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
|
||||
DW_IC_CON_RESTART_EN;
|
@ -0,0 +1,355 @@
|
||||
From 0a1cd70189daec3baf4b4a233dd8e25ffbb9d512 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Wed, 28 Apr 2021 17:46:01 +0100
|
||||
Subject: [PATCH] dmaengine: dw-axi-dmac: Fixes for RP1
|
||||
|
||||
Don't assume that DMA addresses of devices are the same as their
|
||||
physical addresses - convert correctly.
|
||||
|
||||
The CFG2 register layout is used when there are more than 8 channels,
|
||||
but also when configured for more than 16 target peripheral devices
|
||||
because the index of the handshake signal has to be made wider.
|
||||
|
||||
Reset the DMAC on probe
|
||||
|
||||
The driver goes to the trouble of tracking when transfers have been
|
||||
paused, but then doesn't report that state when queried.
|
||||
|
||||
Not having APB registers is not an error - for most use cases it's
|
||||
not even of interest, it's expected. Demote the message to debug level,
|
||||
which is disabled by default.
|
||||
|
||||
Each channel has a descriptor pool, which is shared between transfers.
|
||||
It is unsafe to treat the total number of descriptors allocated from a
|
||||
pool as the number allocated to a specific transfer; doing so leads
|
||||
to releasing buffers that shouldn't be released and walking off the
|
||||
ends of descriptor lists. Instead, give each transfer descriptor its
|
||||
own count.
|
||||
|
||||
Support partial transfers:
|
||||
Some use cases involve streaming from a device where the transfer only
|
||||
proceeds when the device's FIFO occupancy exceeds a certain threshold.
|
||||
In such cases (e.g. when pulling data from a UART) it is important to
|
||||
know how much data has been transferred so far, in order that remaining
|
||||
bytes can be read from the FIFO directly by software.
|
||||
|
||||
Add the necessary code to provide this "residue" value with a finer,
|
||||
sub-transfer granularity.
|
||||
|
||||
In order to prevent the occasional byte getting stuck in the DMA
|
||||
controller's internal buffers, restrict the destination memory width
|
||||
to the source register width.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
.../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 136 +++++++++++++++---
|
||||
drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 3 +
|
||||
2 files changed, 118 insertions(+), 21 deletions(-)
|
||||
|
||||
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
|
||||
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dmapool.h>
|
||||
+#include <linux/dma-direct.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
@@ -79,6 +80,17 @@ axi_chan_iowrite64(struct axi_dma_chan *
|
||||
iowrite32(upper_32_bits(val), chan->chan_regs + reg + 4);
|
||||
}
|
||||
|
||||
+static inline u64
|
||||
+axi_chan_ioread64(struct axi_dma_chan *chan, u32 reg)
|
||||
+{
|
||||
+ /*
|
||||
+ * We split one 64 bit read into two 32 bit reads as some HW doesn't
|
||||
+ * support 64 bit access.
|
||||
+ */
|
||||
+ return ((u64)ioread32(chan->chan_regs + reg + 4) << 32) +
|
||||
+ ioread32(chan->chan_regs + reg);
|
||||
+}
|
||||
+
|
||||
static inline void axi_chan_config_write(struct axi_dma_chan *chan,
|
||||
struct axi_dma_chan_config *config)
|
||||
{
|
||||
@@ -86,7 +98,7 @@ static inline void axi_chan_config_write
|
||||
|
||||
cfg_lo = (config->dst_multblk_type << CH_CFG_L_DST_MULTBLK_TYPE_POS |
|
||||
config->src_multblk_type << CH_CFG_L_SRC_MULTBLK_TYPE_POS);
|
||||
- if (chan->chip->dw->hdata->reg_map_8_channels) {
|
||||
+ if (!chan->chip->dw->hdata->reg_map_cfg2) {
|
||||
cfg_hi = config->tt_fc << CH_CFG_H_TT_FC_POS |
|
||||
config->hs_sel_src << CH_CFG_H_HS_SEL_SRC_POS |
|
||||
config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS |
|
||||
@@ -214,7 +226,18 @@ static void axi_dma_hw_init(struct axi_d
|
||||
{
|
||||
int ret;
|
||||
u32 i;
|
||||
+ int retries = 1000;
|
||||
|
||||
+ axi_dma_iowrite32(chip, DMAC_RESET, 1);
|
||||
+ while (axi_dma_ioread32(chip, DMAC_RESET)) {
|
||||
+ retries--;
|
||||
+ if (!retries) {
|
||||
+ dev_err(chip->dev, "%s: DMAC failed to reset\n",
|
||||
+ __func__);
|
||||
+ return;
|
||||
+ }
|
||||
+ cpu_relax();
|
||||
+ }
|
||||
for (i = 0; i < chip->dw->hdata->nr_channels; i++) {
|
||||
axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
|
||||
axi_chan_disable(&chip->dw->chan[i]);
|
||||
@@ -276,7 +299,7 @@ static struct axi_dma_lli *axi_desc_get(
|
||||
static void axi_desc_put(struct axi_dma_desc *desc)
|
||||
{
|
||||
struct axi_dma_chan *chan = desc->chan;
|
||||
- int count = atomic_read(&chan->descs_allocated);
|
||||
+ u32 count = desc->hw_desc_count;
|
||||
struct axi_dma_hw_desc *hw_desc;
|
||||
int descs_put;
|
||||
|
||||
@@ -298,6 +321,48 @@ static void vchan_desc_put(struct virt_d
|
||||
axi_desc_put(vd_to_axi_desc(vdesc));
|
||||
}
|
||||
|
||||
+static u32 axi_dma_desc_src_pos(struct axi_dma_desc *desc, dma_addr_t addr)
|
||||
+{
|
||||
+ unsigned int idx = 0;
|
||||
+ u32 pos = 0;
|
||||
+
|
||||
+ while (pos < desc->length) {
|
||||
+ struct axi_dma_hw_desc *hw_desc = &desc->hw_desc[idx++];
|
||||
+ u32 len = hw_desc->len;
|
||||
+ dma_addr_t start = le64_to_cpu(hw_desc->lli->sar);
|
||||
+
|
||||
+ if (addr >= start && addr <= (start + len)) {
|
||||
+ pos += addr - start;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ pos += len;
|
||||
+ }
|
||||
+
|
||||
+ return pos;
|
||||
+}
|
||||
+
|
||||
+static u32 axi_dma_desc_dst_pos(struct axi_dma_desc *desc, dma_addr_t addr)
|
||||
+{
|
||||
+ unsigned int idx = 0;
|
||||
+ u32 pos = 0;
|
||||
+
|
||||
+ while (pos < desc->length) {
|
||||
+ struct axi_dma_hw_desc *hw_desc = &desc->hw_desc[idx++];
|
||||
+ u32 len = hw_desc->len;
|
||||
+ dma_addr_t start = le64_to_cpu(hw_desc->lli->dar);
|
||||
+
|
||||
+ if (addr >= start && addr <= (start + len)) {
|
||||
+ pos += addr - start;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ pos += len;
|
||||
+ }
|
||||
+
|
||||
+ return pos;
|
||||
+}
|
||||
+
|
||||
static enum dma_status
|
||||
dma_chan_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
|
||||
struct dma_tx_state *txstate)
|
||||
@@ -307,10 +372,7 @@ dma_chan_tx_status(struct dma_chan *dcha
|
||||
enum dma_status status;
|
||||
u32 completed_length;
|
||||
unsigned long flags;
|
||||
- u32 completed_blocks;
|
||||
size_t bytes = 0;
|
||||
- u32 length;
|
||||
- u32 len;
|
||||
|
||||
status = dma_cookie_status(dchan, cookie, txstate);
|
||||
if (status == DMA_COMPLETE || !txstate)
|
||||
@@ -319,16 +381,31 @@ dma_chan_tx_status(struct dma_chan *dcha
|
||||
spin_lock_irqsave(&chan->vc.lock, flags);
|
||||
|
||||
vdesc = vchan_find_desc(&chan->vc, cookie);
|
||||
- if (vdesc) {
|
||||
- length = vd_to_axi_desc(vdesc)->length;
|
||||
- completed_blocks = vd_to_axi_desc(vdesc)->completed_blocks;
|
||||
- len = vd_to_axi_desc(vdesc)->hw_desc[0].len;
|
||||
- completed_length = completed_blocks * len;
|
||||
- bytes = length - completed_length;
|
||||
+ if (vdesc && vdesc == vchan_next_desc(&chan->vc)) {
|
||||
+ /* This descriptor is in-progress */
|
||||
+ struct axi_dma_desc *desc = vd_to_axi_desc(vdesc);
|
||||
+ dma_addr_t addr;
|
||||
+
|
||||
+ if (chan->direction == DMA_MEM_TO_DEV) {
|
||||
+ addr = axi_chan_ioread64(chan, CH_SAR);
|
||||
+ completed_length = axi_dma_desc_src_pos(desc, addr);
|
||||
+ } else if (chan->direction == DMA_DEV_TO_MEM) {
|
||||
+ addr = axi_chan_ioread64(chan, CH_DAR);
|
||||
+ completed_length = axi_dma_desc_dst_pos(desc, addr);
|
||||
+ } else {
|
||||
+ completed_length = 0;
|
||||
+ }
|
||||
+ bytes = desc->length - completed_length;
|
||||
+ } else if (vdesc) {
|
||||
+ /* Still in the queue so not started */
|
||||
+ bytes = vd_to_axi_desc(vdesc)->length;
|
||||
}
|
||||
|
||||
- spin_unlock_irqrestore(&chan->vc.lock, flags);
|
||||
+ if (chan->is_paused && status == DMA_IN_PROGRESS)
|
||||
+ status = DMA_PAUSED;
|
||||
+
|
||||
dma_set_residue(txstate, bytes);
|
||||
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -516,7 +593,7 @@ static void dw_axi_dma_set_hw_channel(st
|
||||
unsigned long reg_value, val;
|
||||
|
||||
if (!chip->apb_regs) {
|
||||
- dev_err(chip->dev, "apb_regs not initialized\n");
|
||||
+ dev_dbg(chip->dev, "apb_regs not initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -620,18 +697,25 @@ static int dw_axi_dma_set_hw_desc(struct
|
||||
switch (chan->direction) {
|
||||
case DMA_MEM_TO_DEV:
|
||||
reg_width = __ffs(chan->config.dst_addr_width);
|
||||
- device_addr = chan->config.dst_addr;
|
||||
+ device_addr = phys_to_dma(chan->chip->dev, chan->config.dst_addr);
|
||||
ctllo = reg_width << CH_CTL_L_DST_WIDTH_POS |
|
||||
mem_width << CH_CTL_L_SRC_WIDTH_POS |
|
||||
+ DWAXIDMAC_BURST_TRANS_LEN_1 << CH_CTL_L_DST_MSIZE_POS |
|
||||
+ DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS |
|
||||
DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_DST_INC_POS |
|
||||
DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS;
|
||||
block_ts = len >> mem_width;
|
||||
break;
|
||||
case DMA_DEV_TO_MEM:
|
||||
reg_width = __ffs(chan->config.src_addr_width);
|
||||
- device_addr = chan->config.src_addr;
|
||||
+ /* Prevent partial access units getting lost */
|
||||
+ if (mem_width > reg_width)
|
||||
+ mem_width = reg_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 |
|
||||
+ DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
|
||||
+ DWAXIDMAC_BURST_TRANS_LEN_1 << CH_CTL_L_SRC_MSIZE_POS |
|
||||
DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS |
|
||||
DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_SRC_INC_POS;
|
||||
block_ts = len >> reg_width;
|
||||
@@ -667,9 +751,6 @@ static int dw_axi_dma_set_hw_desc(struct
|
||||
}
|
||||
|
||||
hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1);
|
||||
-
|
||||
- ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
|
||||
- DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS;
|
||||
hw_desc->lli->ctl_lo = cpu_to_le32(ctllo);
|
||||
|
||||
set_desc_src_master(hw_desc);
|
||||
@@ -764,6 +845,8 @@ dw_axi_dma_chan_prep_cyclic(struct dma_c
|
||||
src_addr += segment_len;
|
||||
}
|
||||
|
||||
+ desc->hw_desc_count = total_segments;
|
||||
+
|
||||
llp = desc->hw_desc[0].llp;
|
||||
|
||||
/* Managed transfer list */
|
||||
@@ -843,6 +926,8 @@ dw_axi_dma_chan_prep_slave_sg(struct dma
|
||||
} while (len >= segment_len);
|
||||
}
|
||||
|
||||
+ desc->hw_desc_count = loop;
|
||||
+
|
||||
/* Set end-of-link to the last link descriptor of list */
|
||||
set_desc_last(&desc->hw_desc[num_sgs - 1]);
|
||||
|
||||
@@ -950,6 +1035,8 @@ dma_chan_prep_dma_memcpy(struct dma_chan
|
||||
num++;
|
||||
}
|
||||
|
||||
+ desc->hw_desc_count = num;
|
||||
+
|
||||
/* Set end-of-link to the last link descriptor of list */
|
||||
set_desc_last(&desc->hw_desc[num - 1]);
|
||||
/* Managed transfer list */
|
||||
@@ -998,7 +1085,7 @@ static void axi_chan_dump_lli(struct axi
|
||||
static void axi_chan_list_dump_lli(struct axi_dma_chan *chan,
|
||||
struct axi_dma_desc *desc_head)
|
||||
{
|
||||
- int count = atomic_read(&chan->descs_allocated);
|
||||
+ u32 count = desc_head->hw_desc_count;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
@@ -1041,11 +1128,11 @@ out:
|
||||
|
||||
static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan)
|
||||
{
|
||||
- int count = atomic_read(&chan->descs_allocated);
|
||||
struct axi_dma_hw_desc *hw_desc;
|
||||
struct axi_dma_desc *desc;
|
||||
struct virt_dma_desc *vd;
|
||||
unsigned long flags;
|
||||
+ u32 count;
|
||||
u64 llp;
|
||||
int i;
|
||||
|
||||
@@ -1067,6 +1154,7 @@ static void axi_chan_block_xfer_complete
|
||||
if (chan->cyclic) {
|
||||
desc = vd_to_axi_desc(vd);
|
||||
if (desc) {
|
||||
+ count = desc->hw_desc_count;
|
||||
llp = lo_hi_readq(chan->chan_regs + CH_LLP);
|
||||
for (i = 0; i < count; i++) {
|
||||
hw_desc = &desc->hw_desc[i];
|
||||
@@ -1310,6 +1398,8 @@ static int parse_device_properties(struc
|
||||
chip->dw->hdata->nr_channels = tmp;
|
||||
if (tmp <= DMA_REG_MAP_CH_REF)
|
||||
chip->dw->hdata->reg_map_8_channels = true;
|
||||
+ else
|
||||
+ chip->dw->hdata->reg_map_cfg2 = true;
|
||||
|
||||
ret = device_property_read_u32(dev, "snps,dma-masters", &tmp);
|
||||
if (ret)
|
||||
@@ -1319,6 +1409,10 @@ static int parse_device_properties(struc
|
||||
|
||||
chip->dw->hdata->nr_masters = tmp;
|
||||
|
||||
+ ret = device_property_read_u32(dev, "snps,dma-targets", &tmp);
|
||||
+ if (!ret && tmp > 16)
|
||||
+ chip->dw->hdata->reg_map_cfg2 = true;
|
||||
+
|
||||
ret = device_property_read_u32(dev, "snps,data-width", &tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
|
||||
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
|
||||
@@ -32,6 +32,8 @@ struct dw_axi_dma_hcfg {
|
||||
u32 axi_rw_burst_len;
|
||||
/* Register map for DMAX_NUM_CHANNELS <= 8 */
|
||||
bool reg_map_8_channels;
|
||||
+ /* Register map for DMAX_NUM_CHANNELS > 8 || DMAX_NUM_HS_IF > 16*/
|
||||
+ bool reg_map_cfg2;
|
||||
bool restrict_axi_burst_len;
|
||||
};
|
||||
|
||||
@@ -100,6 +102,7 @@ struct axi_dma_desc {
|
||||
|
||||
struct virt_dma_desc vd;
|
||||
struct axi_dma_chan *chan;
|
||||
+ u32 hw_desc_count;
|
||||
u32 completed_blocks;
|
||||
u32 length;
|
||||
u32 period_len;
|
64
target/linux/bcm27xx/patches-6.1/950-0883-spi-dw-Handle-combined-tx-and-rx-messages.patch
Normal file
64
target/linux/bcm27xx/patches-6.1/950-0883-spi-dw-Handle-combined-tx-and-rx-messages.patch
Normal file
@ -0,0 +1,64 @@
|
||||
From 8a9c0607ce0daa91c48faefd70ea73bda54ed0ae Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Tue, 29 Nov 2022 10:09:54 +0000
|
||||
Subject: [PATCH] spi: dw: Handle combined tx and rx messages
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/spi/spi-dw-core.c | 12 +++++++++---
|
||||
drivers/spi/spi-dw-mmio.c | 8 ++++++--
|
||||
2 files changed, 15 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-dw-core.c
|
||||
+++ b/drivers/spi/spi-dw-core.c
|
||||
@@ -244,8 +244,11 @@ static irqreturn_t dw_spi_transfer_handl
|
||||
*/
|
||||
if (irq_status & DW_SPI_INT_TXEI) {
|
||||
dw_writer(dws);
|
||||
- if (!dws->tx_len)
|
||||
+ if (!dws->tx_len) {
|
||||
dw_spi_mask_intr(dws, DW_SPI_INT_TXEI);
|
||||
+ if (!dws->rx_len)
|
||||
+ spi_finalize_current_transfer(dws->master);
|
||||
+ }
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@@ -372,8 +375,11 @@ static void dw_spi_irq_setup(struct dw_s
|
||||
|
||||
dws->transfer_handler = dw_spi_transfer_handler;
|
||||
|
||||
- imask = DW_SPI_INT_TXEI | DW_SPI_INT_TXOI |
|
||||
- DW_SPI_INT_RXUI | DW_SPI_INT_RXOI | DW_SPI_INT_RXFI;
|
||||
+ imask = 0;
|
||||
+ if (dws->tx_len)
|
||||
+ imask |= DW_SPI_INT_TXEI | DW_SPI_INT_TXOI;
|
||||
+ if (dws->rx_len)
|
||||
+ imask |= DW_SPI_INT_RXUI | DW_SPI_INT_RXOI | DW_SPI_INT_RXFI;
|
||||
dw_spi_umask_intr(dws, imask);
|
||||
}
|
||||
|
||||
--- a/drivers/spi/spi-dw-mmio.c
|
||||
+++ b/drivers/spi/spi-dw-mmio.c
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
+#include <linux/interrupt.h>
|
||||
|
||||
#include "spi-dw.h"
|
||||
|
||||
@@ -280,8 +281,11 @@ static int dw_spi_mmio_probe(struct plat
|
||||
dws->paddr = mem->start;
|
||||
|
||||
dws->irq = platform_get_irq(pdev, 0);
|
||||
- if (dws->irq < 0)
|
||||
- return dws->irq; /* -ENXIO */
|
||||
+ if (dws->irq < 0) {
|
||||
+ if (dws->irq != -ENXIO)
|
||||
+ return dws->irq; /* -ENXIO */
|
||||
+ dws->irq = IRQ_NOTCONNECTED;
|
||||
+ }
|
||||
|
||||
dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(dwsmmio->clk))
|
@ -0,0 +1,292 @@
|
||||
From 824f18efc8ad59e2783570ae2df83e2cd16b9f04 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Tue, 14 Feb 2023 14:03:54 +0000
|
||||
Subject: [PATCH] pwm: Add support for RP1 PWM
|
||||
|
||||
Add a driver for the RP1 PWM block.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
.../devicetree/bindings/pwm/pwm-rp1.yaml | 38 ++++
|
||||
drivers/pwm/Kconfig | 9 +
|
||||
drivers/pwm/Makefile | 1 +
|
||||
drivers/pwm/pwm-rp1.c | 203 ++++++++++++++++++
|
||||
4 files changed, 251 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/pwm/pwm-rp1.yaml
|
||||
create mode 100644 drivers/pwm/pwm-rp1.c
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/pwm/pwm-rp1.yaml
|
||||
@@ -0,0 +1,38 @@
|
||||
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/pwm/pwm-rp1.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Raspberry Pi RP1 PWM controller
|
||||
+
|
||||
+maintainers:
|
||||
+ - Naushir Patuck <naush@raspberrypi.com>
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ enum:
|
||||
+ - raspberrypi,rp1-pwm
|
||||
+
|
||||
+ reg:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ "#pwm-cells":
|
||||
+ const: 3
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - reg
|
||||
+ - clocks
|
||||
+ - "#pwm-cells"
|
||||
+
|
||||
+additionalProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ pwm0: pwm@98000 {
|
||||
+ compatible = "raspberrypi,rp1-pwm";
|
||||
+ reg = <0x0 0x98000 0x0 0x100>;
|
||||
+ clocks = <&rp1_sys>;
|
||||
+ #pwm-cells = <3>;
|
||||
+ };
|
||||
--- a/drivers/pwm/Kconfig
|
||||
+++ b/drivers/pwm/Kconfig
|
||||
@@ -451,6 +451,15 @@ config PWM_RASPBERRYPI_POE
|
||||
Enable Raspberry Pi firmware controller PWM bus used to control the
|
||||
official RPI PoE hat
|
||||
|
||||
+config PWM_RP1
|
||||
+ tristate "RP1 PWM support"
|
||||
+ depends on ARCH_BCM2835 || COMPILE_TEST
|
||||
+ help
|
||||
+ PWM framework driver for Raspberry Pi RP1 controller
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the module
|
||||
+ will be called pwm-rp1.
|
||||
+
|
||||
config PWM_RCAR
|
||||
tristate "Renesas R-Car PWM support"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
--- a/drivers/pwm/Makefile
|
||||
+++ b/drivers/pwm/Makefile
|
||||
@@ -41,6 +41,7 @@ obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-om
|
||||
obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
|
||||
obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
|
||||
obj-$(CONFIG_PWM_RASPBERRYPI_POE) += pwm-raspberrypi-poe.o
|
||||
+obj-$(CONFIG_PWM_RP1) += pwm-rp1.o
|
||||
obj-$(CONFIG_PWM_RCAR) += pwm-rcar.o
|
||||
obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o
|
||||
obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pwm/pwm-rp1.c
|
||||
@@ -0,0 +1,203 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * pwm-rp1.c
|
||||
+ *
|
||||
+ * Raspberry Pi RP1 PWM.
|
||||
+ *
|
||||
+ * Copyright © 2023 Raspberry Pi Ltd.
|
||||
+ *
|
||||
+ * Author: Naushir Patuck (naush@raspberrypi.com)
|
||||
+ *
|
||||
+ * Based on the pwm-bcm2835 driver by:
|
||||
+ * Bart Tanghe <bart.tanghe@thomasmore.be>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/pwm.h>
|
||||
+
|
||||
+#define PWM_GLOBAL_CTRL 0x000
|
||||
+#define PWM_CHANNEL_CTRL(x) (0x014 + ((x) * 16))
|
||||
+#define PWM_RANGE(x) (0x018 + ((x) * 16))
|
||||
+#define PWM_DUTY(x) (0x020 + ((x) * 16))
|
||||
+
|
||||
+/* 8:FIFO_POP_MASK + 0:Trailing edge M/S modulation */
|
||||
+#define PWM_CHANNEL_DEFAULT (BIT(8) + BIT(0))
|
||||
+#define PWM_CHANNEL_ENABLE(x) BIT(x)
|
||||
+#define PWM_POLARITY BIT(3)
|
||||
+#define SET_UPDATE BIT(31)
|
||||
+#define PWM_MODE_MASK GENMASK(1, 0)
|
||||
+
|
||||
+struct rp1_pwm {
|
||||
+ struct pwm_chip chip;
|
||||
+ struct device *dev;
|
||||
+ void __iomem *base;
|
||||
+ struct clk *clk;
|
||||
+};
|
||||
+
|
||||
+static inline struct rp1_pwm *to_rp1_pwm(struct pwm_chip *chip)
|
||||
+{
|
||||
+ return container_of(chip, struct rp1_pwm, chip);
|
||||
+}
|
||||
+
|
||||
+static void rp1_pwm_apply_config(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
+{
|
||||
+ struct rp1_pwm *pc = to_rp1_pwm(chip);
|
||||
+ u32 value;
|
||||
+
|
||||
+ value = readl(pc->base + PWM_GLOBAL_CTRL);
|
||||
+ value |= SET_UPDATE;
|
||||
+ writel(value, pc->base + PWM_GLOBAL_CTRL);
|
||||
+}
|
||||
+
|
||||
+static int rp1_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
+{
|
||||
+ struct rp1_pwm *pc = to_rp1_pwm(chip);
|
||||
+
|
||||
+ writel(PWM_CHANNEL_DEFAULT, pc->base + PWM_CHANNEL_CTRL(pwm->hwpwm));
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void rp1_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
+{
|
||||
+ struct rp1_pwm *pc = to_rp1_pwm(chip);
|
||||
+ u32 value;
|
||||
+
|
||||
+ value = readl(pc->base + PWM_CHANNEL_CTRL(pwm->hwpwm));
|
||||
+ value &= ~PWM_MODE_MASK;
|
||||
+ writel(value, pc->base + PWM_CHANNEL_CTRL(pwm->hwpwm));
|
||||
+ rp1_pwm_apply_config(chip, pwm);
|
||||
+}
|
||||
+
|
||||
+static int rp1_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
+ const struct pwm_state *state)
|
||||
+{
|
||||
+ struct rp1_pwm *pc = to_rp1_pwm(chip);
|
||||
+ unsigned long clk_rate = clk_get_rate(pc->clk);
|
||||
+ unsigned long clk_period;
|
||||
+ u32 value;
|
||||
+
|
||||
+ if (!clk_rate) {
|
||||
+ dev_err(pc->dev, "failed to get clock rate\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* set period */
|
||||
+ clk_period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, clk_rate);
|
||||
+
|
||||
+ writel(DIV_ROUND_CLOSEST(state->duty_cycle, clk_period),
|
||||
+ pc->base + PWM_DUTY(pwm->hwpwm));
|
||||
+
|
||||
+ /* set duty cycle */
|
||||
+ writel(DIV_ROUND_CLOSEST(state->period, clk_period),
|
||||
+ pc->base + PWM_RANGE(pwm->hwpwm));
|
||||
+
|
||||
+ /* set polarity */
|
||||
+ value = readl(pc->base + PWM_CHANNEL_CTRL(pwm->hwpwm));
|
||||
+ if (state->polarity == PWM_POLARITY_NORMAL)
|
||||
+ value &= ~PWM_POLARITY;
|
||||
+ else
|
||||
+ value |= PWM_POLARITY;
|
||||
+ writel(value, pc->base + PWM_CHANNEL_CTRL(pwm->hwpwm));
|
||||
+
|
||||
+ /* enable/disable */
|
||||
+ value = readl(pc->base + PWM_GLOBAL_CTRL);
|
||||
+ if (state->enabled)
|
||||
+ value |= PWM_CHANNEL_ENABLE(pwm->hwpwm);
|
||||
+ else
|
||||
+ value &= ~PWM_CHANNEL_ENABLE(pwm->hwpwm);
|
||||
+ writel(value, pc->base + PWM_GLOBAL_CTRL);
|
||||
+
|
||||
+ rp1_pwm_apply_config(chip, pwm);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct pwm_ops rp1_pwm_ops = {
|
||||
+ .request = rp1_pwm_request,
|
||||
+ .free = rp1_pwm_free,
|
||||
+ .apply = rp1_pwm_apply,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static int rp1_pwm_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct rp1_pwm *pc;
|
||||
+ struct resource *res;
|
||||
+ int ret;
|
||||
+
|
||||
+ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
|
||||
+ if (!pc)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ pc->dev = &pdev->dev;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ pc->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
+ if (IS_ERR(pc->base))
|
||||
+ return PTR_ERR(pc->base);
|
||||
+
|
||||
+ pc->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
+ if (IS_ERR(pc->clk))
|
||||
+ return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk),
|
||||
+ "clock not found\n");
|
||||
+
|
||||
+ ret = clk_prepare_enable(pc->clk);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ pc->chip.dev = &pdev->dev;
|
||||
+ pc->chip.ops = &rp1_pwm_ops;
|
||||
+ pc->chip.base = -1;
|
||||
+ pc->chip.npwm = 4;
|
||||
+ pc->chip.of_xlate = of_pwm_xlate_with_flags;
|
||||
+ pc->chip.of_pwm_n_cells = 3;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, pc);
|
||||
+
|
||||
+ ret = pwmchip_add(&pc->chip);
|
||||
+ if (ret < 0)
|
||||
+ goto add_fail;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+add_fail:
|
||||
+ clk_disable_unprepare(pc->clk);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int rp1_pwm_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct rp1_pwm *pc = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ clk_disable_unprepare(pc->clk);
|
||||
+
|
||||
+ pwmchip_remove(&pc->chip);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id rp1_pwm_of_match[] = {
|
||||
+ { .compatible = "raspberrypi,rp1-pwm" },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, rp1_pwm_of_match);
|
||||
+
|
||||
+static struct platform_driver rp1_pwm_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "rpi-pwm",
|
||||
+ .of_match_table = rp1_pwm_of_match,
|
||||
+ },
|
||||
+ .probe = rp1_pwm_probe,
|
||||
+ .remove = rp1_pwm_remove,
|
||||
+};
|
||||
+module_platform_driver(rp1_pwm_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Naushir Patuck <naush@raspberrypi.com");
|
||||
+MODULE_DESCRIPTION("RP1 PWM driver");
|
||||
+MODULE_LICENSE("GPL");
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
75
target/linux/bcm27xx/patches-6.1/950-0888-v4l2-Add-pisp-compression-format-support-to-v4l2.patch
Normal file
75
target/linux/bcm27xx/patches-6.1/950-0888-v4l2-Add-pisp-compression-format-support-to-v4l2.patch
Normal file
@ -0,0 +1,75 @@
|
||||
From 3a419974ba02d32795a5ecfaf3c020f23173b6a1 Mon Sep 17 00:00:00 2001
|
||||
From: Naushir Patuck <naush@raspberrypi.com>
|
||||
Date: Tue, 14 Feb 2023 20:58:59 +0000
|
||||
Subject: [PATCH] v4l2: Add pisp compression format support to v4l2
|
||||
|
||||
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
|
||||
---
|
||||
drivers/media/v4l2-core/v4l2-ioctl.c | 12 ++++++++----
|
||||
include/uapi/linux/media-bus-format.h | 14 ++++++++++++++
|
||||
include/uapi/linux/videodev2.h | 12 ++++++++----
|
||||
3 files changed, 30 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
|
||||
@@ -1507,10 +1507,14 @@ static void v4l_fill_fmtdesc(struct v4l2
|
||||
case V4L2_PIX_FMT_QC08C: descr = "QCOM Compressed 8-bit Format"; break;
|
||||
case V4L2_PIX_FMT_QC10C: descr = "QCOM Compressed 10-bit Format"; break;
|
||||
case V4L2_PIX_FMT_RPI_BE: descr = "PiSP Opaque Format"; break;
|
||||
- case V4L2_PIX_FMT_PISP_COMP_RGGB:
|
||||
- case V4L2_PIX_FMT_PISP_COMP_GRBG:
|
||||
- case V4L2_PIX_FMT_PISP_COMP_GBRG:
|
||||
- case V4L2_PIX_FMT_PISP_COMP_BGGR: descr = "PiSP Bayer Compressed Format"; break;
|
||||
+ case V4L2_PIX_FMT_PISP_COMP1_RGGB:
|
||||
+ case V4L2_PIX_FMT_PISP_COMP1_GRBG:
|
||||
+ case V4L2_PIX_FMT_PISP_COMP1_GBRG:
|
||||
+ case V4L2_PIX_FMT_PISP_COMP1_BGGR: descr = "PiSP Bayer Comp 1"; break;
|
||||
+ case V4L2_PIX_FMT_PISP_COMP2_RGGB:
|
||||
+ case V4L2_PIX_FMT_PISP_COMP2_GRBG:
|
||||
+ case V4L2_PIX_FMT_PISP_COMP2_GBRG:
|
||||
+ case V4L2_PIX_FMT_PISP_COMP2_BGGR: descr = "PiSP Bayer Comp 2"; break;
|
||||
default:
|
||||
if (fmt->description[0])
|
||||
return;
|
||||
--- a/include/uapi/linux/media-bus-format.h
|
||||
+++ b/include/uapi/linux/media-bus-format.h
|
||||
@@ -175,4 +175,18 @@
|
||||
/* Sensor ancillary metadata formats - next is 0x7002 */
|
||||
#define MEDIA_BUS_FMT_SENSOR_DATA 0x7002
|
||||
|
||||
+/* PiSP Formats */
|
||||
+#define MEDIA_BUS_FMT_PISP_COMP1_RGGB 0x8001
|
||||
+#define MEDIA_BUS_FMT_PISP_COMP1_GRBG 0x8002
|
||||
+#define MEDIA_BUS_FMT_PISP_COMP1_GBRG 0x8003
|
||||
+#define MEDIA_BUS_FMT_PISP_COMP1_BGGR 0x8004
|
||||
+#define MEDIA_BUS_FMT_PISP_COMP2_RGGB 0x8005
|
||||
+#define MEDIA_BUS_FMT_PISP_COMP2_GRBG 0x8006
|
||||
+#define MEDIA_BUS_FMT_PISP_COMP2_GBRG 0x8007
|
||||
+#define MEDIA_BUS_FMT_PISP_COMP2_BGGR 0x8008
|
||||
+
|
||||
+#define MEDIA_BUS_FMT_PISP_FE_CONFIG 0x8100
|
||||
+#define MEDIA_BUS_FMT_PISP_FE_STATS 0x8101
|
||||
+#define MEDIA_BUS_FMT_PISP_BE_CONFIG 0x8200
|
||||
+
|
||||
#endif /* __LINUX_MEDIA_BUS_FORMAT_H */
|
||||
--- a/include/uapi/linux/videodev2.h
|
||||
+++ b/include/uapi/linux/videodev2.h
|
||||
@@ -795,10 +795,14 @@ struct v4l2_pix_format {
|
||||
|
||||
/* The pixel format for all our buffers (the precise format is found in the config buffer). */
|
||||
#define V4L2_PIX_FMT_RPI_BE v4l2_fourcc('R', 'P', 'B', 'P')
|
||||
-#define V4L2_PIX_FMT_PISP_COMP_RGGB v4l2_fourcc('P', 'C', 'R', 'G')
|
||||
-#define V4L2_PIX_FMT_PISP_COMP_GRBG v4l2_fourcc('P', 'C', 'G', 'R')
|
||||
-#define V4L2_PIX_FMT_PISP_COMP_GBRG v4l2_fourcc('P', 'C', 'G', 'B')
|
||||
-#define V4L2_PIX_FMT_PISP_COMP_BGGR v4l2_fourcc('P', 'C', 'B', 'G')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP1_RGGB v4l2_fourcc('P', 'C', '1', 'R')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP1_GRBG v4l2_fourcc('P', 'C', '1', 'G')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP1_GBRG v4l2_fourcc('P', 'C', '1', 'g')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP1_BGGR v4l2_fourcc('P', 'C', '1', 'B')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP2_RGGB v4l2_fourcc('P', 'C', '2', 'R')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP2_GRBG v4l2_fourcc('P', 'C', '2', 'G')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP2_GBRG v4l2_fourcc('P', 'C', '2', 'g')
|
||||
+#define V4L2_PIX_FMT_PISP_COMP2_BGGR v4l2_fourcc('P', 'C', '2', 'B')
|
||||
|
||||
/* SDR formats - used only for Software Defined Radio devices */
|
||||
#define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */
|
4527
target/linux/bcm27xx/patches-6.1/950-0889-media-rp1-Add-CFE-Camera-Front-End-support.patch
Normal file
4527
target/linux/bcm27xx/patches-6.1/950-0889-media-rp1-Add-CFE-Camera-Front-End-support.patch
Normal file
File diff suppressed because it is too large
Load Diff
38
target/linux/bcm27xx/patches-6.1/950-0890-dt-bindings-net-cdns-macb-AXI-tuning-properties.patch
Normal file
38
target/linux/bcm27xx/patches-6.1/950-0890-dt-bindings-net-cdns-macb-AXI-tuning-properties.patch
Normal file
@ -0,0 +1,38 @@
|
||||
From 2be65d1fd1f7d3cf6f59b58b53e285400f04a160 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Wed, 15 Feb 2023 09:46:35 +0000
|
||||
Subject: [PATCH] dt-bindings: net: cdns,macb: AXI tuning properties
|
||||
|
||||
Add optional properties to tune the AXI interface -
|
||||
cdns,aw2w-max-pipe, cdns,ar2r-max-pipe and cdns,use-aw2b-fill.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
.../devicetree/bindings/net/cdns,macb.yaml | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/net/cdns,macb.yaml
|
||||
+++ b/Documentation/devicetree/bindings/net/cdns,macb.yaml
|
||||
@@ -121,6 +121,22 @@ properties:
|
||||
Node containing PHY children. If this node is not present, then PHYs will
|
||||
be direct children.
|
||||
|
||||
+ cdns,aw2w-max-pipe:
|
||||
+ $ref: /schemas/types.yaml#/definitions/uint32
|
||||
+ description:
|
||||
+ Maximum number of outstanding AXI write requests
|
||||
+
|
||||
+ cdns,ar2r-max-pipe:
|
||||
+ $ref: /schemas/types.yaml#/definitions/uint32
|
||||
+ description:
|
||||
+ Maximum number of outstanding AXI read requests
|
||||
+
|
||||
+ cdns,use-aw2b-fill:
|
||||
+ type: boolean
|
||||
+ description:
|
||||
+ If set, the maximum number of outstanding write transactions operates
|
||||
+ between the AW to B AXI channel, instead of the AW to W AXI channel.
|
||||
+
|
||||
patternProperties:
|
||||
"^ethernet-phy@[0-9a-f]$":
|
||||
type: object
|
29
target/linux/bcm27xx/patches-6.1/950-0891-ASoC-dwc-list-all-supported-sample-sizes.patch
Normal file
29
target/linux/bcm27xx/patches-6.1/950-0891-ASoC-dwc-list-all-supported-sample-sizes.patch
Normal file
@ -0,0 +1,29 @@
|
||||
From 9ef0615a5c5f93cb72af8df3a2dae6d23b106eb5 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Tue, 21 Feb 2023 21:26:16 +0000
|
||||
Subject: [PATCH] ASoC: dwc: list all supported sample sizes
|
||||
|
||||
The hardware configuration determines the maximum-supported sample size
|
||||
for each channel, but TCRx allows smaller sizes to be specified at run
|
||||
time. Include the smaller supported sizes in the formats array.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
sound/soc/dwc/dwc-i2s.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/sound/soc/dwc/dwc-i2s.c
|
||||
+++ b/sound/soc/dwc/dwc-i2s.c
|
||||
@@ -448,9 +448,9 @@ static const u32 bus_widths[COMP_MAX_DAT
|
||||
static const u32 formats[COMP_MAX_WORDSIZE] = {
|
||||
SNDRV_PCM_FMTBIT_S16_LE,
|
||||
SNDRV_PCM_FMTBIT_S16_LE,
|
||||
- SNDRV_PCM_FMTBIT_S24_LE,
|
||||
- SNDRV_PCM_FMTBIT_S24_LE,
|
||||
- SNDRV_PCM_FMTBIT_S32_LE,
|
||||
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
|
||||
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
|
||||
+ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
|
||||
0,
|
||||
0,
|
||||
0
|
@ -0,0 +1,59 @@
|
||||
From 06f794e8cb227249e03893e4b4923ff58556eb60 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Thu, 4 Mar 2021 14:49:23 +0000
|
||||
Subject: [PATCH] ASoC: dwc: Support set_bclk_ratio
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
sound/soc/dwc/dwc-i2s.c | 35 +++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 35 insertions(+)
|
||||
|
||||
--- a/sound/soc/dwc/dwc-i2s.c
|
||||
+++ b/sound/soc/dwc/dwc-i2s.c
|
||||
@@ -351,11 +351,46 @@ static int dw_i2s_set_fmt(struct snd_soc
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int dw_i2s_set_bclk_ratio(struct snd_soc_dai *cpu_dai,
|
||||
+ unsigned int ratio)
|
||||
+{
|
||||
+ struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
+ struct i2s_clk_config_data *config = &dev->config;
|
||||
+
|
||||
+ dev_err(dev->dev, "%s(%d)\n", __func__, ratio);
|
||||
+ switch (ratio) {
|
||||
+ case 32:
|
||||
+ config->data_width = 16;
|
||||
+ dev->ccr = 0x00;
|
||||
+ dev->xfer_resolution = 0x02;
|
||||
+ break;
|
||||
+
|
||||
+ case 48:
|
||||
+ config->data_width = 24;
|
||||
+ dev->ccr = 0x08;
|
||||
+ dev->xfer_resolution = 0x04;
|
||||
+ break;
|
||||
+
|
||||
+ case 64:
|
||||
+ config->data_width = 32;
|
||||
+ dev->ccr = 0x10;
|
||||
+ dev->xfer_resolution = 0x05;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ i2s_write_reg(dev->i2s_base, CCR, dev->ccr);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const struct snd_soc_dai_ops dw_i2s_dai_ops = {
|
||||
.hw_params = dw_i2s_hw_params,
|
||||
.prepare = dw_i2s_prepare,
|
||||
.trigger = dw_i2s_trigger,
|
||||
.set_fmt = dw_i2s_set_fmt,
|
||||
+ .set_bclk_ratio = dw_i2s_set_bclk_ratio,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
@ -0,0 +1,81 @@
|
||||
From b3b1177092d4d2ba6df74042d39aa42c5055f687 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Mon, 3 Jul 2023 09:08:16 +0100
|
||||
Subject: [PATCH] ASoC: dwc: Add DMACR handling
|
||||
|
||||
Add control of the DMACR register, which is required for paced DMA
|
||||
(i.e. DREQ) support.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
sound/soc/dwc/dwc-i2s.c | 13 ++++++++++---
|
||||
sound/soc/dwc/local.h | 13 +++++++++++++
|
||||
2 files changed, 23 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/sound/soc/dwc/dwc-i2s.c
|
||||
+++ b/sound/soc/dwc/dwc-i2s.c
|
||||
@@ -185,9 +185,9 @@ static void i2s_stop(struct dw_i2s_dev *
|
||||
|
||||
static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
|
||||
{
|
||||
- u32 ch_reg;
|
||||
struct i2s_clk_config_data *config = &dev->config;
|
||||
-
|
||||
+ u32 ch_reg;
|
||||
+ u32 dmacr = 0;
|
||||
|
||||
i2s_disable_channels(dev, stream);
|
||||
|
||||
@@ -198,15 +198,22 @@ static void dw_i2s_config(struct dw_i2s_
|
||||
i2s_write_reg(dev->i2s_base, TFCR(ch_reg),
|
||||
dev->fifo_th - 1);
|
||||
i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
|
||||
+ dmacr |= (DMACR_DMAEN_TXCH0 << ch_reg);
|
||||
} else {
|
||||
i2s_write_reg(dev->i2s_base, RCR(ch_reg),
|
||||
dev->xfer_resolution);
|
||||
i2s_write_reg(dev->i2s_base, RFCR(ch_reg),
|
||||
dev->fifo_th - 1);
|
||||
i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
|
||||
+ dmacr |= (DMACR_DMAEN_RXCH0 << ch_reg);
|
||||
}
|
||||
-
|
||||
}
|
||||
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
+ dmacr |= DMACR_DMAEN_TX;
|
||||
+ else if (stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
+ dmacr |= DMACR_DMAEN_RX;
|
||||
+
|
||||
+ i2s_write_reg(dev->i2s_base, DMACR, dmacr);
|
||||
}
|
||||
|
||||
static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
--- a/sound/soc/dwc/local.h
|
||||
+++ b/sound/soc/dwc/local.h
|
||||
@@ -25,6 +25,8 @@
|
||||
#define RXFFR 0x014
|
||||
#define TXFFR 0x018
|
||||
|
||||
+#define DMACR 0x200
|
||||
+
|
||||
/* Interrupt status register fields */
|
||||
#define ISR_TXFO BIT(5)
|
||||
#define ISR_TXFE BIT(4)
|
||||
@@ -47,6 +49,17 @@
|
||||
#define RFF(x) (0x40 * x + 0x050)
|
||||
#define TFF(x) (0x40 * x + 0x054)
|
||||
|
||||
+#define DMACR_DMAEN_TX BIT(17)
|
||||
+#define DMACR_DMAEN_RX BIT(16)
|
||||
+#define DMACR_DMAEN_TXCH3 BIT(11)
|
||||
+#define DMACR_DMAEN_TXCH2 BIT(10)
|
||||
+#define DMACR_DMAEN_TXCH1 BIT(9)
|
||||
+#define DMACR_DMAEN_TXCH0 BIT(8)
|
||||
+#define DMACR_DMAEN_RXCH3 BIT(3)
|
||||
+#define DMACR_DMAEN_RXCH2 BIT(2)
|
||||
+#define DMACR_DMAEN_RXCH1 BIT(1)
|
||||
+#define DMACR_DMAEN_RXCH0 BIT(0)
|
||||
+
|
||||
/* I2SCOMPRegisters */
|
||||
#define I2S_COMP_PARAM_2 0x01F0
|
||||
#define I2S_COMP_PARAM_1 0x01F4
|
@ -0,0 +1,128 @@
|
||||
From e6baee4502c0228c79408b047096a1259a84353f Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Mon, 3 Jul 2023 10:14:43 +0100
|
||||
Subject: [PATCH] ASOC: dwc: Improve DMA shutdown
|
||||
|
||||
Disabling the I2S interface with outstanding transfers prevents the
|
||||
DMAC from shutting down, so keep it partially active after a stop.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
sound/soc/dwc/dwc-i2s.c | 72 ++++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 64 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/sound/soc/dwc/dwc-i2s.c
|
||||
+++ b/sound/soc/dwc/dwc-i2s.c
|
||||
@@ -165,24 +165,26 @@ static void i2s_start(struct dw_i2s_dev
|
||||
i2s_write_reg(dev->i2s_base, CER, 1);
|
||||
}
|
||||
|
||||
-static void i2s_stop(struct dw_i2s_dev *dev,
|
||||
- struct snd_pcm_substream *substream)
|
||||
+static void i2s_pause(struct dw_i2s_dev *dev, struct snd_pcm_substream *substream)
|
||||
{
|
||||
|
||||
i2s_clear_irqs(dev, substream->stream);
|
||||
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
- i2s_write_reg(dev->i2s_base, ITER, 0);
|
||||
- else
|
||||
- i2s_write_reg(dev->i2s_base, IRER, 0);
|
||||
|
||||
i2s_disable_irqs(dev, substream->stream, 8);
|
||||
|
||||
if (!dev->active) {
|
||||
i2s_write_reg(dev->i2s_base, CER, 0);
|
||||
- i2s_write_reg(dev->i2s_base, IER, 0);
|
||||
+ /* Keep the device enabled until the shutdown - do not clear IER */
|
||||
}
|
||||
}
|
||||
|
||||
+static void i2s_stop(struct dw_i2s_dev *dev, struct snd_pcm_substream *substream)
|
||||
+{
|
||||
+ i2s_clear_irqs(dev, substream->stream);
|
||||
+
|
||||
+ i2s_disable_irqs(dev, substream->stream, 8);
|
||||
+}
|
||||
+
|
||||
static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
|
||||
{
|
||||
struct i2s_clk_config_data *config = &dev->config;
|
||||
@@ -288,6 +290,55 @@ static int dw_i2s_hw_params(struct snd_p
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int dw_i2s_startup(struct snd_pcm_substream *substream,
|
||||
+ struct snd_soc_dai *cpu_dai)
|
||||
+{
|
||||
+ struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
+ union dw_i2s_snd_dma_data *dma_data = NULL;
|
||||
+ u32 dmacr;
|
||||
+
|
||||
+ dev_dbg(dev->dev, "%s(%s)\n", __func__, substream->name);
|
||||
+ if (!(dev->capability & DWC_I2S_RECORD) &&
|
||||
+ substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!(dev->capability & DWC_I2S_PLAY) &&
|
||||
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ dw_i2s_config(dev, substream->stream);
|
||||
+ dmacr = i2s_read_reg(dev->i2s_base, DMACR);
|
||||
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
+ dma_data = &dev->play_dma_data;
|
||||
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
+ dma_data = &dev->capture_dma_data;
|
||||
+
|
||||
+ snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data);
|
||||
+ i2s_write_reg(dev->i2s_base, DMACR, dmacr);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void dw_i2s_shutdown(struct snd_pcm_substream *substream,
|
||||
+ struct snd_soc_dai *dai)
|
||||
+{
|
||||
+ struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
|
||||
+
|
||||
+ dev_dbg(dev->dev, "%s(%s)\n", __func__, substream->name);
|
||||
+ i2s_disable_channels(dev, substream->stream);
|
||||
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
+ i2s_write_reg(dev->i2s_base, ITER, 0);
|
||||
+ else
|
||||
+ i2s_write_reg(dev->i2s_base, IRER, 0);
|
||||
+
|
||||
+ i2s_disable_irqs(dev, substream->stream, 8);
|
||||
+
|
||||
+ if (!dev->active) {
|
||||
+ i2s_write_reg(dev->i2s_base, CER, 0);
|
||||
+ i2s_write_reg(dev->i2s_base, IER, 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int dw_i2s_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
@@ -315,9 +366,12 @@ static int dw_i2s_trigger(struct snd_pcm
|
||||
i2s_start(dev, substream);
|
||||
break;
|
||||
|
||||
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
+ dev->active--;
|
||||
+ i2s_pause(dev, substream);
|
||||
+ break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
dev->active--;
|
||||
i2s_stop(dev, substream);
|
||||
break;
|
||||
@@ -394,6 +448,8 @@ static int dw_i2s_set_bclk_ratio(struct
|
||||
|
||||
static const struct snd_soc_dai_ops dw_i2s_dai_ops = {
|
||||
.hw_params = dw_i2s_hw_params,
|
||||
+ .startup = dw_i2s_startup,
|
||||
+ .shutdown = dw_i2s_shutdown,
|
||||
.prepare = dw_i2s_prepare,
|
||||
.trigger = dw_i2s_trigger,
|
||||
.set_fmt = dw_i2s_set_fmt,
|
@ -0,0 +1,88 @@
|
||||
From 9c6694c24f26ea435165431d41c72451fadbd753 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Fri, 21 Jul 2023 12:07:16 +0100
|
||||
Subject: [PATCH] ASOC: dwc: Fix 16-bit audio handling
|
||||
|
||||
IMO the Synopsys datasheet could be clearer in this area, but it seems
|
||||
that the DMA data ports (DMATX and DMARX) expect left and right samples
|
||||
in alternate writes; if a stereo pair is pushed in a single 32-bit
|
||||
write, the upper half is ignored, leading to double speed audio with a
|
||||
confused stereo image. Make sure the necessary changes happen by
|
||||
updating the DMA configuration data in the hw_params method.
|
||||
|
||||
The set_bclk_ratio change was made at a time when it looked like it
|
||||
could be causing an error, but I think the division of responsibilities
|
||||
is clearer this way (and the kernel log clearer without the info-level
|
||||
message).
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
sound/soc/dwc/dwc-i2s.c | 22 +++++++++++++++-------
|
||||
1 file changed, 15 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/sound/soc/dwc/dwc-i2s.c
|
||||
+++ b/sound/soc/dwc/dwc-i2s.c
|
||||
@@ -223,23 +223,34 @@ static int dw_i2s_hw_params(struct snd_p
|
||||
{
|
||||
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
|
||||
struct i2s_clk_config_data *config = &dev->config;
|
||||
+ union dw_i2s_snd_dma_data *dma_data = NULL;
|
||||
int ret;
|
||||
|
||||
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
+ dma_data = &dev->play_dma_data;
|
||||
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
+ dma_data = &dev->capture_dma_data;
|
||||
+ else
|
||||
+ return -1;
|
||||
+
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
config->data_width = 16;
|
||||
+ dma_data->dt.addr_width = 2;
|
||||
dev->ccr = 0x00;
|
||||
dev->xfer_resolution = 0x02;
|
||||
break;
|
||||
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
config->data_width = 24;
|
||||
+ dma_data->dt.addr_width = 4;
|
||||
dev->ccr = 0x08;
|
||||
dev->xfer_resolution = 0x04;
|
||||
break;
|
||||
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
config->data_width = 32;
|
||||
+ dma_data->dt.addr_width = 4;
|
||||
dev->ccr = 0x10;
|
||||
dev->xfer_resolution = 0x05;
|
||||
break;
|
||||
@@ -418,24 +429,21 @@ static int dw_i2s_set_bclk_ratio(struct
|
||||
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
struct i2s_clk_config_data *config = &dev->config;
|
||||
|
||||
- dev_err(dev->dev, "%s(%d)\n", __func__, ratio);
|
||||
+ dev_dbg(dev->dev, "%s(%d)\n", __func__, ratio);
|
||||
+ if (ratio < config->data_width * 2)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
switch (ratio) {
|
||||
case 32:
|
||||
- config->data_width = 16;
|
||||
dev->ccr = 0x00;
|
||||
- dev->xfer_resolution = 0x02;
|
||||
break;
|
||||
|
||||
case 48:
|
||||
- config->data_width = 24;
|
||||
dev->ccr = 0x08;
|
||||
- dev->xfer_resolution = 0x04;
|
||||
break;
|
||||
|
||||
case 64:
|
||||
- config->data_width = 32;
|
||||
dev->ccr = 0x10;
|
||||
- dev->xfer_resolution = 0x05;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
304
target/linux/bcm27xx/patches-6.1/950-0896-ASoC-bcm-Remove-dependency-on-BCM2835-I2S.patch
Normal file
304
target/linux/bcm27xx/patches-6.1/950-0896-ASoC-bcm-Remove-dependency-on-BCM2835-I2S.patch
Normal file
@ -0,0 +1,304 @@
|
||||
From f476db1b71e8b82e5299168f963a2fefb7a395e2 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Fri, 1 Sep 2023 14:07:48 +0100
|
||||
Subject: [PATCH] ASoC: bcm: Remove dependency on BCM2835 I2S
|
||||
|
||||
These soundcard drivers don't rely on a specific I2S interface, so
|
||||
remove the dependency declarations.
|
||||
|
||||
See: https://github.com/raspberrypi/linux-2712/issues/111
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
sound/soc/bcm/Kconfig | 40 +---------------------------------------
|
||||
1 file changed, 1 insertion(+), 39 deletions(-)
|
||||
|
||||
--- a/sound/soc/bcm/Kconfig
|
||||
+++ b/sound/soc/bcm/Kconfig
|
||||
@@ -29,13 +29,11 @@ config SND_BCM63XX_I2S_WHISTLER
|
||||
|
||||
config SND_BCM2708_SOC_CHIPDIP_DAC
|
||||
tristate "Support for the ChipDip DAC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
help
|
||||
Say Y or M if you want to add support for the ChipDip DAC soundcard
|
||||
|
||||
config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD
|
||||
tristate "Support for Google voiceHAT soundcard"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_VOICEHAT
|
||||
select SND_RPI_SIMPLE_SOUNDCARD
|
||||
help
|
||||
@@ -43,7 +41,6 @@ config SND_BCM2708_SOC_GOOGLEVOICEHAT_SO
|
||||
|
||||
config SND_BCM2708_SOC_HIFIBERRY_DAC
|
||||
tristate "Support for HifiBerry DAC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM5102A
|
||||
select SND_RPI_SIMPLE_SOUNDCARD
|
||||
help
|
||||
@@ -51,7 +48,6 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC
|
||||
|
||||
config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
|
||||
tristate "Support for HifiBerry DAC+"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM512x
|
||||
select SND_SOC_TPA6130A2
|
||||
select COMMON_CLK_HIFIBERRY_DACPRO
|
||||
@@ -60,7 +56,6 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
|
||||
|
||||
config SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD
|
||||
tristate "Support for HifiBerry DAC+ HD"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM179X_I2C
|
||||
select COMMON_CLK_HIFIBERRY_DACPLUSHD
|
||||
help
|
||||
@@ -68,7 +63,6 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
|
||||
|
||||
config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC
|
||||
tristate "Support for HifiBerry DAC+ADC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM512x_I2C
|
||||
select SND_SOC_DMIC
|
||||
select COMMON_CLK_HIFIBERRY_DACPRO
|
||||
@@ -77,7 +71,6 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
|
||||
|
||||
config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO
|
||||
tristate "Support for HifiBerry DAC+ADC PRO"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM512x_I2C
|
||||
select SND_SOC_PCM186X_I2C
|
||||
select SND_SOC_TPA6130A2
|
||||
@@ -87,29 +80,25 @@ config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
|
||||
|
||||
config SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP
|
||||
tristate "Support for HifiBerry DAC+DSP"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_RPI_SIMPLE_SOUNDCARD
|
||||
help
|
||||
Say Y or M if you want to add support for HifiBerry DSP-DAC.
|
||||
|
||||
config SND_BCM2708_SOC_HIFIBERRY_DIGI
|
||||
tristate "Support for HifiBerry Digi"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_WM8804
|
||||
help
|
||||
Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board.
|
||||
|
||||
config SND_BCM2708_SOC_HIFIBERRY_AMP
|
||||
tristate "Support for the HifiBerry Amp"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_TAS5713
|
||||
select SND_RPI_SIMPLE_SOUNDCARD
|
||||
help
|
||||
Say Y or M if you want to add support for the HifiBerry Amp amplifier board.
|
||||
|
||||
- config SND_BCM2708_SOC_PIFI_40
|
||||
+config SND_BCM2708_SOC_PIFI_40
|
||||
tristate "Support for the PiFi-40 amp"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_TAS571X
|
||||
select SND_PIFI_40
|
||||
help
|
||||
@@ -117,7 +106,6 @@ config SND_BCM2708_SOC_HIFIBERRY_AMP
|
||||
|
||||
config SND_BCM2708_SOC_RPI_CIRRUS
|
||||
tristate "Support for Cirrus Logic Audio Card"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_WM5102
|
||||
select SND_SOC_WM8804
|
||||
help
|
||||
@@ -126,7 +114,6 @@ config SND_BCM2708_SOC_RPI_CIRRUS
|
||||
|
||||
config SND_BCM2708_SOC_RPI_DAC
|
||||
tristate "Support for RPi-DAC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM1794A
|
||||
select SND_RPI_SIMPLE_SOUNDCARD
|
||||
help
|
||||
@@ -134,14 +121,12 @@ config SND_BCM2708_SOC_RPI_DAC
|
||||
|
||||
config SND_BCM2708_SOC_RPI_PROTO
|
||||
tristate "Support for Rpi-PROTO"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_WM8731_I2C
|
||||
help
|
||||
Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731).
|
||||
|
||||
config SND_BCM2708_SOC_JUSTBOOM_BOTH
|
||||
tristate "Support for simultaneous JustBoom Digi and JustBoom DAC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_WM8804
|
||||
select SND_SOC_PCM512x
|
||||
help
|
||||
@@ -153,14 +138,12 @@ config SND_BCM2708_SOC_JUSTBOOM_BOTH
|
||||
|
||||
config SND_BCM2708_SOC_JUSTBOOM_DAC
|
||||
tristate "Support for JustBoom DAC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM512x
|
||||
help
|
||||
Say Y or M if you want to add support for JustBoom DAC.
|
||||
|
||||
config SND_BCM2708_SOC_JUSTBOOM_DIGI
|
||||
tristate "Support for JustBoom Digi"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_WM8804
|
||||
select SND_RPI_WM8804_SOUNDCARD
|
||||
help
|
||||
@@ -168,21 +151,18 @@ config SND_BCM2708_SOC_JUSTBOOM_DIGI
|
||||
|
||||
config SND_BCM2708_SOC_IQAUDIO_CODEC
|
||||
tristate "Support for IQaudIO-CODEC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_DA7213
|
||||
help
|
||||
Say Y or M if you want to add support for IQaudIO-CODEC.
|
||||
|
||||
config SND_BCM2708_SOC_IQAUDIO_DAC
|
||||
tristate "Support for IQaudIO-DAC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM512x_I2C
|
||||
help
|
||||
Say Y or M if you want to add support for IQaudIO-DAC.
|
||||
|
||||
config SND_BCM2708_SOC_IQAUDIO_DIGI
|
||||
tristate "Support for IQAudIO Digi"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_WM8804
|
||||
select SND_RPI_WM8804_SOUNDCARD
|
||||
help
|
||||
@@ -190,14 +170,12 @@ config SND_BCM2708_SOC_IQAUDIO_DIGI
|
||||
|
||||
config SND_BCM2708_SOC_I_SABRE_Q2M
|
||||
tristate "Support for Audiophonics I-Sabre Q2M DAC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_I_SABRE_CODEC
|
||||
help
|
||||
Say Y or M if you want to add support for Audiophonics I-SABRE Q2M DAC
|
||||
|
||||
config SND_BCM2708_SOC_ADAU1977_ADC
|
||||
tristate "Support for ADAU1977 ADC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_ADAU1977_I2C
|
||||
select SND_RPI_SIMPLE_SOUNDCARD
|
||||
help
|
||||
@@ -205,35 +183,30 @@ config SND_BCM2708_SOC_ADAU1977_ADC
|
||||
|
||||
config SND_AUDIOINJECTOR_PI_SOUNDCARD
|
||||
tristate "Support for audioinjector.net Pi add on soundcard"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_WM8731_I2C
|
||||
help
|
||||
Say Y or M if you want to add support for audioinjector.net Pi Hat
|
||||
|
||||
config SND_AUDIOINJECTOR_OCTO_SOUNDCARD
|
||||
tristate "Support for audioinjector.net Octo channel (Hat) soundcard"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_CS42XX8_I2C
|
||||
help
|
||||
Say Y or M if you want to add support for audioinjector.net octo add on
|
||||
|
||||
config SND_AUDIOINJECTOR_ISOLATED_SOUNDCARD
|
||||
tristate "Support for audioinjector.net isolated DAC and ADC soundcard"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_CS4271_I2C
|
||||
help
|
||||
Say Y or M if you want to add support for audioinjector.net isolated soundcard
|
||||
|
||||
config SND_AUDIOSENSE_PI
|
||||
tristate "Support for AudioSense Add-On Soundcard"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_TLV320AIC32X4_I2C
|
||||
help
|
||||
Say Y or M if you want to add support for tlv320aic32x4 add-on
|
||||
|
||||
config SND_DIGIDAC1_SOUNDCARD
|
||||
tristate "Support for Red Rocks Audio DigiDAC1"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_WM8804
|
||||
select SND_SOC_WM8741
|
||||
help
|
||||
@@ -241,35 +214,30 @@ config SND_DIGIDAC1_SOUNDCARD
|
||||
|
||||
config SND_BCM2708_SOC_DIONAUDIO_LOCO
|
||||
tristate "Support for Dion Audio LOCO DAC-AMP"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM5102a
|
||||
help
|
||||
Say Y or M if you want to add support for Dion Audio LOCO.
|
||||
|
||||
config SND_BCM2708_SOC_DIONAUDIO_LOCO_V2
|
||||
tristate "Support for Dion Audio LOCO-V2 DAC-AMP"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM5122
|
||||
help
|
||||
Say Y or M if you want to add support for Dion Audio LOCO-V2.
|
||||
|
||||
config SND_BCM2708_SOC_ALLO_PIANO_DAC
|
||||
tristate "Support for Allo Piano DAC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM512x_I2C
|
||||
help
|
||||
Say Y or M if you want to add support for Allo Piano DAC.
|
||||
|
||||
config SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS
|
||||
tristate "Support for Allo Piano DAC Plus"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM512x_I2C
|
||||
help
|
||||
Say Y or M if you want to add support for Allo Piano DAC Plus.
|
||||
|
||||
config SND_BCM2708_SOC_ALLO_BOSS_DAC
|
||||
tristate "Support for Allo Boss DAC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_PCM512x_I2C
|
||||
select COMMON_CLK_HIFIBERRY_DACPRO
|
||||
help
|
||||
@@ -277,7 +245,6 @@ config SND_BCM2708_SOC_ALLO_BOSS_DAC
|
||||
|
||||
config SND_BCM2708_SOC_ALLO_BOSS2_DAC
|
||||
tristate "Support for Allo Boss2 DAC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
select SND_AUDIO_GRAPH_CARD
|
||||
@@ -286,7 +253,6 @@ config SND_BCM2708_SOC_ALLO_BOSS2_DAC
|
||||
|
||||
config SND_BCM2708_SOC_ALLO_DIGIONE
|
||||
tristate "Support for Allo DigiOne"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_WM8804
|
||||
select SND_RPI_WM8804_SOUNDCARD
|
||||
help
|
||||
@@ -294,7 +260,6 @@ config SND_BCM2708_SOC_ALLO_DIGIONE
|
||||
|
||||
config SND_BCM2708_SOC_ALLO_KATANA_DAC
|
||||
tristate "Support for Allo Katana DAC"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
select SND_AUDIO_GRAPH_CARD
|
||||
@@ -303,14 +268,12 @@ config SND_BCM2708_SOC_ALLO_KATANA_DAC
|
||||
|
||||
config SND_BCM2708_SOC_FE_PI_AUDIO
|
||||
tristate "Support for Fe-Pi-Audio"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_SGTL5000
|
||||
help
|
||||
Say Y or M if you want to add support for Fe-Pi-Audio.
|
||||
|
||||
config SND_PISOUND
|
||||
tristate "Support for Blokas Labs pisound"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_RAWMIDI
|
||||
help
|
||||
Say Y or M if you want to add support for Blokas Labs pisound.
|
||||
@@ -328,7 +291,6 @@ config SND_RPI_WM8804_SOUNDCARD
|
||||
|
||||
config SND_DACBERRY400
|
||||
tristate "Support for DACBERRY400 Soundcard"
|
||||
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||
select SND_SOC_TLV320AIC3X_I2C
|
||||
help
|
||||
Say Y or M if you want to add support for tlv320aic3x add-on
|
343
target/linux/bcm27xx/patches-6.1/950-0897-hwmon-Add-RP1-ADC-and-temperature-driver.patch
Normal file
343
target/linux/bcm27xx/patches-6.1/950-0897-hwmon-Add-RP1-ADC-and-temperature-driver.patch
Normal file
@ -0,0 +1,343 @@
|
||||
From cad3c92ff0c1a5fa539d08b695b0f6b326924890 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Thu, 2 Mar 2023 18:04:42 +0000
|
||||
Subject: [PATCH] hwmon: Add RP1 ADC and temperature driver
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/hwmon/Kconfig | 7 +
|
||||
drivers/hwmon/Makefile | 1 +
|
||||
drivers/hwmon/rp1-adc.c | 301 ++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 309 insertions(+)
|
||||
create mode 100644 drivers/hwmon/rp1-adc.c
|
||||
|
||||
--- a/drivers/hwmon/Kconfig
|
||||
+++ b/drivers/hwmon/Kconfig
|
||||
@@ -2331,6 +2331,13 @@ config SENSORS_INTEL_M10_BMC_HWMON
|
||||
sensors monitor various telemetry data of different components on the
|
||||
card, e.g. board temperature, FPGA core temperature/voltage/current.
|
||||
|
||||
+config SENSORS_RP1_ADC
|
||||
+ tristate "RP1 ADC and temperature sensor driver"
|
||||
+ depends on MFD_RP1
|
||||
+ help
|
||||
+ Say yes here to enable support for the voltage and temperature
|
||||
+ sensors of the Raspberry Pi RP1 peripheral chip.
|
||||
+
|
||||
if ACPI
|
||||
|
||||
comment "ACPI drivers"
|
||||
--- a/drivers/hwmon/Makefile
|
||||
+++ b/drivers/hwmon/Makefile
|
||||
@@ -173,6 +173,7 @@ obj-$(CONFIG_SENSORS_PCF8591) += pcf8591
|
||||
obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o
|
||||
obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
|
||||
obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
|
||||
+obj-$(CONFIG_SENSORS_RP1_ADC) += rp1-adc.o
|
||||
obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_SBTSI) += sbtsi_temp.o
|
||||
obj-$(CONFIG_SENSORS_SBRMI) += sbrmi.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/hwmon/rp1-adc.c
|
||||
@@ -0,0 +1,301 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/*
|
||||
+ * Driver for the RP1 ADC and temperature sensor
|
||||
+ * Copyright (C) 2023 Raspberry Pi Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/hwmon.h>
|
||||
+#include <linux/hwmon-sysfs.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mod_devicetable.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regulator/consumer.h>
|
||||
+
|
||||
+#define MODULE_NAME "rp1-adc"
|
||||
+
|
||||
+#define RP1_ADC_CS 0x00
|
||||
+#define RP1_ADC_RESULT 0x04
|
||||
+#define RP1_ADC_FCS 0x08
|
||||
+#define RP1_ADC_FIFO 0x0c
|
||||
+#define RP1_ADC_DIV 0x10
|
||||
+
|
||||
+#define RP1_ADC_INTR 0x14
|
||||
+#define RP1_ADC_INTE 0x18
|
||||
+#define RP1_ADC_INTF 0x1c
|
||||
+#define RP1_ADC_INTS 0x20
|
||||
+
|
||||
+#define RP1_ADC_RWTYPE_SET 0x2000
|
||||
+#define RP1_ADC_RWTYPE_CLR 0x3000
|
||||
+
|
||||
+#define RP1_ADC_CS_RROBIN_MASK 0x1f
|
||||
+#define RP1_ADC_CS_RROBIN_SHIFT 16
|
||||
+#define RP1_ADC_CS_AINSEL_MASK 0x7
|
||||
+#define RP1_ADC_CS_AINSEL_SHIFT 12
|
||||
+#define RP1_ADC_CS_ERR_STICKY 0x400
|
||||
+#define RP1_ADC_CS_ERR 0x200
|
||||
+#define RP1_ADC_CS_READY 0x100
|
||||
+#define RP1_ADC_CS_START_MANY 0x8
|
||||
+#define RP1_ADC_CS_START_ONCE 0x4
|
||||
+#define RP1_ADC_CS_TS_EN 0x2
|
||||
+#define RP1_ADC_CS_EN 0x1
|
||||
+
|
||||
+#define RP1_ADC_FCS_THRESH_MASK 0xf
|
||||
+#define RP1_ADC_FCS_THRESH_SHIFT 24
|
||||
+#define RP1_ADC_FCS_LEVEL_MASK 0xf
|
||||
+#define RP1_ADC_FCS_LEVEL_SHIFT 16
|
||||
+#define RP1_ADC_FCS_OVER 0x800
|
||||
+#define RP1_ADC_FCS_UNDER 0x400
|
||||
+#define RP1_ADC_FCS_FULL 0x200
|
||||
+#define RP1_ADC_FCS_EMPTY 0x100
|
||||
+#define RP1_ADC_FCS_DREQ_EN 0x8
|
||||
+#define RP1_ADC_FCS_ERR 0x4
|
||||
+#define RP1_ADC_FCS_SHIFR 0x2
|
||||
+#define RP1_ADC_FCS_EN 0x1
|
||||
+
|
||||
+#define RP1_ADC_FIFO_ERR 0x8000
|
||||
+#define RP1_ADC_FIFO_VAL_MASK 0xfff
|
||||
+
|
||||
+#define RP1_ADC_DIV_INT_MASK 0xffff
|
||||
+#define RP1_ADC_DIV_INT_SHIFT 8
|
||||
+#define RP1_ADC_DIV_FRAC_MASK 0xff
|
||||
+#define RP1_ADC_DIV_FRAC_SHIFT 0
|
||||
+
|
||||
+struct rp1_adc_data {
|
||||
+ void __iomem *base;
|
||||
+ spinlock_t lock;
|
||||
+ struct device *hwmon_dev;
|
||||
+ int vref_mv;
|
||||
+};
|
||||
+
|
||||
+static int rp1_adc_ready_wait(struct rp1_adc_data *data)
|
||||
+{
|
||||
+ int retries = 10;
|
||||
+
|
||||
+ while (retries && !(readl(data->base + RP1_ADC_CS) & RP1_ADC_CS_READY))
|
||||
+ retries--;
|
||||
+
|
||||
+ return retries ? 0 : -EIO;
|
||||
+}
|
||||
+
|
||||
+static int rp1_adc_read(struct rp1_adc_data *data,
|
||||
+ struct device_attribute *devattr, unsigned int *val)
|
||||
+{
|
||||
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
+ int channel = attr->index;
|
||||
+ int ret;
|
||||
+
|
||||
+ spin_lock(&data->lock);
|
||||
+
|
||||
+ writel(RP1_ADC_CS_AINSEL_MASK << RP1_ADC_CS_AINSEL_SHIFT,
|
||||
+ data->base + RP1_ADC_RWTYPE_CLR + RP1_ADC_CS);
|
||||
+ writel(channel << RP1_ADC_CS_AINSEL_SHIFT,
|
||||
+ data->base + RP1_ADC_RWTYPE_SET + RP1_ADC_CS);
|
||||
+ writel(RP1_ADC_CS_START_ONCE,
|
||||
+ data->base + RP1_ADC_RWTYPE_SET + RP1_ADC_CS);
|
||||
+
|
||||
+ ret = rp1_adc_ready_wait(data);
|
||||
+ if (!ret)
|
||||
+ *val = readl(data->base + RP1_ADC_RESULT);
|
||||
+
|
||||
+ spin_unlock(&data->lock);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int rp1_adc_to_mv(struct rp1_adc_data *data, unsigned int val)
|
||||
+{
|
||||
+ return ((u64)data->vref_mv * val) / 0xfff;
|
||||
+}
|
||||
+
|
||||
+static ssize_t rp1_adc_show(struct device *dev,
|
||||
+ struct device_attribute *devattr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct rp1_adc_data *data = dev_get_drvdata(dev);
|
||||
+ unsigned int val;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = rp1_adc_read(data, devattr, &val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return sprintf(buf, "%d\n", rp1_adc_to_mv(data, val));
|
||||
+}
|
||||
+
|
||||
+static ssize_t rp1_adc_temp_show(struct device *dev,
|
||||
+ struct device_attribute *devattr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct rp1_adc_data *data = dev_get_drvdata(dev);
|
||||
+ unsigned int val;
|
||||
+ int ret, mv, mc;
|
||||
+
|
||||
+ writel(RP1_ADC_CS_TS_EN,
|
||||
+ data->base + RP1_ADC_RWTYPE_SET + RP1_ADC_CS);
|
||||
+ ret = rp1_adc_read(data, devattr, &val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ mv = rp1_adc_to_mv(data, val);
|
||||
+
|
||||
+ /* T = 27 - (ADC_voltage - 0.706)/0.001721 */
|
||||
+
|
||||
+ mc = 27000 - DIV_ROUND_CLOSEST((mv - 706) * (s64)1000000, 1721);
|
||||
+
|
||||
+ return sprintf(buf, "%d\n", mc);
|
||||
+}
|
||||
+
|
||||
+static ssize_t rp1_adc_raw_show(struct device *dev,
|
||||
+ struct device_attribute *devattr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct rp1_adc_data *data = dev_get_drvdata(dev);
|
||||
+ unsigned int val;
|
||||
+ int ret = rp1_adc_read(data, devattr, &val);
|
||||
+
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return sprintf(buf, "%u\n", val);
|
||||
+}
|
||||
+
|
||||
+static ssize_t rp1_adc_temp_raw_show(struct device *dev,
|
||||
+ struct device_attribute *devattr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct rp1_adc_data *data = dev_get_drvdata(dev);
|
||||
+ unsigned int val;
|
||||
+ int ret = rp1_adc_read(data, devattr, &val);
|
||||
+
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return sprintf(buf, "%u\n", val);
|
||||
+}
|
||||
+
|
||||
+static SENSOR_DEVICE_ATTR_RO(in1_input, rp1_adc, 0);
|
||||
+static SENSOR_DEVICE_ATTR_RO(in2_input, rp1_adc, 1);
|
||||
+static SENSOR_DEVICE_ATTR_RO(in3_input, rp1_adc, 2);
|
||||
+static SENSOR_DEVICE_ATTR_RO(in4_input, rp1_adc, 3);
|
||||
+static SENSOR_DEVICE_ATTR_RO(temp1_input, rp1_adc_temp, 4);
|
||||
+static SENSOR_DEVICE_ATTR_RO(in1_raw, rp1_adc_raw, 0);
|
||||
+static SENSOR_DEVICE_ATTR_RO(in2_raw, rp1_adc_raw, 1);
|
||||
+static SENSOR_DEVICE_ATTR_RO(in3_raw, rp1_adc_raw, 2);
|
||||
+static SENSOR_DEVICE_ATTR_RO(in4_raw, rp1_adc_raw, 3);
|
||||
+static SENSOR_DEVICE_ATTR_RO(temp1_raw, rp1_adc_temp_raw, 4);
|
||||
+
|
||||
+static struct attribute *rp1_adc_attrs[] = {
|
||||
+ &sensor_dev_attr_in1_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in2_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in3_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in4_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in1_raw.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in2_raw.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in3_raw.dev_attr.attr,
|
||||
+ &sensor_dev_attr_in4_raw.dev_attr.attr,
|
||||
+ &sensor_dev_attr_temp1_raw.dev_attr.attr,
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+static umode_t rp1_adc_is_visible(struct kobject *kobj,
|
||||
+ struct attribute *attr, int index)
|
||||
+{
|
||||
+ return 0444;
|
||||
+}
|
||||
+
|
||||
+static const struct attribute_group rp1_adc_group = {
|
||||
+ .attrs = rp1_adc_attrs,
|
||||
+ .is_visible = rp1_adc_is_visible,
|
||||
+};
|
||||
+__ATTRIBUTE_GROUPS(rp1_adc);
|
||||
+
|
||||
+static int __init rp1_adc_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct rp1_adc_data *data;
|
||||
+ struct regulator *reg;
|
||||
+ struct clk *clk;
|
||||
+ int vref_uv, ret;
|
||||
+
|
||||
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
+ if (!data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ spin_lock_init(&data->lock);
|
||||
+
|
||||
+ data->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(data->base))
|
||||
+ return PTR_ERR(data->base);
|
||||
+
|
||||
+ platform_set_drvdata(pdev, data);
|
||||
+
|
||||
+ clk = devm_clk_get(&pdev->dev, NULL);
|
||||
+ if (IS_ERR(clk))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ clk_set_rate(clk, 50000000);
|
||||
+ clk_prepare_enable(clk);
|
||||
+
|
||||
+ reg = devm_regulator_get(&pdev->dev, "vref");
|
||||
+ if (IS_ERR(reg))
|
||||
+ return PTR_ERR(reg);
|
||||
+
|
||||
+ vref_uv = regulator_get_voltage(reg);
|
||||
+ data->vref_mv = DIV_ROUND_CLOSEST(vref_uv, 1000);
|
||||
+
|
||||
+ data->hwmon_dev =
|
||||
+ devm_hwmon_device_register_with_groups(&pdev->dev,
|
||||
+ "rp1_adc",
|
||||
+ data,
|
||||
+ rp1_adc_groups);
|
||||
+ if (IS_ERR(data->hwmon_dev)) {
|
||||
+ ret = PTR_ERR(data->hwmon_dev);
|
||||
+ dev_err(&pdev->dev, "hwmon_device_register failed with %d.\n", ret);
|
||||
+ goto err_register;
|
||||
+ }
|
||||
+
|
||||
+ /* Disable interrupts */
|
||||
+ writel(0, data->base + RP1_ADC_INTE);
|
||||
+
|
||||
+ /* Enable the block, clearing any sticky error */
|
||||
+ writel(RP1_ADC_CS_EN | RP1_ADC_CS_ERR_STICKY, data->base + RP1_ADC_CS);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_register:
|
||||
+ sysfs_remove_group(&pdev->dev.kobj, &rp1_adc_group);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int rp1_adc_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct rp1_adc_data *data = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ hwmon_device_unregister(data->hwmon_dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id rp1_adc_dt_ids[] = {
|
||||
+ { .compatible = "raspberrypi,rp1-adc", },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, rp1_adc_dt_ids);
|
||||
+
|
||||
+static struct platform_driver rp1_adc_driver = {
|
||||
+ .remove = rp1_adc_remove,
|
||||
+ .driver = {
|
||||
+ .name = MODULE_NAME,
|
||||
+ .of_match_table = rp1_adc_dt_ids,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver_probe(rp1_adc_driver, rp1_adc_probe);
|
||||
+
|
||||
+MODULE_DESCRIPTION("RP1 ADC driver");
|
||||
+MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.com>");
|
||||
+MODULE_LICENSE("GPL");
|
69
target/linux/bcm27xx/patches-6.1/950-0898-mfd-bcm2835-pm-Add-support-for-BCM2712.patch
Normal file
69
target/linux/bcm27xx/patches-6.1/950-0898-mfd-bcm2835-pm-Add-support-for-BCM2712.patch
Normal file
@ -0,0 +1,69 @@
|
||||
From 0c7aeb96fd3ab68011ba6c24239c501190890308 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Wed, 8 Mar 2023 14:27:58 +0000
|
||||
Subject: [PATCH] mfd: bcm2835-pm: Add support for BCM2712
|
||||
|
||||
BCM2712 lacks the "asb" and "rpivid_asb" register ranges, but still
|
||||
requires the use of the bcm2835-power driver to reset the V3D block.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/mfd/bcm2835-pm.c | 28 +++++++++++++++++++---------
|
||||
1 file changed, 19 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/mfd/bcm2835-pm.c
|
||||
+++ b/drivers/mfd/bcm2835-pm.c
|
||||
@@ -69,12 +69,30 @@ static int bcm2835_pm_get_pdata(struct p
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static const struct of_device_id bcm2835_pm_of_match[] = {
|
||||
+ { .compatible = "brcm,bcm2835-pm-wdt", },
|
||||
+ { .compatible = "brcm,bcm2835-pm", },
|
||||
+ { .compatible = "brcm,bcm2711-pm", },
|
||||
+ { .compatible = "brcm,bcm2712-pm", .data = (const void *)1},
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
|
||||
+
|
||||
static int bcm2835_pm_probe(struct platform_device *pdev)
|
||||
{
|
||||
+ const struct of_device_id *of_id;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct bcm2835_pm *pm;
|
||||
+ bool is_2712;
|
||||
int ret;
|
||||
|
||||
+ of_id = of_match_node(bcm2835_pm_of_match, pdev->dev.of_node);
|
||||
+ if (!of_id) {
|
||||
+ dev_err(&pdev->dev, "Failed to match compatible string\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ is_2712 = !!of_id->data;
|
||||
+
|
||||
pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL);
|
||||
if (!pm)
|
||||
return -ENOMEM;
|
||||
@@ -97,21 +115,13 @@ static int bcm2835_pm_probe(struct platf
|
||||
* bcm2835-pm binding as the key for whether we can reference
|
||||
* the full PM register range and support power domains.
|
||||
*/
|
||||
- if (pm->asb)
|
||||
+ if (pm->asb || is_2712)
|
||||
return devm_mfd_add_devices(dev, -1, bcm2835_power_devs,
|
||||
ARRAY_SIZE(bcm2835_power_devs),
|
||||
NULL, 0, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static const struct of_device_id bcm2835_pm_of_match[] = {
|
||||
- { .compatible = "brcm,bcm2835-pm-wdt", },
|
||||
- { .compatible = "brcm,bcm2835-pm", },
|
||||
- { .compatible = "brcm,bcm2711-pm", },
|
||||
- {},
|
||||
-};
|
||||
-MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match);
|
||||
-
|
||||
static struct platform_driver bcm2835_pm_driver = {
|
||||
.probe = bcm2835_pm_probe,
|
||||
.driver = {
|
76
target/linux/bcm27xx/patches-6.1/950-0899-soc-bcm-bcm2835-power-Add-support-for-BCM2712.patch
Normal file
76
target/linux/bcm27xx/patches-6.1/950-0899-soc-bcm-bcm2835-power-Add-support-for-BCM2712.patch
Normal file
@ -0,0 +1,76 @@
|
||||
From 9cf85a95eeb239a079a3485bd1d0447431bdc7f1 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Wed, 8 Mar 2023 14:42:48 +0000
|
||||
Subject: [PATCH] soc: bcm: bcm2835-power: Add support for BCM2712
|
||||
|
||||
BCM2712 has a PM block but neither ASB nor RPIVID_ASB. Use the absence
|
||||
of the "asb" register range to indicate BCM2712 and its different PM
|
||||
register range.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/soc/bcm/bcm2835-power.c | 29 +++++++++++++++++++----------
|
||||
1 file changed, 19 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/soc/bcm/bcm2835-power.c
|
||||
+++ b/drivers/soc/bcm/bcm2835-power.c
|
||||
@@ -79,6 +79,7 @@
|
||||
#define PM_IMAGE 0x108
|
||||
#define PM_GRAFX 0x10c
|
||||
#define PM_PROC 0x110
|
||||
+#define PM_GRAFX_2712 0x304
|
||||
#define PM_ENAB BIT(12)
|
||||
#define PM_ISPRSTN BIT(8)
|
||||
#define PM_H264RSTN BIT(7)
|
||||
@@ -381,6 +382,9 @@ static int bcm2835_power_pd_power_on(str
|
||||
return bcm2835_power_power_on(pd, PM_GRAFX);
|
||||
|
||||
case BCM2835_POWER_DOMAIN_GRAFX_V3D:
|
||||
+ if (!power->asb)
|
||||
+ return bcm2835_asb_power_on(pd, PM_GRAFX_2712,
|
||||
+ 0, 0, PM_V3DRSTN);
|
||||
return bcm2835_asb_power_on(pd, PM_GRAFX,
|
||||
ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
|
||||
PM_V3DRSTN);
|
||||
@@ -447,6 +451,9 @@ static int bcm2835_power_pd_power_off(st
|
||||
return bcm2835_power_power_off(pd, PM_GRAFX);
|
||||
|
||||
case BCM2835_POWER_DOMAIN_GRAFX_V3D:
|
||||
+ if (!power->asb)
|
||||
+ return bcm2835_asb_power_off(pd, PM_GRAFX_2712,
|
||||
+ 0, 0, PM_V3DRSTN);
|
||||
return bcm2835_asb_power_off(pd, PM_GRAFX,
|
||||
ASB_V3D_M_CTRL, ASB_V3D_S_CTRL,
|
||||
PM_V3DRSTN);
|
||||
@@ -642,19 +649,21 @@ static int bcm2835_power_probe(struct pl
|
||||
power->asb = pm->asb;
|
||||
power->rpivid_asb = pm->rpivid_asb;
|
||||
|
||||
- id = readl(power->asb + ASB_AXI_BRDG_ID);
|
||||
- if (id != BCM2835_BRDG_ID /* "BRDG" */) {
|
||||
- dev_err(dev, "ASB register ID returned 0x%08x\n", id);
|
||||
- return -ENODEV;
|
||||
- }
|
||||
-
|
||||
- if (power->rpivid_asb) {
|
||||
- id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID);
|
||||
+ if (power->asb) {
|
||||
+ id = readl(power->asb + ASB_AXI_BRDG_ID);
|
||||
if (id != BCM2835_BRDG_ID /* "BRDG" */) {
|
||||
- dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n",
|
||||
- id);
|
||||
+ dev_err(dev, "ASB register ID returned 0x%08x\n", id);
|
||||
return -ENODEV;
|
||||
}
|
||||
+
|
||||
+ if (power->rpivid_asb) {
|
||||
+ id = readl(power->rpivid_asb + ASB_AXI_BRDG_ID);
|
||||
+ if (id != BCM2835_BRDG_ID /* "BRDG" */) {
|
||||
+ dev_err(dev, "RPiVid ASB register ID returned 0x%08x\n",
|
||||
+ id);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
power->pd_xlate.domains = devm_kcalloc(dev,
|
150
target/linux/bcm27xx/patches-6.1/950-0900-drivers-spi-Fix-spi-gpio-to-correctly-implement-sck-.patch
Normal file
150
target/linux/bcm27xx/patches-6.1/950-0900-drivers-spi-Fix-spi-gpio-to-correctly-implement-sck-.patch
Normal file
@ -0,0 +1,150 @@
|
||||
From 380c336af070edf85826abbb0057bf92a03ec466 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||
Date: Wed, 1 Mar 2023 17:57:11 +0000
|
||||
Subject: [PATCH] drivers: spi: Fix spi-gpio to correctly implement
|
||||
sck-idle-input
|
||||
|
||||
Formerly, if configured using DT, CS GPIOs were driven from spi.c
|
||||
and it was possible for CS to be asserted (low) *before* starting
|
||||
to drive SCK. CS GPIOs have been brought under control of this
|
||||
driver in both ACPI and DT cases, with a fixup for GPIO polarity.
|
||||
|
||||
Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||
---
|
||||
drivers/spi/spi-gpio.c | 74 +++++++++++++++++++++++++++++-------------
|
||||
1 file changed, 51 insertions(+), 23 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-gpio.c
|
||||
+++ b/drivers/spi/spi-gpio.c
|
||||
@@ -37,6 +37,7 @@ struct spi_gpio {
|
||||
struct gpio_desc *mosi;
|
||||
bool sck_idle_input;
|
||||
struct gpio_desc **cs_gpios;
|
||||
+ bool cs_dont_invert;
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
@@ -233,12 +234,18 @@ static void spi_gpio_chipselect(struct s
|
||||
gpiod_set_value_cansleep(spi_gpio->sck, spi->mode & SPI_CPOL);
|
||||
}
|
||||
|
||||
- /* Drive chip select line, if we have one */
|
||||
+ /*
|
||||
+ * Drive chip select line, if we have one.
|
||||
+ * SPI chip selects are normally active-low, but when
|
||||
+ * cs_dont_invert is set, we assume their polarity is
|
||||
+ * controlled by the GPIO, and write '1' to assert.
|
||||
+ */
|
||||
if (spi_gpio->cs_gpios) {
|
||||
struct gpio_desc *cs = spi_gpio->cs_gpios[spi->chip_select];
|
||||
+ int val = ((spi->mode & SPI_CS_HIGH) || spi_gpio->cs_dont_invert) ?
|
||||
+ is_active : !is_active;
|
||||
|
||||
- /* SPI chip selects are normally active-low */
|
||||
- gpiod_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
|
||||
+ gpiod_set_value_cansleep(cs, val);
|
||||
}
|
||||
|
||||
if (spi_gpio->sck_idle_input && !is_active)
|
||||
@@ -254,12 +261,14 @@ static int spi_gpio_setup(struct spi_dev
|
||||
/*
|
||||
* The CS GPIOs have already been
|
||||
* initialized from the descriptor lookup.
|
||||
+ * Here we set them to the non-asserted state.
|
||||
*/
|
||||
if (spi_gpio->cs_gpios) {
|
||||
cs = spi_gpio->cs_gpios[spi->chip_select];
|
||||
if (!spi->controller_state && cs)
|
||||
status = gpiod_direction_output(cs,
|
||||
- !(spi->mode & SPI_CS_HIGH));
|
||||
+ !((spi->mode & SPI_CS_HIGH) ||
|
||||
+ spi_gpio->cs_dont_invert));
|
||||
}
|
||||
|
||||
if (!status)
|
||||
@@ -336,6 +345,38 @@ static int spi_gpio_request(struct devic
|
||||
return PTR_ERR_OR_ZERO(spi_gpio->sck);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * In order to implement "sck-idle-input" (which requires SCK
|
||||
+ * direction and CS level to be switched in a particular order),
|
||||
+ * we need to control GPIO chip selects from within this driver.
|
||||
+ */
|
||||
+
|
||||
+static int spi_gpio_probe_get_cs_gpios(struct device *dev,
|
||||
+ struct spi_master *master,
|
||||
+ bool gpio_defines_polarity)
|
||||
+{
|
||||
+ int i;
|
||||
+ struct spi_gpio *spi_gpio = spi_master_get_devdata(master);
|
||||
+
|
||||
+ spi_gpio->cs_dont_invert = gpio_defines_polarity;
|
||||
+ spi_gpio->cs_gpios = devm_kcalloc(dev, master->num_chipselect,
|
||||
+ sizeof(*spi_gpio->cs_gpios),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!spi_gpio->cs_gpios)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ for (i = 0; i < master->num_chipselect; i++) {
|
||||
+ spi_gpio->cs_gpios[i] =
|
||||
+ devm_gpiod_get_index(dev, "cs", i,
|
||||
+ gpio_defines_polarity ?
|
||||
+ GPIOD_OUT_LOW : GPIOD_OUT_HIGH);
|
||||
+ if (IS_ERR(spi_gpio->cs_gpios[i]))
|
||||
+ return PTR_ERR(spi_gpio->cs_gpios[i]);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id spi_gpio_dt_ids[] = {
|
||||
{ .compatible = "spi-gpio" },
|
||||
@@ -346,10 +387,12 @@ MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids)
|
||||
static int spi_gpio_probe_dt(struct platform_device *pdev,
|
||||
struct spi_master *master)
|
||||
{
|
||||
- master->dev.of_node = pdev->dev.of_node;
|
||||
- master->use_gpio_descriptors = true;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
|
||||
- return 0;
|
||||
+ master->dev.of_node = dev->of_node;
|
||||
+ master->num_chipselect = gpiod_count(dev, "cs");
|
||||
+
|
||||
+ return spi_gpio_probe_get_cs_gpios(dev, master, true);
|
||||
}
|
||||
#else
|
||||
static inline int spi_gpio_probe_dt(struct platform_device *pdev,
|
||||
@@ -364,8 +407,6 @@ static int spi_gpio_probe_pdata(struct p
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spi_gpio_platform_data *pdata = dev_get_platdata(dev);
|
||||
- struct spi_gpio *spi_gpio = spi_master_get_devdata(master);
|
||||
- int i;
|
||||
|
||||
#ifdef GENERIC_BITBANG
|
||||
if (!pdata || !pdata->num_chipselect)
|
||||
@@ -377,20 +418,7 @@ static int spi_gpio_probe_pdata(struct p
|
||||
*/
|
||||
master->num_chipselect = pdata->num_chipselect ?: 1;
|
||||
|
||||
- spi_gpio->cs_gpios = devm_kcalloc(dev, master->num_chipselect,
|
||||
- sizeof(*spi_gpio->cs_gpios),
|
||||
- GFP_KERNEL);
|
||||
- if (!spi_gpio->cs_gpios)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- for (i = 0; i < master->num_chipselect; i++) {
|
||||
- spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs", i,
|
||||
- GPIOD_OUT_HIGH);
|
||||
- if (IS_ERR(spi_gpio->cs_gpios[i]))
|
||||
- return PTR_ERR(spi_gpio->cs_gpios[i]);
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
+ return spi_gpio_probe_get_cs_gpios(dev, master, false);
|
||||
}
|
||||
|
||||
static int spi_gpio_probe(struct platform_device *pdev)
|
55
target/linux/bcm27xx/patches-6.1/950-0901-spi-spi-gpio-Implement-spidelay-when-requested-bit-r.patch
Normal file
55
target/linux/bcm27xx/patches-6.1/950-0901-spi-spi-gpio-Implement-spidelay-when-requested-bit-r.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From 586f87307e75552292cfc6c76b81cd38d5ec31e2 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||
Date: Mon, 4 Sep 2023 10:57:47 +0100
|
||||
Subject: [PATCH] spi: spi-gpio: Implement spidelay when requested bit rate <=
|
||||
1 Mbps
|
||||
|
||||
Formerly the delay was omitted as bit-banged SPI seldom achieved
|
||||
even one Mbit/s; but some modern platforms can run faster, and
|
||||
some SPI devices may need to be clocked slower.
|
||||
|
||||
Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||||
---
|
||||
drivers/spi/spi-gpio.c | 18 ++++++++++++------
|
||||
1 file changed, 12 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-gpio.c
|
||||
+++ b/drivers/spi/spi-gpio.c
|
||||
@@ -11,12 +11,12 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
+#include <linux/delay.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi_bitbang.h>
|
||||
#include <linux/spi/spi_gpio.h>
|
||||
|
||||
-
|
||||
/*
|
||||
* This bitbanging SPI master driver should help make systems usable
|
||||
* when a native hardware SPI engine is not available, perhaps because
|
||||
@@ -111,12 +111,18 @@ static inline int getmiso(const struct s
|
||||
}
|
||||
|
||||
/*
|
||||
- * NOTE: this clocks "as fast as we can". It "should" be a function of the
|
||||
- * requested device clock. Software overhead means we usually have trouble
|
||||
- * reaching even one Mbit/sec (except when we can inline bitops), so for now
|
||||
- * we'll just assume we never need additional per-bit slowdowns.
|
||||
+ * Generic bit-banged GPIO SPI might free-run at something in the range
|
||||
+ * 1Mbps ~ 10Mbps (depending on the platform), and some SPI devices may
|
||||
+ * need to be clocked at a lower rate. ndelay() is often implemented by
|
||||
+ * udelay() with rounding up, so do the delay only for nsecs >= 500
|
||||
+ * (<= 1Mbps). The conditional test adds a small overhead.
|
||||
*/
|
||||
-#define spidelay(nsecs) do {} while (0)
|
||||
+
|
||||
+static inline void spidelay(unsigned long nsecs)
|
||||
+{
|
||||
+ if (nsecs >= 500)
|
||||
+ ndelay(nsecs);
|
||||
+}
|
||||
|
||||
#include "spi-bitbang-txrx.h"
|
||||
|
672
target/linux/bcm27xx/patches-6.1/950-0902-drm-v3d-fix-up-register-addresses-for-V3D-7.x.patch
Normal file
672
target/linux/bcm27xx/patches-6.1/950-0902-drm-v3d-fix-up-register-addresses-for-V3D-7.x.patch
Normal file
@ -0,0 +1,672 @@
|
||||
From 3f949caeef21269afc67dd62ae9826204f215934 Mon Sep 17 00:00:00 2001
|
||||
From: Iago Toral Quiroga <itoral@igalia.com>
|
||||
Date: Thu, 2 Mar 2023 11:49:46 +0100
|
||||
Subject: [PATCH] drm/v3d: fix up register addresses for V3D 7.x
|
||||
|
||||
v2: fix kernel panic with debug-fs interface to list registers
|
||||
---
|
||||
drivers/gpu/drm/v3d/v3d_debugfs.c | 177 +++++++++++++++++-------------
|
||||
drivers/gpu/drm/v3d/v3d_gem.c | 3 +
|
||||
drivers/gpu/drm/v3d/v3d_irq.c | 47 ++++----
|
||||
drivers/gpu/drm/v3d/v3d_regs.h | 51 ++++++++-
|
||||
drivers/gpu/drm/v3d/v3d_sched.c | 41 ++++---
|
||||
5 files changed, 204 insertions(+), 115 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
|
||||
+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
|
||||
@@ -13,69 +13,83 @@
|
||||
#include "v3d_drv.h"
|
||||
#include "v3d_regs.h"
|
||||
|
||||
-#define REGDEF(reg) { reg, #reg }
|
||||
+#define REGDEF(min_ver, max_ver, reg) { min_ver, max_ver, reg, #reg }
|
||||
struct v3d_reg_def {
|
||||
+ u32 min_ver;
|
||||
+ u32 max_ver;
|
||||
u32 reg;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct v3d_reg_def v3d_hub_reg_defs[] = {
|
||||
- REGDEF(V3D_HUB_AXICFG),
|
||||
- REGDEF(V3D_HUB_UIFCFG),
|
||||
- REGDEF(V3D_HUB_IDENT0),
|
||||
- REGDEF(V3D_HUB_IDENT1),
|
||||
- REGDEF(V3D_HUB_IDENT2),
|
||||
- REGDEF(V3D_HUB_IDENT3),
|
||||
- REGDEF(V3D_HUB_INT_STS),
|
||||
- REGDEF(V3D_HUB_INT_MSK_STS),
|
||||
-
|
||||
- REGDEF(V3D_MMU_CTL),
|
||||
- REGDEF(V3D_MMU_VIO_ADDR),
|
||||
- REGDEF(V3D_MMU_VIO_ID),
|
||||
- REGDEF(V3D_MMU_DEBUG_INFO),
|
||||
+ REGDEF(33, 42, V3D_HUB_AXICFG),
|
||||
+ REGDEF(33, 71, V3D_HUB_UIFCFG),
|
||||
+ REGDEF(33, 71, V3D_HUB_IDENT0),
|
||||
+ REGDEF(33, 71, V3D_HUB_IDENT1),
|
||||
+ REGDEF(33, 71, V3D_HUB_IDENT2),
|
||||
+ REGDEF(33, 71, V3D_HUB_IDENT3),
|
||||
+ REGDEF(33, 71, V3D_HUB_INT_STS),
|
||||
+ REGDEF(33, 71, V3D_HUB_INT_MSK_STS),
|
||||
+
|
||||
+ REGDEF(33, 71, V3D_MMU_CTL),
|
||||
+ REGDEF(33, 71, V3D_MMU_VIO_ADDR),
|
||||
+ REGDEF(33, 71, V3D_MMU_VIO_ID),
|
||||
+ REGDEF(33, 71, V3D_MMU_DEBUG_INFO),
|
||||
+
|
||||
+ REGDEF(71, 71, V3D_V7_GMP_STATUS),
|
||||
+ REGDEF(71, 71, V3D_V7_GMP_CFG),
|
||||
+ REGDEF(71, 71, V3D_V7_GMP_VIO_ADDR),
|
||||
};
|
||||
|
||||
static const struct v3d_reg_def v3d_gca_reg_defs[] = {
|
||||
- REGDEF(V3D_GCA_SAFE_SHUTDOWN),
|
||||
- REGDEF(V3D_GCA_SAFE_SHUTDOWN_ACK),
|
||||
+ REGDEF(33, 33, V3D_GCA_SAFE_SHUTDOWN),
|
||||
+ REGDEF(33, 33, V3D_GCA_SAFE_SHUTDOWN_ACK),
|
||||
};
|
||||
|
||||
static const struct v3d_reg_def v3d_core_reg_defs[] = {
|
||||
- REGDEF(V3D_CTL_IDENT0),
|
||||
- REGDEF(V3D_CTL_IDENT1),
|
||||
- REGDEF(V3D_CTL_IDENT2),
|
||||
- REGDEF(V3D_CTL_MISCCFG),
|
||||
- REGDEF(V3D_CTL_INT_STS),
|
||||
- REGDEF(V3D_CTL_INT_MSK_STS),
|
||||
- REGDEF(V3D_CLE_CT0CS),
|
||||
- REGDEF(V3D_CLE_CT0CA),
|
||||
- REGDEF(V3D_CLE_CT0EA),
|
||||
- REGDEF(V3D_CLE_CT1CS),
|
||||
- REGDEF(V3D_CLE_CT1CA),
|
||||
- REGDEF(V3D_CLE_CT1EA),
|
||||
-
|
||||
- REGDEF(V3D_PTB_BPCA),
|
||||
- REGDEF(V3D_PTB_BPCS),
|
||||
-
|
||||
- REGDEF(V3D_GMP_STATUS),
|
||||
- REGDEF(V3D_GMP_CFG),
|
||||
- REGDEF(V3D_GMP_VIO_ADDR),
|
||||
-
|
||||
- REGDEF(V3D_ERR_FDBGO),
|
||||
- REGDEF(V3D_ERR_FDBGB),
|
||||
- REGDEF(V3D_ERR_FDBGS),
|
||||
- REGDEF(V3D_ERR_STAT),
|
||||
+ REGDEF(33, 71, V3D_CTL_IDENT0),
|
||||
+ REGDEF(33, 71, V3D_CTL_IDENT1),
|
||||
+ REGDEF(33, 71, V3D_CTL_IDENT2),
|
||||
+ REGDEF(33, 71, V3D_CTL_MISCCFG),
|
||||
+ REGDEF(33, 71, V3D_CTL_INT_STS),
|
||||
+ REGDEF(33, 71, V3D_CTL_INT_MSK_STS),
|
||||
+ REGDEF(33, 71, V3D_CLE_CT0CS),
|
||||
+ REGDEF(33, 71, V3D_CLE_CT0CA),
|
||||
+ REGDEF(33, 71, V3D_CLE_CT0EA),
|
||||
+ REGDEF(33, 71, V3D_CLE_CT1CS),
|
||||
+ REGDEF(33, 71, V3D_CLE_CT1CA),
|
||||
+ REGDEF(33, 71, V3D_CLE_CT1EA),
|
||||
+
|
||||
+ REGDEF(33, 71, V3D_PTB_BPCA),
|
||||
+ REGDEF(33, 71, V3D_PTB_BPCS),
|
||||
+
|
||||
+ REGDEF(33, 41, V3D_GMP_STATUS),
|
||||
+ REGDEF(33, 41, V3D_GMP_CFG),
|
||||
+ REGDEF(33, 41, V3D_GMP_VIO_ADDR),
|
||||
+
|
||||
+ REGDEF(33, 71, V3D_ERR_FDBGO),
|
||||
+ REGDEF(33, 71, V3D_ERR_FDBGB),
|
||||
+ REGDEF(33, 71, V3D_ERR_FDBGS),
|
||||
+ REGDEF(33, 71, V3D_ERR_STAT),
|
||||
};
|
||||
|
||||
static const struct v3d_reg_def v3d_csd_reg_defs[] = {
|
||||
- REGDEF(V3D_CSD_STATUS),
|
||||
- REGDEF(V3D_CSD_CURRENT_CFG0),
|
||||
- REGDEF(V3D_CSD_CURRENT_CFG1),
|
||||
- REGDEF(V3D_CSD_CURRENT_CFG2),
|
||||
- REGDEF(V3D_CSD_CURRENT_CFG3),
|
||||
- REGDEF(V3D_CSD_CURRENT_CFG4),
|
||||
- REGDEF(V3D_CSD_CURRENT_CFG5),
|
||||
- REGDEF(V3D_CSD_CURRENT_CFG6),
|
||||
+ REGDEF(41, 71, V3D_CSD_STATUS),
|
||||
+ REGDEF(41, 41, V3D_CSD_CURRENT_CFG0),
|
||||
+ REGDEF(41, 41, V3D_CSD_CURRENT_CFG1),
|
||||
+ REGDEF(41, 41, V3D_CSD_CURRENT_CFG2),
|
||||
+ REGDEF(41, 41, V3D_CSD_CURRENT_CFG3),
|
||||
+ REGDEF(41, 41, V3D_CSD_CURRENT_CFG4),
|
||||
+ REGDEF(41, 41, V3D_CSD_CURRENT_CFG5),
|
||||
+ REGDEF(41, 41, V3D_CSD_CURRENT_CFG6),
|
||||
+ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG0),
|
||||
+ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG1),
|
||||
+ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG2),
|
||||
+ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG3),
|
||||
+ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG4),
|
||||
+ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG5),
|
||||
+ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG6),
|
||||
+ REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG7),
|
||||
};
|
||||
|
||||
static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused)
|
||||
@@ -86,38 +100,41 @@ static int v3d_v3d_debugfs_regs(struct s
|
||||
int i, core;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(v3d_hub_reg_defs); i++) {
|
||||
- seq_printf(m, "%s (0x%04x): 0x%08x\n",
|
||||
- v3d_hub_reg_defs[i].name, v3d_hub_reg_defs[i].reg,
|
||||
- V3D_READ(v3d_hub_reg_defs[i].reg));
|
||||
+ const struct v3d_reg_def *def = &v3d_hub_reg_defs[i];
|
||||
+
|
||||
+ if (v3d->ver >= def->min_ver && v3d->ver <= def->max_ver) {
|
||||
+ seq_printf(m, "%s (0x%04x): 0x%08x\n",
|
||||
+ def->name, def->reg, V3D_READ(def->reg));
|
||||
+ }
|
||||
}
|
||||
|
||||
- if (v3d->ver < 41) {
|
||||
- for (i = 0; i < ARRAY_SIZE(v3d_gca_reg_defs); i++) {
|
||||
+ for (i = 0; i < ARRAY_SIZE(v3d_gca_reg_defs); i++) {
|
||||
+ const struct v3d_reg_def *def = &v3d_gca_reg_defs[i];
|
||||
+
|
||||
+ if (v3d->ver >= def->min_ver && v3d->ver <= def->max_ver) {
|
||||
seq_printf(m, "%s (0x%04x): 0x%08x\n",
|
||||
- v3d_gca_reg_defs[i].name,
|
||||
- v3d_gca_reg_defs[i].reg,
|
||||
- V3D_GCA_READ(v3d_gca_reg_defs[i].reg));
|
||||
+ def->name, def->reg, V3D_GCA_READ(def->reg));
|
||||
}
|
||||
}
|
||||
|
||||
for (core = 0; core < v3d->cores; core++) {
|
||||
for (i = 0; i < ARRAY_SIZE(v3d_core_reg_defs); i++) {
|
||||
- seq_printf(m, "core %d %s (0x%04x): 0x%08x\n",
|
||||
- core,
|
||||
- v3d_core_reg_defs[i].name,
|
||||
- v3d_core_reg_defs[i].reg,
|
||||
- V3D_CORE_READ(core,
|
||||
- v3d_core_reg_defs[i].reg));
|
||||
+ const struct v3d_reg_def *def = &v3d_core_reg_defs[i];
|
||||
+
|
||||
+ if (v3d->ver >= def->min_ver && v3d->ver <= def->max_ver) {
|
||||
+ seq_printf(m, "core %d %s (0x%04x): 0x%08x\n",
|
||||
+ core, def->name, def->reg,
|
||||
+ V3D_CORE_READ(core, def->reg));
|
||||
+ }
|
||||
}
|
||||
|
||||
- if (v3d_has_csd(v3d)) {
|
||||
- for (i = 0; i < ARRAY_SIZE(v3d_csd_reg_defs); i++) {
|
||||
+ for (i = 0; i < ARRAY_SIZE(v3d_csd_reg_defs); i++) {
|
||||
+ const struct v3d_reg_def *def = &v3d_csd_reg_defs[i];
|
||||
+
|
||||
+ if (v3d->ver >= def->min_ver && v3d->ver <= def->max_ver) {
|
||||
seq_printf(m, "core %d %s (0x%04x): 0x%08x\n",
|
||||
- core,
|
||||
- v3d_csd_reg_defs[i].name,
|
||||
- v3d_csd_reg_defs[i].reg,
|
||||
- V3D_CORE_READ(core,
|
||||
- v3d_csd_reg_defs[i].reg));
|
||||
+ core, def->name, def->reg,
|
||||
+ V3D_CORE_READ(core, def->reg));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,8 +165,10 @@ static int v3d_v3d_debugfs_ident(struct
|
||||
str_yes_no(ident2 & V3D_HUB_IDENT2_WITH_MMU));
|
||||
seq_printf(m, "TFU: %s\n",
|
||||
str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TFU));
|
||||
- seq_printf(m, "TSY: %s\n",
|
||||
- str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TSY));
|
||||
+ if (v3d->ver <= 42) {
|
||||
+ seq_printf(m, "TSY: %s\n",
|
||||
+ str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TSY));
|
||||
+ }
|
||||
seq_printf(m, "MSO: %s\n",
|
||||
str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_MSO));
|
||||
seq_printf(m, "L3C: %s (%dkb)\n",
|
||||
@@ -178,10 +197,14 @@ static int v3d_v3d_debugfs_ident(struct
|
||||
seq_printf(m, " QPUs: %d\n", nslc * qups);
|
||||
seq_printf(m, " Semaphores: %d\n",
|
||||
V3D_GET_FIELD(ident1, V3D_IDENT1_NSEM));
|
||||
- seq_printf(m, " BCG int: %d\n",
|
||||
- (ident2 & V3D_IDENT2_BCG_INT) != 0);
|
||||
- seq_printf(m, " Override TMU: %d\n",
|
||||
- (misccfg & V3D_MISCCFG_OVRTMUOUT) != 0);
|
||||
+ if (v3d->ver <= 42) {
|
||||
+ seq_printf(m, " BCG int: %d\n",
|
||||
+ (ident2 & V3D_IDENT2_BCG_INT) != 0);
|
||||
+ }
|
||||
+ if (v3d->ver < 40) {
|
||||
+ seq_printf(m, " Override TMU: %d\n",
|
||||
+ (misccfg & V3D_MISCCFG_OVRTMUOUT) != 0);
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -289,8 +312,10 @@ static int v3d_measure_clock(struct seq_
|
||||
int measure_ms = 1000;
|
||||
|
||||
if (v3d->ver >= 40) {
|
||||
+ int cycle_count_reg = v3d->ver < 71 ?
|
||||
+ V3D_PCTR_CYCLE_COUNT : V3D_V7_PCTR_CYCLE_COUNT;
|
||||
V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
|
||||
- V3D_SET_FIELD(V3D_PCTR_CYCLE_COUNT,
|
||||
+ V3D_SET_FIELD(cycle_count_reg,
|
||||
V3D_PCTR_S0));
|
||||
V3D_CORE_WRITE(core, V3D_V4_PCTR_0_CLR, 1);
|
||||
V3D_CORE_WRITE(core, V3D_V4_PCTR_0_EN, 1);
|
||||
--- a/drivers/gpu/drm/v3d/v3d_gem.c
|
||||
+++ b/drivers/gpu/drm/v3d/v3d_gem.c
|
||||
@@ -88,6 +88,9 @@ v3d_init_hw_state(struct v3d_dev *v3d)
|
||||
static void
|
||||
v3d_idle_axi(struct v3d_dev *v3d, int core)
|
||||
{
|
||||
+ if (v3d->ver >= 71)
|
||||
+ return;
|
||||
+
|
||||
V3D_CORE_WRITE(core, V3D_GMP_CFG, V3D_GMP_CFG_STOP_REQ);
|
||||
|
||||
if (wait_for((V3D_CORE_READ(core, V3D_GMP_STATUS) &
|
||||
--- a/drivers/gpu/drm/v3d/v3d_irq.c
|
||||
+++ b/drivers/gpu/drm/v3d/v3d_irq.c
|
||||
@@ -20,16 +20,17 @@
|
||||
#include "v3d_regs.h"
|
||||
#include "v3d_trace.h"
|
||||
|
||||
-#define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM | \
|
||||
- V3D_INT_FLDONE | \
|
||||
- V3D_INT_FRDONE | \
|
||||
- V3D_INT_CSDDONE | \
|
||||
- V3D_INT_GMPV))
|
||||
-
|
||||
-#define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV | \
|
||||
- V3D_HUB_INT_MMU_PTI | \
|
||||
- V3D_HUB_INT_MMU_CAP | \
|
||||
- V3D_HUB_INT_TFUC))
|
||||
+#define V3D_CORE_IRQS(ver) ((u32)(V3D_INT_OUTOMEM | \
|
||||
+ V3D_INT_FLDONE | \
|
||||
+ V3D_INT_FRDONE | \
|
||||
+ (ver < 71 ? V3D_INT_CSDDONE : V3D_V7_INT_CSDDONE) | \
|
||||
+ (ver < 71 ? V3D_INT_GMPV : 0)))
|
||||
+
|
||||
+#define V3D_HUB_IRQS(ver) ((u32)(V3D_HUB_INT_MMU_WRV | \
|
||||
+ V3D_HUB_INT_MMU_PTI | \
|
||||
+ V3D_HUB_INT_MMU_CAP | \
|
||||
+ V3D_HUB_INT_TFUC | \
|
||||
+ (ver >= 71 ? V3D_V7_HUB_INT_GMPV : 0)))
|
||||
|
||||
static irqreturn_t
|
||||
v3d_hub_irq(int irq, void *arg);
|
||||
@@ -118,7 +119,8 @@ v3d_irq(int irq, void *arg)
|
||||
status = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
- if (intsts & V3D_INT_CSDDONE) {
|
||||
+ if ((v3d->ver < 71 && (intsts & V3D_INT_CSDDONE)) ||
|
||||
+ (v3d->ver >= 71 && (intsts & V3D_V7_INT_CSDDONE))) {
|
||||
struct v3d_fence *fence =
|
||||
to_v3d_fence(v3d->csd_job->base.irq_fence);
|
||||
v3d->gpu_queue_stats[V3D_CSD].last_exec_end = local_clock();
|
||||
@@ -131,7 +133,7 @@ v3d_irq(int irq, void *arg)
|
||||
/* We shouldn't be triggering these if we have GMP in
|
||||
* always-allowed mode.
|
||||
*/
|
||||
- if (intsts & V3D_INT_GMPV)
|
||||
+ if (v3d->ver < 71 && (intsts & V3D_INT_GMPV))
|
||||
dev_err(v3d->drm.dev, "GMP violation\n");
|
||||
|
||||
/* V3D 4.2 wires the hub and core IRQs together, so if we &
|
||||
@@ -205,6 +207,11 @@ v3d_hub_irq(int irq, void *arg)
|
||||
status = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
+ if (v3d->ver >= 71 && intsts & V3D_V7_HUB_INT_GMPV) {
|
||||
+ dev_err(v3d->drm.dev, "GMP Violation\n");
|
||||
+ status = IRQ_HANDLED;
|
||||
+ }
|
||||
+
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -219,8 +226,8 @@ v3d_irq_init(struct v3d_dev *v3d)
|
||||
* for us.
|
||||
*/
|
||||
for (core = 0; core < v3d->cores; core++)
|
||||
- V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS);
|
||||
- V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS);
|
||||
+ V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS(v3d->ver));
|
||||
+ V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS(v3d->ver));
|
||||
|
||||
irq1 = platform_get_irq_optional(v3d_to_pdev(v3d), 1);
|
||||
if (irq1 == -EPROBE_DEFER)
|
||||
@@ -264,12 +271,12 @@ v3d_irq_enable(struct v3d_dev *v3d)
|
||||
|
||||
/* Enable our set of interrupts, masking out any others. */
|
||||
for (core = 0; core < v3d->cores; core++) {
|
||||
- V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_SET, ~V3D_CORE_IRQS);
|
||||
- V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_CLR, V3D_CORE_IRQS);
|
||||
+ V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_SET, ~V3D_CORE_IRQS(v3d->ver));
|
||||
+ V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_CLR, V3D_CORE_IRQS(v3d->ver));
|
||||
}
|
||||
|
||||
- V3D_WRITE(V3D_HUB_INT_MSK_SET, ~V3D_HUB_IRQS);
|
||||
- V3D_WRITE(V3D_HUB_INT_MSK_CLR, V3D_HUB_IRQS);
|
||||
+ V3D_WRITE(V3D_HUB_INT_MSK_SET, ~V3D_HUB_IRQS(v3d->ver));
|
||||
+ V3D_WRITE(V3D_HUB_INT_MSK_CLR, V3D_HUB_IRQS(v3d->ver));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -284,8 +291,8 @@ v3d_irq_disable(struct v3d_dev *v3d)
|
||||
|
||||
/* Clear any pending interrupts we might have left. */
|
||||
for (core = 0; core < v3d->cores; core++)
|
||||
- V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS);
|
||||
- V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS);
|
||||
+ V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS(v3d->ver));
|
||||
+ V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS(v3d->ver));
|
||||
|
||||
cancel_work_sync(&v3d->overflow_mem_work);
|
||||
}
|
||||
--- a/drivers/gpu/drm/v3d/v3d_regs.h
|
||||
+++ b/drivers/gpu/drm/v3d/v3d_regs.h
|
||||
@@ -57,6 +57,7 @@
|
||||
#define V3D_HUB_INT_MSK_STS 0x0005c
|
||||
#define V3D_HUB_INT_MSK_SET 0x00060
|
||||
#define V3D_HUB_INT_MSK_CLR 0x00064
|
||||
+# define V3D_V7_HUB_INT_GMPV BIT(6)
|
||||
# define V3D_HUB_INT_MMU_WRV BIT(5)
|
||||
# define V3D_HUB_INT_MMU_PTI BIT(4)
|
||||
# define V3D_HUB_INT_MMU_CAP BIT(3)
|
||||
@@ -64,6 +65,7 @@
|
||||
# define V3D_HUB_INT_TFUC BIT(1)
|
||||
# define V3D_HUB_INT_TFUF BIT(0)
|
||||
|
||||
+/* GCA registers only exist in V3D < 41 */
|
||||
#define V3D_GCA_CACHE_CTRL 0x0000c
|
||||
# define V3D_GCA_CACHE_CTRL_FLUSH BIT(0)
|
||||
|
||||
@@ -87,6 +89,7 @@
|
||||
# define V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT BIT(0)
|
||||
|
||||
#define V3D_TFU_CS 0x00400
|
||||
+#define V3D_V7_TFU_CS 0x00700
|
||||
/* Stops current job, empties input fifo. */
|
||||
# define V3D_TFU_CS_TFURST BIT(31)
|
||||
# define V3D_TFU_CS_CVTCT_MASK V3D_MASK(23, 16)
|
||||
@@ -96,6 +99,7 @@
|
||||
# define V3D_TFU_CS_BUSY BIT(0)
|
||||
|
||||
#define V3D_TFU_SU 0x00404
|
||||
+#define V3D_V7_TFU_SU 0x00704
|
||||
/* Interrupt when FINTTHR input slots are free (0 = disabled) */
|
||||
# define V3D_TFU_SU_FINTTHR_MASK V3D_MASK(13, 8)
|
||||
# define V3D_TFU_SU_FINTTHR_SHIFT 8
|
||||
@@ -107,38 +111,53 @@
|
||||
# define V3D_TFU_SU_THROTTLE_SHIFT 0
|
||||
|
||||
#define V3D_TFU_ICFG 0x00408
|
||||
+#define V3D_V7_TFU_ICFG 0x00708
|
||||
/* Interrupt when the conversion is complete. */
|
||||
# define V3D_TFU_ICFG_IOC BIT(0)
|
||||
|
||||
/* Input Image Address */
|
||||
#define V3D_TFU_IIA 0x0040c
|
||||
+#define V3D_V7_TFU_IIA 0x0070c
|
||||
/* Input Chroma Address */
|
||||
#define V3D_TFU_ICA 0x00410
|
||||
+#define V3D_V7_TFU_ICA 0x00710
|
||||
/* Input Image Stride */
|
||||
#define V3D_TFU_IIS 0x00414
|
||||
+#define V3D_V7_TFU_IIS 0x00714
|
||||
/* Input Image U-Plane Address */
|
||||
#define V3D_TFU_IUA 0x00418
|
||||
+#define V3D_V7_TFU_IUA 0x00718
|
||||
+/* Image output config (VD 7.x only) */
|
||||
+#define V3D_V7_TFU_IOC 0x0071c
|
||||
/* Output Image Address */
|
||||
#define V3D_TFU_IOA 0x0041c
|
||||
+#define V3D_V7_TFU_IOA 0x00720
|
||||
/* Image Output Size */
|
||||
#define V3D_TFU_IOS 0x00420
|
||||
+#define V3D_V7_TFU_IOS 0x00724
|
||||
/* TFU YUV Coefficient 0 */
|
||||
#define V3D_TFU_COEF0 0x00424
|
||||
-/* Use these regs instead of the defaults. */
|
||||
+#define V3D_V7_TFU_COEF0 0x00728
|
||||
+/* Use these regs instead of the defaults (V3D 4.x only) */
|
||||
# define V3D_TFU_COEF0_USECOEF BIT(31)
|
||||
/* TFU YUV Coefficient 1 */
|
||||
#define V3D_TFU_COEF1 0x00428
|
||||
+#define V3D_V7_TFU_COEF1 0x0072c
|
||||
/* TFU YUV Coefficient 2 */
|
||||
#define V3D_TFU_COEF2 0x0042c
|
||||
+#define V3D_V7_TFU_COEF2 0x00730
|
||||
/* TFU YUV Coefficient 3 */
|
||||
#define V3D_TFU_COEF3 0x00430
|
||||
+#define V3D_V7_TFU_COEF3 0x00734
|
||||
|
||||
+/* V3D 4.x only */
|
||||
#define V3D_TFU_CRC 0x00434
|
||||
|
||||
/* Per-MMU registers. */
|
||||
|
||||
#define V3D_MMUC_CONTROL 0x01000
|
||||
# define V3D_MMUC_CONTROL_CLEAR BIT(3)
|
||||
+# define V3D_V7_MMUC_CONTROL_CLEAR BIT(11)
|
||||
# define V3D_MMUC_CONTROL_FLUSHING BIT(2)
|
||||
# define V3D_MMUC_CONTROL_FLUSH BIT(1)
|
||||
# define V3D_MMUC_CONTROL_ENABLE BIT(0)
|
||||
@@ -246,7 +265,6 @@
|
||||
|
||||
#define V3D_CTL_L2TCACTL 0x00030
|
||||
# define V3D_L2TCACTL_TMUWCF BIT(8)
|
||||
-# define V3D_L2TCACTL_L2T_NO_WM BIT(4)
|
||||
/* Invalidates cache lines. */
|
||||
# define V3D_L2TCACTL_FLM_FLUSH 0
|
||||
/* Removes cachelines without writing dirty lines back. */
|
||||
@@ -268,7 +286,9 @@
|
||||
# define V3D_INT_QPU_MASK V3D_MASK(27, 16)
|
||||
# define V3D_INT_QPU_SHIFT 16
|
||||
# define V3D_INT_CSDDONE BIT(7)
|
||||
+# define V3D_V7_INT_CSDDONE BIT(6)
|
||||
# define V3D_INT_PCTR BIT(6)
|
||||
+# define V3D_V7_INT_PCTR BIT(5)
|
||||
# define V3D_INT_GMPV BIT(5)
|
||||
# define V3D_INT_TRFB BIT(4)
|
||||
# define V3D_INT_SPILLUSE BIT(3)
|
||||
@@ -350,14 +370,19 @@
|
||||
#define V3D_V4_PCTR_0_SRC_X(x) (V3D_V4_PCTR_0_SRC_0_3 + \
|
||||
4 * (x))
|
||||
# define V3D_PCTR_S0_MASK V3D_MASK(6, 0)
|
||||
+# define V3D_V7_PCTR_S0_MASK V3D_MASK(7, 0)
|
||||
# define V3D_PCTR_S0_SHIFT 0
|
||||
# define V3D_PCTR_S1_MASK V3D_MASK(14, 8)
|
||||
+# define V3D_V7_PCTR_S1_MASK V3D_MASK(15, 8)
|
||||
# define V3D_PCTR_S1_SHIFT 8
|
||||
# define V3D_PCTR_S2_MASK V3D_MASK(22, 16)
|
||||
+# define V3D_V7_PCTR_S2_MASK V3D_MASK(23, 16)
|
||||
# define V3D_PCTR_S2_SHIFT 16
|
||||
# define V3D_PCTR_S3_MASK V3D_MASK(30, 24)
|
||||
+# define V3D_V7_PCTR_S3_MASK V3D_MASK(31, 24)
|
||||
# define V3D_PCTR_S3_SHIFT 24
|
||||
# define V3D_PCTR_CYCLE_COUNT 32
|
||||
+# define V3D_V7_PCTR_CYCLE_COUNT 0
|
||||
|
||||
/* Output values of the counters. */
|
||||
#define V3D_PCTR_0_PCTR0 0x00680
|
||||
@@ -365,6 +390,7 @@
|
||||
#define V3D_PCTR_0_PCTRX(x) (V3D_PCTR_0_PCTR0 + \
|
||||
4 * (x))
|
||||
#define V3D_GMP_STATUS 0x00800
|
||||
+#define V3D_V7_GMP_STATUS 0x00600
|
||||
# define V3D_GMP_STATUS_GMPRST BIT(31)
|
||||
# define V3D_GMP_STATUS_WR_COUNT_MASK V3D_MASK(30, 24)
|
||||
# define V3D_GMP_STATUS_WR_COUNT_SHIFT 24
|
||||
@@ -378,12 +404,14 @@
|
||||
# define V3D_GMP_STATUS_VIO BIT(0)
|
||||
|
||||
#define V3D_GMP_CFG 0x00804
|
||||
+#define V3D_V7_GMP_CFG 0x00604
|
||||
# define V3D_GMP_CFG_LBURSTEN BIT(3)
|
||||
# define V3D_GMP_CFG_PGCRSEN BIT()
|
||||
# define V3D_GMP_CFG_STOP_REQ BIT(1)
|
||||
# define V3D_GMP_CFG_PROT_ENABLE BIT(0)
|
||||
|
||||
#define V3D_GMP_VIO_ADDR 0x00808
|
||||
+#define V3D_V7_GMP_VIO_ADDR 0x00608
|
||||
#define V3D_GMP_VIO_TYPE 0x0080c
|
||||
#define V3D_GMP_TABLE_ADDR 0x00810
|
||||
#define V3D_GMP_CLEAR_LOAD 0x00814
|
||||
@@ -399,24 +427,28 @@
|
||||
# define V3D_CSD_STATUS_HAVE_QUEUED_DISPATCH BIT(0)
|
||||
|
||||
#define V3D_CSD_QUEUED_CFG0 0x00904
|
||||
+#define V3D_V7_CSD_QUEUED_CFG0 0x00930
|
||||
# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_MASK V3D_MASK(31, 16)
|
||||
# define V3D_CSD_QUEUED_CFG0_NUM_WGS_X_SHIFT 16
|
||||
# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_MASK V3D_MASK(15, 0)
|
||||
# define V3D_CSD_QUEUED_CFG0_WG_X_OFFSET_SHIFT 0
|
||||
|
||||
#define V3D_CSD_QUEUED_CFG1 0x00908
|
||||
+#define V3D_V7_CSD_QUEUED_CFG1 0x00934
|
||||
# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_MASK V3D_MASK(31, 16)
|
||||
# define V3D_CSD_QUEUED_CFG1_NUM_WGS_Y_SHIFT 16
|
||||
# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_MASK V3D_MASK(15, 0)
|
||||
# define V3D_CSD_QUEUED_CFG1_WG_Y_OFFSET_SHIFT 0
|
||||
|
||||
#define V3D_CSD_QUEUED_CFG2 0x0090c
|
||||
+#define V3D_V7_CSD_QUEUED_CFG2 0x00938
|
||||
# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_MASK V3D_MASK(31, 16)
|
||||
# define V3D_CSD_QUEUED_CFG2_NUM_WGS_Z_SHIFT 16
|
||||
# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_MASK V3D_MASK(15, 0)
|
||||
# define V3D_CSD_QUEUED_CFG2_WG_Z_OFFSET_SHIFT 0
|
||||
|
||||
#define V3D_CSD_QUEUED_CFG3 0x00910
|
||||
+#define V3D_V7_CSD_QUEUED_CFG3 0x0093c
|
||||
# define V3D_CSD_QUEUED_CFG3_OVERLAP_WITH_PREV BIT(26)
|
||||
# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_MASK V3D_MASK(25, 20)
|
||||
# define V3D_CSD_QUEUED_CFG3_MAX_SG_ID_SHIFT 20
|
||||
@@ -429,22 +461,36 @@
|
||||
|
||||
/* Number of batches, minus 1 */
|
||||
#define V3D_CSD_QUEUED_CFG4 0x00914
|
||||
+#define V3D_V7_CSD_QUEUED_CFG4 0x00940
|
||||
|
||||
/* Shader address, pnan, singleseg, threading, like a shader record. */
|
||||
#define V3D_CSD_QUEUED_CFG5 0x00918
|
||||
+#define V3D_V7_CSD_QUEUED_CFG5 0x00944
|
||||
|
||||
/* Uniforms address (4 byte aligned) */
|
||||
#define V3D_CSD_QUEUED_CFG6 0x0091c
|
||||
+#define V3D_V7_CSD_QUEUED_CFG6 0x00948
|
||||
+
|
||||
+#define V3D_V7_CSD_QUEUED_CFG7 0x0094c
|
||||
|
||||
#define V3D_CSD_CURRENT_CFG0 0x00920
|
||||
+#define V3D_V7_CSD_CURRENT_CFG0 0x00958
|
||||
#define V3D_CSD_CURRENT_CFG1 0x00924
|
||||
+#define V3D_V7_CSD_CURRENT_CFG1 0x0095c
|
||||
#define V3D_CSD_CURRENT_CFG2 0x00928
|
||||
+#define V3D_V7_CSD_CURRENT_CFG2 0x00960
|
||||
#define V3D_CSD_CURRENT_CFG3 0x0092c
|
||||
+#define V3D_V7_CSD_CURRENT_CFG3 0x00964
|
||||
#define V3D_CSD_CURRENT_CFG4 0x00930
|
||||
+#define V3D_V7_CSD_CURRENT_CFG4 0x00968
|
||||
#define V3D_CSD_CURRENT_CFG5 0x00934
|
||||
+#define V3D_V7_CSD_CURRENT_CFG5 0x0096c
|
||||
#define V3D_CSD_CURRENT_CFG6 0x00938
|
||||
+#define V3D_V7_CSD_CURRENT_CFG6 0x00970
|
||||
+#define V3D_V7_CSD_CURRENT_CFG7 0x00974
|
||||
|
||||
#define V3D_CSD_CURRENT_ID0 0x0093c
|
||||
+#define V3D_V7_CSD_CURRENT_ID0 0x00978
|
||||
# define V3D_CSD_CURRENT_ID0_WG_X_MASK V3D_MASK(31, 16)
|
||||
# define V3D_CSD_CURRENT_ID0_WG_X_SHIFT 16
|
||||
# define V3D_CSD_CURRENT_ID0_WG_IN_SG_MASK V3D_MASK(11, 8)
|
||||
@@ -453,6 +499,7 @@
|
||||
# define V3D_CSD_CURRENT_ID0_L_IDX_SHIFT 0
|
||||
|
||||
#define V3D_CSD_CURRENT_ID1 0x00940
|
||||
+#define V3D_V7_CSD_CURRENT_ID1 0x0097c
|
||||
# define V3D_CSD_CURRENT_ID0_WG_Z_MASK V3D_MASK(31, 16)
|
||||
# define V3D_CSD_CURRENT_ID0_WG_Z_SHIFT 16
|
||||
# define V3D_CSD_CURRENT_ID0_WG_Y_MASK V3D_MASK(15, 0)
|
||||
--- a/drivers/gpu/drm/v3d/v3d_sched.c
|
||||
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
|
||||
@@ -282,6 +282,8 @@ static struct dma_fence *v3d_render_job_
|
||||
return fence;
|
||||
}
|
||||
|
||||
+#define V3D_TFU_REG(name) ((v3d->ver < 71) ? V3D_TFU_ ## name : V3D_V7_TFU_ ## name)
|
||||
+
|
||||
static struct dma_fence *
|
||||
v3d_tfu_job_run(struct drm_sched_job *sched_job)
|
||||
{
|
||||
@@ -302,20 +304,22 @@ v3d_tfu_job_run(struct drm_sched_job *sc
|
||||
trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
|
||||
|
||||
v3d_sched_stats_add_job(&v3d->gpu_queue_stats[V3D_TFU], sched_job);
|
||||
- V3D_WRITE(V3D_TFU_IIA, job->args.iia);
|
||||
- V3D_WRITE(V3D_TFU_IIS, job->args.iis);
|
||||
- V3D_WRITE(V3D_TFU_ICA, job->args.ica);
|
||||
- V3D_WRITE(V3D_TFU_IUA, job->args.iua);
|
||||
- V3D_WRITE(V3D_TFU_IOA, job->args.ioa);
|
||||
- V3D_WRITE(V3D_TFU_IOS, job->args.ios);
|
||||
- V3D_WRITE(V3D_TFU_COEF0, job->args.coef[0]);
|
||||
- if (job->args.coef[0] & V3D_TFU_COEF0_USECOEF) {
|
||||
- V3D_WRITE(V3D_TFU_COEF1, job->args.coef[1]);
|
||||
- V3D_WRITE(V3D_TFU_COEF2, job->args.coef[2]);
|
||||
- V3D_WRITE(V3D_TFU_COEF3, job->args.coef[3]);
|
||||
+ V3D_WRITE(V3D_TFU_REG(IIA), job->args.iia);
|
||||
+ V3D_WRITE(V3D_TFU_REG(IIS), job->args.iis);
|
||||
+ V3D_WRITE(V3D_TFU_REG(ICA), job->args.ica);
|
||||
+ V3D_WRITE(V3D_TFU_REG(IUA), job->args.iua);
|
||||
+ V3D_WRITE(V3D_TFU_REG(IOA), job->args.ioa);
|
||||
+ if (v3d->ver >= 71)
|
||||
+ V3D_WRITE(V3D_V7_TFU_IOC, job->args.v71.ioc);
|
||||
+ V3D_WRITE(V3D_TFU_REG(IOS), job->args.ios);
|
||||
+ V3D_WRITE(V3D_TFU_REG(COEF0), job->args.coef[0]);
|
||||
+ if (v3d->ver >= 71 || (job->args.coef[0] & V3D_TFU_COEF0_USECOEF)) {
|
||||
+ V3D_WRITE(V3D_TFU_REG(COEF1), job->args.coef[1]);
|
||||
+ V3D_WRITE(V3D_TFU_REG(COEF2), job->args.coef[2]);
|
||||
+ V3D_WRITE(V3D_TFU_REG(COEF3), job->args.coef[3]);
|
||||
}
|
||||
/* ICFG kicks off the job. */
|
||||
- V3D_WRITE(V3D_TFU_ICFG, job->args.icfg | V3D_TFU_ICFG_IOC);
|
||||
+ V3D_WRITE(V3D_TFU_REG(ICFG), job->args.icfg | V3D_TFU_ICFG_IOC);
|
||||
|
||||
return fence;
|
||||
}
|
||||
@@ -327,7 +331,7 @@ v3d_csd_job_run(struct drm_sched_job *sc
|
||||
struct v3d_dev *v3d = job->base.v3d;
|
||||
struct drm_device *dev = &v3d->drm;
|
||||
struct dma_fence *fence;
|
||||
- int i;
|
||||
+ int i, csd_cfg0_reg, csd_cfg_reg_count;
|
||||
|
||||
v3d->csd_job = job;
|
||||
|
||||
@@ -346,10 +350,12 @@ v3d_csd_job_run(struct drm_sched_job *sc
|
||||
v3d_sched_stats_add_job(&v3d->gpu_queue_stats[V3D_CSD], sched_job);
|
||||
v3d_switch_perfmon(v3d, &job->base);
|
||||
|
||||
- for (i = 1; i <= 6; i++)
|
||||
- V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0 + 4 * i, job->args.cfg[i]);
|
||||
+ csd_cfg0_reg = v3d->ver < 71 ? V3D_CSD_QUEUED_CFG0 : V3D_V7_CSD_QUEUED_CFG0;
|
||||
+ csd_cfg_reg_count = v3d->ver < 71 ? 6 : 7;
|
||||
+ for (i = 1; i <= csd_cfg_reg_count; i++)
|
||||
+ V3D_CORE_WRITE(0, csd_cfg0_reg + 4 * i, job->args.cfg[i]);
|
||||
/* CFG0 write kicks off the job. */
|
||||
- V3D_CORE_WRITE(0, V3D_CSD_QUEUED_CFG0, job->args.cfg[0]);
|
||||
+ V3D_CORE_WRITE(0, csd_cfg0_reg, job->args.cfg[0]);
|
||||
|
||||
return fence;
|
||||
}
|
||||
@@ -452,7 +458,8 @@ v3d_csd_job_timedout(struct drm_sched_jo
|
||||
{
|
||||
struct v3d_csd_job *job = to_csd_job(sched_job);
|
||||
struct v3d_dev *v3d = job->base.v3d;
|
||||
- u32 batches = V3D_CORE_READ(0, V3D_CSD_CURRENT_CFG4);
|
||||
+ u32 batches = V3D_CORE_READ(0, (v3d->ver < 71 ? V3D_CSD_CURRENT_CFG4 :
|
||||
+ V3D_V7_CSD_CURRENT_CFG4));
|
||||
|
||||
/* If we've made progress, skip reset and let the timer get
|
||||
* rearmed.
|
24
target/linux/bcm27xx/patches-6.1/950-0903-drm-v3d-update-UAPI-to-match-user-space-for-V3D-7.x.patch
Normal file
24
target/linux/bcm27xx/patches-6.1/950-0903-drm-v3d-update-UAPI-to-match-user-space-for-V3D-7.x.patch
Normal file
@ -0,0 +1,24 @@
|
||||
From 22fb30936524ae96151789741885edbc45efb53d Mon Sep 17 00:00:00 2001
|
||||
From: Iago Toral Quiroga <itoral@igalia.com>
|
||||
Date: Thu, 2 Mar 2023 11:52:08 +0100
|
||||
Subject: [PATCH] drm/v3d: update UAPI to match user-space for V3D 7.x
|
||||
|
||||
V3D t.x takes a new parameter to configure TFU jobs that needs
|
||||
to be provided by user space.
|
||||
---
|
||||
include/uapi/drm/v3d_drm.h | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/include/uapi/drm/v3d_drm.h
|
||||
+++ b/include/uapi/drm/v3d_drm.h
|
||||
@@ -319,6 +319,10 @@ struct drm_v3d_submit_tfu {
|
||||
|
||||
/* Pointer to an array of ioctl extensions*/
|
||||
__u64 extensions;
|
||||
+
|
||||
+ struct {
|
||||
+ __u32 ioc;
|
||||
+ } v71;
|
||||
};
|
||||
|
||||
/* Submits a compute shader for dispatch. This job will block on any
|
19
target/linux/bcm27xx/patches-6.1/950-0904-drm-v3d-add-brcm-2712-v3d-as-a-compatible-V3D-device.patch
Normal file
19
target/linux/bcm27xx/patches-6.1/950-0904-drm-v3d-add-brcm-2712-v3d-as-a-compatible-V3D-device.patch
Normal file
@ -0,0 +1,19 @@
|
||||
From 18bc419d38eda06ded78c7b702c0e21e5af8f24c Mon Sep 17 00:00:00 2001
|
||||
From: Iago Toral Quiroga <itoral@igalia.com>
|
||||
Date: Thu, 2 Mar 2023 11:54:45 +0100
|
||||
Subject: [PATCH] drm/v3d: add brcm,2712-v3d as a compatible V3D device
|
||||
|
||||
---
|
||||
drivers/gpu/drm/v3d/v3d_drv.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/gpu/drm/v3d/v3d_drv.c
|
||||
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
|
||||
@@ -193,6 +193,7 @@ static const struct drm_driver v3d_drm_d
|
||||
};
|
||||
|
||||
static const struct of_device_id v3d_of_match[] = {
|
||||
+ { .compatible = "brcm,2712-v3d" },
|
||||
{ .compatible = "brcm,2711-v3d" },
|
||||
{ .compatible = "brcm,7268-v3d" },
|
||||
{ .compatible = "brcm,7278-v3d" },
|
64
target/linux/bcm27xx/patches-6.1/950-0905-drm-v3d-Improve-MMU-support-for-larger-pages.patch
Normal file
64
target/linux/bcm27xx/patches-6.1/950-0905-drm-v3d-Improve-MMU-support-for-larger-pages.patch
Normal file
@ -0,0 +1,64 @@
|
||||
From 12c7ea43b930976f35ce75d11fd3f55438868e13 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Elwell <phil@raspberrypi.com>
|
||||
Date: Fri, 4 Aug 2023 11:26:10 +0100
|
||||
Subject: [PATCH] drm/v3d: Improve MMU support for larger pages
|
||||
|
||||
The built-in MMU driver went most of the way towards supporting larger
|
||||
kernel pages, but dropped the ball when it comes to calculating indexes
|
||||
into the page table. Fix it.
|
||||
|
||||
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
---
|
||||
drivers/gpu/drm/v3d/v3d_mmu.c | 15 ++++++++-------
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/v3d/v3d_mmu.c
|
||||
+++ b/drivers/gpu/drm/v3d/v3d_mmu.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "v3d_regs.h"
|
||||
|
||||
#define V3D_MMU_PAGE_SHIFT 12
|
||||
+#define V3D_PAGE_FACTOR (PAGE_SIZE >> V3D_MMU_PAGE_SHIFT)
|
||||
|
||||
/* Note: All PTEs for the 1MB superpage must be filled with the
|
||||
* superpage bit set.
|
||||
@@ -88,7 +89,7 @@ void v3d_mmu_insert_ptes(struct v3d_bo *
|
||||
{
|
||||
struct drm_gem_shmem_object *shmem_obj = &bo->base;
|
||||
struct v3d_dev *v3d = to_v3d_dev(shmem_obj->base.dev);
|
||||
- u32 page = bo->node.start;
|
||||
+ u32 page = bo->node.start * V3D_PAGE_FACTOR;
|
||||
u32 page_prot = V3D_PTE_WRITEABLE | V3D_PTE_VALID;
|
||||
struct sg_dma_page_iter dma_iter;
|
||||
|
||||
@@ -98,13 +99,13 @@ void v3d_mmu_insert_ptes(struct v3d_bo *
|
||||
u32 pte = page_prot | page_address;
|
||||
u32 i;
|
||||
|
||||
- BUG_ON(page_address + (PAGE_SIZE >> V3D_MMU_PAGE_SHIFT) >=
|
||||
+ BUG_ON(page_address + V3D_PAGE_FACTOR >=
|
||||
BIT(24));
|
||||
- for (i = 0; i < PAGE_SIZE >> V3D_MMU_PAGE_SHIFT; i++)
|
||||
+ for (i = 0; i < V3D_PAGE_FACTOR; i++)
|
||||
v3d->pt[page++] = pte + i;
|
||||
}
|
||||
|
||||
- WARN_ON_ONCE(page - bo->node.start !=
|
||||
+ WARN_ON_ONCE(page - (bo->node.start * V3D_PAGE_FACTOR) !=
|
||||
shmem_obj->base.size >> V3D_MMU_PAGE_SHIFT);
|
||||
|
||||
if (v3d_mmu_flush_all(v3d))
|
||||
@@ -115,10 +116,10 @@ void v3d_mmu_remove_ptes(struct v3d_bo *
|
||||
{
|
||||
struct v3d_dev *v3d = to_v3d_dev(bo->base.base.dev);
|
||||
u32 npages = bo->base.base.size >> V3D_MMU_PAGE_SHIFT;
|
||||
- u32 page;
|
||||
+ u32 page = bo->node.start * V3D_PAGE_FACTOR;
|
||||
|
||||
- for (page = bo->node.start; page < bo->node.start + npages; page++)
|
||||
- v3d->pt[page] = 0;
|
||||
+ while (npages--)
|
||||
+ v3d->pt[page++] = 0;
|
||||
|
||||
if (v3d_mmu_flush_all(v3d))
|
||||
dev_err(v3d->drm.dev, "MMU flush timeout\n");
|
19
target/linux/bcm27xx/patches-6.1/950-0906-dt-bindings-gpu-v3d-Add-BCM2712-to-compatibility-lis.patch
Normal file
19
target/linux/bcm27xx/patches-6.1/950-0906-dt-bindings-gpu-v3d-Add-BCM2712-to-compatibility-lis.patch
Normal file
@ -0,0 +1,19 @@
|
||||
From 5970fa51663511d7f773db7109ff6fa2504f186a Mon Sep 17 00:00:00 2001
|
||||
From: Iago Toral Quiroga <itoral@igalia.com>
|
||||
Date: Thu, 2 Mar 2023 11:56:52 +0100
|
||||
Subject: [PATCH] dt-bindings: gpu: v3d: Add BCM2712 to compatibility list
|
||||
|
||||
---
|
||||
Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.yaml | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.yaml
|
||||
+++ b/Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.yaml
|
||||
@@ -16,6 +16,7 @@ properties:
|
||||
|
||||
compatible:
|
||||
enum:
|
||||
+ - brcm,2712-v3d
|
||||
- brcm,2711-v3d
|
||||
- brcm,7268-v3d
|
||||
- brcm,7278-v3d
|
328
target/linux/bcm27xx/patches-6.1/950-0907-drivers-char-add-generic-gpiomem-driver.patch
Normal file
328
target/linux/bcm27xx/patches-6.1/950-0907-drivers-char-add-generic-gpiomem-driver.patch
Normal file
@ -0,0 +1,328 @@
|
||||
From fdf9cab5eaa849e90b12e17718bc47130a91433c Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
Date: Tue, 25 Apr 2023 15:52:13 +0100
|
||||
Subject: [PATCH] drivers: char: add generic gpiomem driver
|
||||
|
||||
Based on bcm2835-gpiomem.
|
||||
|
||||
We allow export of the "GPIO registers" to userspace via a chardev as
|
||||
this allows for finer access control (e.g. users must be group gpio, root
|
||||
not required).
|
||||
|
||||
This driver allows access to either rp1-gpiomem or gpiomem, depending on
|
||||
which nodes are populated in devicetree.
|
||||
|
||||
RP1 has a different look-and-feel to BCM283x SoCs as it has split ranges
|
||||
for IO controls and the parallel registered OE/IN/OUT access. To handle
|
||||
this, the driver concatenates the ranges for an IO bank and the
|
||||
corresponding RIO instance into a contiguous buffer.
|
||||
|
||||
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
||||
---
|
||||
drivers/char/Kconfig | 8 +
|
||||
drivers/char/Makefile | 1 +
|
||||
drivers/char/raspberrypi-gpiomem.c | 276 +++++++++++++++++++++++++++++
|
||||
3 files changed, 285 insertions(+)
|
||||
create mode 100644 drivers/char/raspberrypi-gpiomem.c
|
||||
|
||||
--- a/drivers/char/Kconfig
|
||||
+++ b/drivers/char/Kconfig
|
||||
@@ -461,4 +461,12 @@ config RANDOM_TRUST_BOOTLOADER
|
||||
believe its RNG facilities may be faulty. This may also be configured
|
||||
at boot time with "random.trust_bootloader=on/off".
|
||||
|
||||
+config RASPBERRYPI_GPIOMEM
|
||||
+ tristate "Rootless GPIO access via mmap() on Raspberry Pi boards"
|
||||
+ default n
|
||||
+ help
|
||||
+ Provides users with root-free access to the GPIO registers
|
||||
+ on the board. Calling mmap(/dev/gpiomem) will map the GPIO
|
||||
+ register page to the user's pointer.
|
||||
+
|
||||
endmenu
|
||||
--- a/drivers/char/Makefile
|
||||
+++ b/drivers/char/Makefile
|
||||
@@ -46,3 +46,4 @@ obj-$(CONFIG_XILLYBUS_CLASS) += xillybus
|
||||
obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
|
||||
obj-$(CONFIG_ADI) += adi.o
|
||||
obj-$(CONFIG_BRCM_CHAR_DRIVERS) += broadcom/
|
||||
+obj-$(CONFIG_RASPBERRYPI_GPIOMEM) += raspberrypi-gpiomem.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/char/raspberrypi-gpiomem.c
|
||||
@@ -0,0 +1,276 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
+/**
|
||||
+ * raspberrypi-gpiomem.c
|
||||
+ *
|
||||
+ * Provides MMIO access to discontiguous section of Device memory as a linear
|
||||
+ * user mapping. Successor to bcm2835-gpiomem.c.
|
||||
+ *
|
||||
+ * Copyright (c) 2023, Raspberry Pi Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/mm.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/cdev.h>
|
||||
+#include <linux/pagemap.h>
|
||||
+#include <linux/io.h>
|
||||
+
|
||||
+#define DRIVER_NAME "rpi-gpiomem"
|
||||
+#define DEVICE_MINOR 0
|
||||
+
|
||||
+/*
|
||||
+ * Sensible max for a hypothetical "gpio" controller that splits pads,
|
||||
+ * IO controls, GPIO in/out/enable, and function selection into different
|
||||
+ * ranges. Most use only one or two.
|
||||
+ */
|
||||
+#define MAX_RANGES 4
|
||||
+
|
||||
+struct io_windows {
|
||||
+ unsigned long phys_base;
|
||||
+ unsigned long len;
|
||||
+};
|
||||
+
|
||||
+struct rpi_gpiomem_priv {
|
||||
+ dev_t devid;
|
||||
+ struct class *class;
|
||||
+ struct cdev rpi_gpiomem_cdev;
|
||||
+ struct device *dev;
|
||||
+ const char *name;
|
||||
+ unsigned int nr_wins;
|
||||
+ struct io_windows iowins[4];
|
||||
+};
|
||||
+
|
||||
+static int rpi_gpiomem_open(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ int dev = iminor(inode);
|
||||
+ int ret = 0;
|
||||
+ struct rpi_gpiomem_priv *priv;
|
||||
+
|
||||
+ if (dev != DEVICE_MINOR)
|
||||
+ ret = -ENXIO;
|
||||
+
|
||||
+ priv = container_of(inode->i_cdev, struct rpi_gpiomem_priv,
|
||||
+ rpi_gpiomem_cdev);
|
||||
+ if (!priv)
|
||||
+ return -EINVAL;
|
||||
+ file->private_data = priv;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int rpi_gpiomem_release(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ int dev = iminor(inode);
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (dev != DEVICE_MINOR)
|
||||
+ ret = -ENXIO;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const struct vm_operations_struct rpi_gpiomem_vm_ops = {
|
||||
+#ifdef CONFIG_HAVE_IOREMAP_PROT
|
||||
+ .access = generic_access_phys
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static int rpi_gpiomem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
+{
|
||||
+ int i;
|
||||
+ struct rpi_gpiomem_priv *priv;
|
||||
+ unsigned long base;
|
||||
+ unsigned long len = 0;
|
||||
+ unsigned long offset;
|
||||
+
|
||||
+ priv = file->private_data;
|
||||
+ /*
|
||||
+ * Userspace must provide a virtual address space at least
|
||||
+ * the size of the concatenated ranges.
|
||||
+ */
|
||||
+ for (i = 0; i < priv->nr_wins; i++)
|
||||
+ len += priv->iowins[i].len;
|
||||
+ if (len > vma->vm_end - vma->vm_start + 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ vma->vm_ops = &rpi_gpiomem_vm_ops;
|
||||
+ offset = vma->vm_start;
|
||||
+ for (i = 0; i < priv->nr_wins; i++) {
|
||||
+ base = priv->iowins[i].phys_base >> PAGE_SHIFT;
|
||||
+ len = priv->iowins[i].len;
|
||||
+ vma->vm_page_prot = phys_mem_access_prot(file, base, len,
|
||||
+ vma->vm_page_prot);
|
||||
+ if (remap_pfn_range(vma, offset,
|
||||
+ base, len,
|
||||
+ vma->vm_page_prot))
|
||||
+ break;
|
||||
+ offset += len;
|
||||
+ }
|
||||
+
|
||||
+ if (i < priv->nr_wins)
|
||||
+ return -EAGAIN;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations rpi_gpiomem_fops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .open = rpi_gpiomem_open,
|
||||
+ .release = rpi_gpiomem_release,
|
||||
+ .mmap = rpi_gpiomem_mmap,
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id rpi_gpiomem_of_match[];
|
||||
+
|
||||
+static int rpi_gpiomem_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ int err, i;
|
||||
+ const struct of_device_id *id;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct device_node *node = dev->of_node;
|
||||
+ struct resource *ioresource;
|
||||
+ struct rpi_gpiomem_priv *priv;
|
||||
+
|
||||
+ /* Allocate buffers and instance data */
|
||||
+
|
||||
+ priv = kzalloc(sizeof(struct rpi_gpiomem_priv), GFP_KERNEL);
|
||||
+
|
||||
+ if (!priv) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto failed_inst_alloc;
|
||||
+ }
|
||||
+ platform_set_drvdata(pdev, priv);
|
||||
+
|
||||
+ priv->dev = dev;
|
||||
+ id = of_match_device(rpi_gpiomem_of_match, dev);
|
||||
+ if (!id)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /*
|
||||
+ * Device node naming - for legacy (bcm2835) DT bindings, the driver
|
||||
+ * created the node based on a hardcoded name - for new bindings,
|
||||
+ * take the node name from DT.
|
||||
+ */
|
||||
+ if (id == &rpi_gpiomem_of_match[0]) {
|
||||
+ priv->name = "gpiomem";
|
||||
+ } else {
|
||||
+ err = of_property_read_string(node, "chardev-name", &priv->name);
|
||||
+ if (err)
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Go find the register ranges associated with this instance
|
||||
+ */
|
||||
+ for (i = 0; i < MAX_RANGES; i++) {
|
||||
+ ioresource = platform_get_resource(pdev, IORESOURCE_MEM, i);
|
||||
+ if (!ioresource && i == 0) {
|
||||
+ dev_err(priv->dev, "failed to get IO resource - no ranges available\n");
|
||||
+ err = -ENOENT;
|
||||
+ goto failed_get_resource;
|
||||
+ }
|
||||
+ if (!ioresource)
|
||||
+ break;
|
||||
+
|
||||
+ priv->iowins[i].phys_base = ioresource->start;
|
||||
+ priv->iowins[i].len = (ioresource->end + 1) - ioresource->start;
|
||||
+ dev_info(&pdev->dev, "window base 0x%08lx size 0x%08lx\n",
|
||||
+ priv->iowins[i].phys_base, priv->iowins[i].len);
|
||||
+ priv->nr_wins++;
|
||||
+ }
|
||||
+
|
||||
+ /* Create character device entries */
|
||||
+
|
||||
+ err = alloc_chrdev_region(&priv->devid,
|
||||
+ DEVICE_MINOR, 1, priv->name);
|
||||
+ if (err != 0) {
|
||||
+ dev_err(priv->dev, "unable to allocate device number");
|
||||
+ goto failed_alloc_chrdev;
|
||||
+ }
|
||||
+ cdev_init(&priv->rpi_gpiomem_cdev, &rpi_gpiomem_fops);
|
||||
+ priv->rpi_gpiomem_cdev.owner = THIS_MODULE;
|
||||
+ err = cdev_add(&priv->rpi_gpiomem_cdev, priv->devid, 1);
|
||||
+ if (err != 0) {
|
||||
+ dev_err(priv->dev, "unable to register device");
|
||||
+ goto failed_cdev_add;
|
||||
+ }
|
||||
+
|
||||
+ /* Create sysfs entries */
|
||||
+
|
||||
+ priv->class = class_create(THIS_MODULE, priv->name);
|
||||
+ if (IS_ERR(priv->class)) {
|
||||
+ err = PTR_ERR(priv->class);
|
||||
+ goto failed_class_create;
|
||||
+ }
|
||||
+
|
||||
+ dev = device_create(priv->class, NULL, priv->devid, NULL, priv->name);
|
||||
+ if (IS_ERR(dev)) {
|
||||
+ err = PTR_ERR(dev);
|
||||
+ goto failed_device_create;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(priv->dev, "initialised %u regions as /dev/%s\n",
|
||||
+ priv->nr_wins, priv->name);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+failed_device_create:
|
||||
+ class_destroy(priv->class);
|
||||
+failed_class_create:
|
||||
+ cdev_del(&priv->rpi_gpiomem_cdev);
|
||||
+failed_cdev_add:
|
||||
+ unregister_chrdev_region(priv->devid, 1);
|
||||
+failed_alloc_chrdev:
|
||||
+failed_get_resource:
|
||||
+ kfree(priv);
|
||||
+failed_inst_alloc:
|
||||
+ dev_err(&pdev->dev, "could not load rpi_gpiomem");
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int rpi_gpiomem_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct rpi_gpiomem_priv *priv = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ device_destroy(priv->class, priv->devid);
|
||||
+ class_destroy(priv->class);
|
||||
+ cdev_del(&priv->rpi_gpiomem_cdev);
|
||||
+ unregister_chrdev_region(priv->devid, 1);
|
||||
+ kfree(priv);
|
||||
+
|
||||
+ dev_info(dev, "%s driver removed - OK", priv->name);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id rpi_gpiomem_of_match[] = {
|
||||
+ {
|
||||
+ .compatible = "brcm,bcm2835-gpiomem",
|
||||
+ },
|
||||
+ {
|
||||
+ .compatible = "raspberrypi,gpiomem",
|
||||
+ },
|
||||
+ { /* sentinel */ },
|
||||
+};
|
||||
+
|
||||
+MODULE_DEVICE_TABLE(of, rpi_gpiomem_of_match);
|
||||
+
|
||||
+static struct platform_driver rpi_gpiomem_driver = {
|
||||
+ .probe = rpi_gpiomem_probe,
|
||||
+ .remove = rpi_gpiomem_remove,
|
||||
+ .driver = {
|
||||
+ .name = DRIVER_NAME,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = rpi_gpiomem_of_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(rpi_gpiomem_driver);
|
||||
+
|
||||
+MODULE_ALIAS("platform:rpi-gpiomem");
|
||||
+MODULE_LICENSE("Dual BSD/GPL");
|
||||
+MODULE_DESCRIPTION("Driver for accessing GPIOs from userspace");
|
||||
+MODULE_AUTHOR("Jonathan Bell <jonathan@raspberrypi.com>");
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user