From 511578c128121326a3c48fdb35e4e62f96dc7b9d Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Wed, 27 Dec 2023 14:21:46 +0100 Subject: [PATCH 001/222] wolfssl: update to 5.6.6 Release Notes: https://github.com/wolfSSL/wolfssl/releases/tag/v5.6.6-stable Refresh patches: - 100-disable-hardening-check.patch Fixes: CVE-2023-6935 CVE-2023-6936 CVE-2023-6937 Signed-off-by: Nick Hainke --- package/libs/wolfssl/Makefile | 4 ++-- .../libs/wolfssl/patches/100-disable-hardening-check.patch | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package/libs/wolfssl/Makefile b/package/libs/wolfssl/Makefile index 6451dca68d..8477fb85c5 100644 --- a/package/libs/wolfssl/Makefile +++ b/package/libs/wolfssl/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=wolfssl -PKG_VERSION:=5.6.4-stable +PKG_VERSION:=5.6.6-stable PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/wolfSSL/wolfssl/archive/v$(PKG_VERSION) -PKG_HASH:=031691906794ff45e1e792561cf31759f5d29ac74936bc8dffb8b14f16d820b4 +PKG_HASH:=3d2ca672d41c2c2fa667885a80d6fa03c3e91f0f4f72f87aef2bc947e8c87237 PKG_FIXUP:=libtool libtool-abiver PKG_INSTALL:=1 diff --git a/package/libs/wolfssl/patches/100-disable-hardening-check.patch b/package/libs/wolfssl/patches/100-disable-hardening-check.patch index 368ec3e7e0..019645d796 100644 --- a/package/libs/wolfssl/patches/100-disable-hardening-check.patch +++ b/package/libs/wolfssl/patches/100-disable-hardening-check.patch @@ -1,6 +1,6 @@ --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h -@@ -2630,7 +2630,7 @@ extern void uITRON4_free(void *p) ; +@@ -2774,7 +2774,7 @@ extern void uITRON4_free(void *p) ; /* warning for not using harden build options (default with ./configure) */ /* do not warn if big integer support is disabled */ From 131403d8aae659a4e1393ad252e19bf1fd5fb428 Mon Sep 17 00:00:00 2001 From: John Audia Date: Mon, 1 Jan 2024 09:47:05 -0500 Subject: [PATCH 002/222] kernel: bump 6.1 to 6.1.70 Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.1.70 All patches automatically rebased. Build system: x86/64 Build-tested: x86/64/AMD Cezanne, filogic/xiaomi_redmi-router-ax6000-ubootmod Run-tested: x86/64/AMD Cezanne, filogic/xiaomi_redmi-router-ax6000-ubootmod Signed-off-by: John Audia --- include/kernel-6.1 | 4 ++-- ...ers-remove-legacy_cursor_update-hacks.patch | 2 +- ...h-Always-request-for-user-confirmatio.patch | 4 ++-- .../721-net-add-packet-mangeling.patch | 2 +- .../780-usb-net-MeigLink_modem_support.patch | 4 ++-- ...ET-skip-GRO-for-foreign-MAC-addresses.patch | 8 ++++---- ...tional-threading-for-backlog-processi.patch | 18 +++++++++--------- ...et-introduce-napi_is_scheduled-helper.patch | 2 +- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/include/kernel-6.1 b/include/kernel-6.1 index b42886811e..8cfdaad6d7 100644 --- a/include/kernel-6.1 +++ b/include/kernel-6.1 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.1 = .69 -LINUX_KERNEL_HASH-6.1.69 = 7e3d2694d18ce502068cc88a430da809abbd17d0773268524ebece442612b541 +LINUX_VERSION-6.1 = .70 +LINUX_KERNEL_HASH-6.1.70 = ed1365266456c07696a7499581aec5d851ca2296f4f6f90f23d189ea5a56afef diff --git a/target/linux/bcm27xx/patches-6.1/950-0045-drm-atomic-helpers-remove-legacy_cursor_update-hacks.patch b/target/linux/bcm27xx/patches-6.1/950-0045-drm-atomic-helpers-remove-legacy_cursor_update-hacks.patch index 178d0c514e..b64f2972c5 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0045-drm-atomic-helpers-remove-legacy_cursor_update-hacks.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0045-drm-atomic-helpers-remove-legacy_cursor_update-hacks.patch @@ -88,7 +88,7 @@ Signed-off-by: Maxime Ripard commit->event = kzalloc(sizeof(*commit->event), --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c -@@ -7743,6 +7743,19 @@ static int intel_atomic_commit(struct dr +@@ -7754,6 +7754,19 @@ static int intel_atomic_commit(struct dr state->base.legacy_cursor_update = false; } diff --git a/target/linux/bcm27xx/patches-6.1/950-0078-Revert-Bluetooth-Always-request-for-user-confirmatio.patch b/target/linux/bcm27xx/patches-6.1/950-0078-Revert-Bluetooth-Always-request-for-user-confirmatio.patch index 7304bf8bb6..bd2ccaa197 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0078-Revert-Bluetooth-Always-request-for-user-confirmatio.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0078-Revert-Bluetooth-Always-request-for-user-confirmatio.patch @@ -24,7 +24,7 @@ Signed-off-by: Phil Elwell --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c -@@ -2207,7 +2207,7 @@ mackey_and_ltk: +@@ -2214,7 +2214,7 @@ mackey_and_ltk: if (err) return SMP_UNSPECIFIED; @@ -33,7 +33,7 @@ Signed-off-by: Phil Elwell if (hcon->out) { sc_dhkey_check(smp); SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); -@@ -2222,9 +2222,6 @@ mackey_and_ltk: +@@ -2229,9 +2229,6 @@ mackey_and_ltk: confirm_hint = 0; confirm: diff --git a/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch index 9ce8f82af0..40aeb5da6f 100644 --- a/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch @@ -105,7 +105,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3604,6 +3604,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3607,6 +3607,11 @@ static int xmit_one(struct sk_buff *skb, if (dev_nit_active(dev)) dev_queue_xmit_nit(skb, dev); diff --git a/target/linux/generic/hack-6.1/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-6.1/780-usb-net-MeigLink_modem_support.patch index 481185122f..51f939356f 100644 --- a/target/linux/generic/hack-6.1/780-usb-net-MeigLink_modem_support.patch +++ b/target/linux/generic/hack-6.1/780-usb-net-MeigLink_modem_support.patch @@ -43,7 +43,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support #define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ -@@ -1146,6 +1151,11 @@ static const struct usb_device_id option +@@ -1147,6 +1152,11 @@ static const struct usb_device_id option { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000), /* SIMCom SIM5218 */ .driver_info = NCTRL(0) | NCTRL(1) | NCTRL(2) | NCTRL(3) | RSVD(4) }, @@ -55,7 +55,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support /* Quectel products using Qualcomm vendor ID */ { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)}, { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20), -@@ -1187,6 +1197,11 @@ static const struct usb_device_id option +@@ -1188,6 +1198,11 @@ static const struct usb_device_id option .driver_info = ZLP }, { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), .driver_info = RSVD(4) }, diff --git a/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index 094d63dd89..8763b92c02 100644 --- a/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -44,7 +44,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -7622,6 +7622,48 @@ static void __netdev_adjacent_dev_unlink +@@ -7625,6 +7625,48 @@ static void __netdev_adjacent_dev_unlink &upper_dev->adj_list.lower); } @@ -93,7 +93,7 @@ Signed-off-by: Felix Fietkau static int __netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev, bool master, void *upper_priv, void *upper_info, -@@ -7673,6 +7715,7 @@ static int __netdev_upper_dev_link(struc +@@ -7676,6 +7718,7 @@ static int __netdev_upper_dev_link(struc if (ret) return ret; @@ -101,7 +101,7 @@ Signed-off-by: Felix Fietkau ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); ret = notifier_to_errno(ret); -@@ -7769,6 +7812,7 @@ static void __netdev_upper_dev_unlink(st +@@ -7772,6 +7815,7 @@ static void __netdev_upper_dev_unlink(st __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); @@ -109,7 +109,7 @@ Signed-off-by: Felix Fietkau call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); -@@ -8821,6 +8865,7 @@ int dev_set_mac_address(struct net_devic +@@ -8824,6 +8868,7 @@ int dev_set_mac_address(struct net_devic if (err) return err; dev->addr_assign_type = NET_ADDR_SET; diff --git a/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch b/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch index e50a3ef699..baaf850fe4 100644 --- a/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch +++ b/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau #endif --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -4622,7 +4622,7 @@ static int napi_schedule_rps(struct soft +@@ -4625,7 +4625,7 @@ static int napi_schedule_rps(struct soft struct softnet_data *mysd = this_cpu_ptr(&softnet_data); #ifdef CONFIG_RPS @@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau sd->rps_ipi_next = mysd->rps_ipi_list; mysd->rps_ipi_list = sd; -@@ -5803,6 +5803,8 @@ static DEFINE_PER_CPU(struct work_struct +@@ -5806,6 +5806,8 @@ static DEFINE_PER_CPU(struct work_struct /* Network device is going away, flush any packets still pending */ static void flush_backlog(struct work_struct *work) { @@ -48,7 +48,7 @@ Signed-off-by: Felix Fietkau struct sk_buff *skb, *tmp; struct softnet_data *sd; -@@ -5817,8 +5819,17 @@ static void flush_backlog(struct work_st +@@ -5820,8 +5822,17 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau skb_queue_walk_safe(&sd->process_queue, skb, tmp) { if (skb->dev->reg_state == NETREG_UNREGISTERING) { __skb_unlink(skb, &sd->process_queue); -@@ -5826,7 +5837,16 @@ static void flush_backlog(struct work_st +@@ -5829,7 +5840,16 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau } static bool flush_required(int cpu) -@@ -5958,6 +5978,7 @@ static int process_backlog(struct napi_s +@@ -5961,6 +5981,7 @@ static int process_backlog(struct napi_s } rps_lock_irq_disable(sd); @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau if (skb_queue_empty(&sd->input_pkt_queue)) { /* * Inline a custom version of __napi_complete(). -@@ -5967,7 +5988,8 @@ static int process_backlog(struct napi_s +@@ -5970,7 +5991,8 @@ static int process_backlog(struct napi_s * We can use a plain write instead of clear_bit(), * and we dont need an smp_mb() memory barrier. */ @@ -101,7 +101,7 @@ Signed-off-by: Felix Fietkau again = false; } else { skb_queue_splice_tail_init(&sd->input_pkt_queue, -@@ -6383,6 +6405,55 @@ int dev_set_threaded(struct net_device * +@@ -6386,6 +6408,55 @@ int dev_set_threaded(struct net_device * } EXPORT_SYMBOL(dev_set_threaded); @@ -157,7 +157,7 @@ Signed-off-by: Felix Fietkau void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct *, int), int weight) { -@@ -11165,6 +11236,9 @@ static int dev_cpu_dead(unsigned int old +@@ -11168,6 +11239,9 @@ static int dev_cpu_dead(unsigned int old raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); @@ -167,7 +167,7 @@ Signed-off-by: Felix Fietkau #ifdef CONFIG_RPS remsd = oldsd->rps_ipi_list; oldsd->rps_ipi_list = NULL; -@@ -11468,6 +11542,7 @@ static int __init net_dev_init(void) +@@ -11471,6 +11545,7 @@ static int __init net_dev_init(void) INIT_CSD(&sd->defer_csd, trigger_rx_softirq, sd); spin_lock_init(&sd->defer_lock); diff --git a/target/linux/ipq806x/patches-6.1/700-01-net-introduce-napi_is_scheduled-helper.patch b/target/linux/ipq806x/patches-6.1/700-01-net-introduce-napi_is_scheduled-helper.patch index 35c0d850cd..f59c461f65 100644 --- a/target/linux/ipq806x/patches-6.1/700-01-net-introduce-napi_is_scheduled-helper.patch +++ b/target/linux/ipq806x/patches-6.1/700-01-net-introduce-napi_is_scheduled-helper.patch @@ -66,7 +66,7 @@ Signed-off-by: Christian Marangi /** --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -6591,7 +6591,7 @@ static int __napi_poll(struct napi_struc +@@ -6594,7 +6594,7 @@ static int __napi_poll(struct napi_struc * accidentally calling ->poll() when NAPI is not scheduled. */ work = 0; From b22539b5fef9572f9ce2bedcd01d083c918d82f1 Mon Sep 17 00:00:00 2001 From: Patryk Kowalczyk Date: Tue, 2 Jan 2024 10:37:47 +0100 Subject: [PATCH 003/222] mediatek: filogic: Asus TUF AX6000 fix inverted LED for 2.5Gb LAN port Router Asus TUF AX6000 have second MaxLinear GPY211 PHY controller for 2.5Gb LAN port. The 5'th LAN port have inverted status of the LED. Based on the commit from main branch 90fbec8 we could set proper status of the LED. Signed-off-by: Patryk Kowalczyk --- target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts b/target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts index 41e6d2471d..b05dec93b4 100644 --- a/target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts +++ b/target/linux/mediatek/dts/mt7986a-asus-tuf-ax6000.dts @@ -131,6 +131,7 @@ compatible = "ethernet-phy-ieee802.3-c45"; reg = <5>; + mxl,led-drive-vdd; mxl,led-config = <0x03f0 0x0 0x0 0x0>; }; From fdb87a91b4202ad1a58fe46f499e4e68bf82de4e Mon Sep 17 00:00:00 2001 From: Roland Reinl Date: Sun, 12 Nov 2023 19:04:32 +0100 Subject: [PATCH 004/222] mediatek: Add support for D-Link EAGLE PRO AI R32 R32 is like the M32 part of the EAGLE PRO AI series from D-Link. Specification: - MT7622BV SoC with 2.4GHz wifi - MT7975AN + MT7915AN for 5GHz - MT7531BE Switch - 512MB RAM - 128 MB flash - 2 LEDs (Status and Internet, both can be either orange or white) - 2 buttons (WPS and Reset) Compared to M32, the R32 has the following differences: - 4 LAN ports instead of 2 - The recory image starts with DLK6E6015001 instaed of DLK6E6010001 - Individual LEDs for power and internet - MAC address is stored at another offset in the ODM partition MAC addresses: - WAN MAC is stored in partition "Odm" at offset 0x81 - LAN (as printed on the device) is WAN MAC + 1 - WLAN MAC (2.4 GHz) is WAN MAC + 2 - WLAN MAC (5GHz) is WAN MAC + 3 Flashing via Recovery Web Interface: - Set your IP address to 192.168.0.10, subnetmask 255.255.255.0 - Press the reset button while powering on the deivce - Keep the reset button pressed until the internet LED blinks fast - Open a Chromium based and goto http://192.168.0.1 - Download openwrt-mediatek-mt7622-dlink_eagle-pro-ai-r32-a1-squashfs-recovery.bin Flashing via uBoot: - Open the case, connect to the UART console - Set your IP address to 10.10.10.3, subnet mask 255.255.255.0. Connect to one of the LAN interfaces of the router - Run a tftp server which provides openwrt-mediatek-mt7622-dlink_eagle-pro-ai-r32-initramfs-kernel.bin. - You can rename the file to iverson_uImage (no extension), then you don't have to enter the whole file name in uboot later. - Power on the device and select "1. System Load Linux to SDRAM via TFTP." in the boot menu - Enter image file, tftp server IP and device IP (if they differ from the default). - TFTP download to RAM will start. After a few seconds OpenWrt initramfs should start - The initramfs is accessible via 192.168.1.1, change your IP address accordingly (or use multiple IP addresses on your interface) - Create a backup of the Kernel1 partition, this file is required if a revert to stock should be done later - Perform a sysupgrade using openwrt-mediatek-mt7622-dlink_eagle-pro-ai-r32-squashfs-sysupgrade.bin - Reboot the device. OpenWrt should start from flash now Revert back to stock using the Recovery Web Interface: - Set your IP address to 192.168.0.10, subnetmask 255.255.255.0 - Press the reset button while powering on the deivce - Keep the reset button pressed until the internet LED blinks fast - Open a Chromium based and goto http://192.168.0.1 - Flash a decrypted firmware image from D-Link. Decrypting an firmware image is described below. Decrypting a D-Link firmware image: - Download https://github.com/RolandoMagico/firmware-utils/blob/M32/src/m32-firmware-util.c - Compile a binary from the downloaded file, e.g. gcc m32-firmware-util.c -lcrypto -o m32-firmware-util - Run ./m32-firmware-util R32 --DecryptFactoryImage - Example for firmware R32A1_FW103B01: ./m32-firmware-util R32 --DecryptFactoryImage R32A1_FW103B01.bin R32A1_FW103B01.decrypted.bin Revert back to stock using uBoot: - Open the case, connect to the UART console - Set your IP address to 10.10.10.3, subnet mask 255.255.255.0. Connect to one of the LAN interfaces of the router - Run a tftp server which provides the previously created backup of the Kernel1 partition. - You can rename the file to iverson_uImage (no extension), then you don't have to enter the whole file name in uboot later. - Power on the device and select "2. System Load Linux Kernel then write to Flash via TFTP." in the boot menu - Enter image file, tftp server IP and device IP (if they differ from the default). - TFTP download to FLASH will start. After a few seconds the stock firmware should start again There is also an image openwrt-mediatek-mt7622-dlink_eagle-pro-ai-r32-a1-squashfs-tftp.bin which can directly be flashed via U-Boot and TFTP. It can be used if no backup of the Kernel1 partition is reuqired. Flahsing via OEM web interface is currently not possible, the OEM images are encrypted. Creating images is only possible manually at the moment. The support for the M32/R32 already includes support for flashing from the OEM web interface: - The device tree contains both partitions (Kernel1 and Kernel2) with conditions to select the correct one based on the kernel command line - The U-Boot variable "boot_part" is set accordingly during startup to finish the partition swap after flashing from the OEM web interface - OpenWrt sysupgrade flashing always uses the partition where it was initially flashed to (no partition swap) Signed-off-by: Roland Reinl --- .../boot/uboot-envtools/files/mediatek_mt7622 | 4 + .../mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi | 369 ++++++++++++++++ .../dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts | 394 ++---------------- .../dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts | 78 ++++ target/linux/mediatek/image/mt7622.mk | 40 +- .../mt7622/base-files/etc/board.d/02_network | 5 +- .../etc/hotplug.d/ieee80211/11_fix_wifi_mac | 4 - .../mt7622/base-files/etc/init.d/bootcount | 8 + .../mt7622/base-files/lib/upgrade/platform.sh | 4 +- 9 files changed, 521 insertions(+), 385 deletions(-) create mode 100644 target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi create mode 100644 target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts diff --git a/package/boot/uboot-envtools/files/mediatek_mt7622 b/package/boot/uboot-envtools/files/mediatek_mt7622 index e01dcc4fef..fdf0d331fc 100644 --- a/package/boot/uboot-envtools/files/mediatek_mt7622 +++ b/package/boot/uboot-envtools/files/mediatek_mt7622 @@ -12,6 +12,10 @@ touch /etc/config/ubootenv board=$(board_name) case "$board" in +dlink,eagle-pro-ai-m32-a1|\ +dlink,eagle-pro-ai-r32-a1) + ubootenv_add_uci_config "/dev/mtd3" "0x0" "0x2000" "0x2000" + ;; linksys,e8450-ubi) ubootenv_add_uci_config "/dev/ubi0_0" "0x0" "0x1f000" "0x1f000" "1" ubootenv_add_uci_config "/dev/ubi0_1" "0x0" "0x1f000" "0x1f000" "1" diff --git a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi new file mode 100644 index 0000000000..6d87454370 --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi @@ -0,0 +1,369 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7622.dtsi" +#include "mt6380.dtsi" +#include +#include + +/ { + aliases { + serial0 = &uart0; + label-mac-device = &gmac0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8 swiotlb=512"; + }; + + cpus { + cpu@0 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; + }; + + cpu@1 { + proc-supply = <&mt6380_vcpu_reg>; + sram-supply = <&mt6380_vm_reg>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-reset { + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + label = "reset"; + linux,code = ; + }; + + button-wps { + gpios = <&pio 102 GPIO_ACTIVE_LOW>; + label = "wps"; + linux,code = ; + }; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; +}; + +&bch { + status = "okay"; +}; + +&btif { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <ð_pins>; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + phy-mode = "2500base-x"; + reg = <0>; + nvmem-cells = <&macaddr_odm 1>; + nvmem-cell-names = "mac-address"; + fixed-link { + full-duplex; + pause; + speed = <2500>; + }; + }; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + switch: switch@0 { + compatible = "mediatek,mt7531"; + reg = <0>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; + reset-gpios = <&pio 54 0>; + + ports { + wan: port@4 { + reg = <4>; + label = "wan"; + nvmem-cells = <&macaddr_odm 0>; + nvmem-cell-names = "mac-address"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + }; +}; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>; + status = "okay"; +}; + +&pcie1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_pins>; + status = "okay"; +}; + +&pio { + epa_elna_pins: epa-elna-pins { + mux { + function = "antsel"; + groups = "antsel0", "antsel1", "antsel2", "antsel3", + "antsel4", "antsel5", "antsel6", "antsel7", + "antsel8", "antsel9", "antsel12", "antsel13", + "antsel14", "antsel15", "antsel16", "antsel17"; + }; + }; + + eth_pins: eth-pins { + mux { + function = "eth"; + groups = "mdc_mdio", "rgmii_via_gmac2"; + }; + }; + + pcie0_pins: pcie0-pins { + mux { + function = "pcie"; + groups = "pcie0_pad_perst", + "pcie0_1_waken", + "pcie0_1_clkreq"; + }; + }; + + pcie1_pins: pcie1-pins { + mux { + function = "pcie"; + groups = "pcie1_pad_perst", + "pcie1_0_waken", + "pcie1_0_clkreq"; + }; + }; + + pmic_bus_pins: pmic-bus-pins { + mux { + function = "pmic"; + groups = "pmic_bus"; + }; + }; + + /* Serial NAND is shared pin with SPI-NOR */ + serial_nand_pins: serial-nand-pins { + mux { + function = "flash"; + groups = "snfi"; + }; + }; + + uart0_pins: uart0-pins { + mux { + function = "uart"; + groups = "uart0_0_tx_rx"; + }; + }; + + watchdog_pins: watchdog-pins { + mux { + function = "watchdog"; + groups = "watchdog"; + }; + }; +}; + +&pwrap { + pinctrl-names = "default"; + pinctrl-0 = <&pmic_bus_pins>; + status = "okay"; +}; + +&rtc { + status = "disabled"; +}; + +&sata { + status = "disabled"; +}; + +&sata_phy { + status = "disabled"; +}; + +&slot0 { + wmac1: mt7915@0,0 { + reg = <0x0000 0 0 0 0>; + ieee80211-freq-limit = <5000000 6000000>; + mediatek,mtd-eeprom = <&factory 0x05000>; + nvmem-cells = <&macaddr_odm 3>; + nvmem-cell-names = "mac-address"; + }; +}; + +&snfi { + pinctrl-names = "default"; + pinctrl-0 = <&serial_nand_pins>; + status = "okay"; + + snand: flash@0 { + compatible = "spi-nand"; + mediatek,bmt-table-size = <0x1000>; + mediatek,bmt-v2; + nand-ecc-engine = <&snfi>; + reg = <0>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Preloader"; + reg = <0x00000000 0x00080000>; + read-only; + }; + + partition@80000 { + label = "ATF"; + reg = <0x00080000 0x00040000>; + read-only; + }; + + partition@C0000 { + label = "Bootloader"; + reg = <0x000C0000 0x00080000>; + read-only; + }; + + partition@140000 { + label = "BootConfig"; + reg = <0x00140000 0x00040000>; + }; + + partition@180000 { + label = "Odm"; + reg = <0x00180000 0x00040000>; + read-only; + odm_partition: nvmem-layout { + compatible = "fixed-layout"; + }; + }; + + config1: partition@1C0000 { + compatible = "nvmem-cells"; + label = "Config1"; + reg = <0x001C0000 0x00080000>; + read-only; + }; + + partition@240000 { + label = "Config2"; + reg = <0x00240000 0x00080000>; + read-only; + }; + + partition@2C0000 { + label = "Kernel1"; + reg = <0x002C0000 0x02D00000>; + + compatible = "denx,fit"; + openwrt,cmdline-match = "boot_part=Kernel1"; + partition@0 { + label = "kernel"; + reg = <0x00000000 0x00800000>; + }; + + partition@800000 { + label = "ubi"; + reg = <0x00800000 0x02500000>; + }; + }; + + partition@2FC0000 { + label = "Kernel2"; + reg = <0x02FC0000 0x02D00000>; + + compatible = "denx,fit"; + openwrt,cmdline-match = "boot_part=Kernel2"; + partition@0 { + label = "kernel"; + reg = <0x00000000 0x00800000>; + }; + + partition@800000 { + label = "ubi"; + reg = <0x00800000 0x02500000>; + }; + }; + + factory: partition@5CC0000 { + label = "Factory"; + reg = <0x05CC0000 0x00100000>; + read-only; + }; + + partition@5DC0000 { + label = "Mydlink"; + reg = <0x05DC0000 0x00200000>; + read-only; + }; + + partition@5FC0000 { + label = "Storage"; + reg = <0x05FC0000 0x00300000>; + read-only; + }; + }; + }; +}; + +&ssusb { + status = "disabled"; +}; + +&u3phy { + status = "disabled"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&watchdog { + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + status = "okay"; +}; + +&wmac { + pinctrl-names = "default"; + pinctrl-0 = <&epa_elna_pins>; + mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&macaddr_odm 2>; + nvmem-cell-names = "mac-address"; + status = "okay"; +}; + diff --git a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts index 9c90cee516..2b40c5e7d5 100644 --- a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts +++ b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-m32-a1.dts @@ -1,401 +1,63 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT /dts-v1/; -#include "mt7622.dtsi" -#include "mt6380.dtsi" -#include -#include +#include "mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi" +#include / { model = "D-Link EAGLE PRO AI M32 A1"; compatible = "dlink,eagle-pro-ai-m32-a1", "mediatek,mt7622"; aliases { - led-boot = &status_orange; - led-failsafe = &status_red; - led-running = &status_white; - led-upgrade = &status_red; - serial0 = &uart0; - label-mac-device = &gmac0; - }; - - chosen { - stdout-path = "serial0:115200n8"; - bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8 swiotlb=512"; - }; - - cpus { - cpu@0 { - proc-supply = <&mt6380_vcpu_reg>; - sram-supply = <&mt6380_vm_reg>; - }; - - cpu@1 { - proc-supply = <&mt6380_vcpu_reg>; - sram-supply = <&mt6380_vm_reg>; - }; - }; - - gpio-keys { - compatible = "gpio-keys"; - - reset { - gpios = <&pio 0 GPIO_ACTIVE_LOW>; - label = "reset"; - linux,code = ; - }; - - wps { - gpios = <&pio 102 GPIO_ACTIVE_LOW>; - label = "wps"; - linux,code = ; - }; + led-boot = &led_status_orange; + led-failsafe = &led_status_red; + led-running = &led_status_white; + led-upgrade = &led_status_red; }; leds { compatible = "gpio-leds"; - status_white: status_white { - label = "white:status"; + led_status_white: led-status-white { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 85 GPIO_ACTIVE_LOW>; }; - status_orange: status_orange { - label = "orange:status"; + led_status_orange: led-status-orange { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 20 GPIO_ACTIVE_LOW>; default-state = "on"; }; - status_red: status_red { - label = "red:status"; + led_status_red: led-status-red { + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 17 GPIO_ACTIVE_LOW>; }; }; - - memory { - reg = <0 0x40000000 0 0x40000000>; - }; }; -&bch { - status = "okay"; -}; - -&btif { - status = "okay"; -}; - -ð { - pinctrl-names = "default"; - pinctrl-0 = <ð_pins>; - status = "okay"; - - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - nvmem-cells = <&macaddr_odm_83>; - nvmem-cell-names = "mac-address"; - phy-mode = "2500base-x"; - reg = <0>; - - fixed-link { - full-duplex; - pause; - speed = <2500>; +&switch { + ports { + port@2 { + reg = <2>; + label = "lan2"; }; - }; - mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - switch@0 { - compatible = "mediatek,mt7531"; - reg = <0>; - interrupt-controller; - #interrupt-cells = <1>; - interrupt-parent = <&pio>; - interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; - reset-gpios = <&pio 54 0>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@2 { - reg = <2>; - label = "lan2"; - }; - - port@3 { - reg = <3>; - label = "lan1"; - }; - - wan: port@4 { - reg = <4>; - label = "wan"; - }; - - port@6 { - reg = <6>; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; + port@3 { + reg = <3>; + label = "lan1"; }; }; }; -&pcie0 { - pinctrl-names = "default"; - pinctrl-0 = <&pcie0_pins>; - status = "okay"; -}; - -&pcie1 { - pinctrl-names = "default"; - pinctrl-0 = <&pcie1_pins>; - status = "okay"; -}; - -&pio { - epa_elna_pins: epa-elna-pins { - mux { - function = "antsel"; - groups = "antsel0", "antsel1", "antsel2", "antsel3", - "antsel4", "antsel5", "antsel6", "antsel7", - "antsel8", "antsel9", "antsel12", "antsel13", - "antsel14", "antsel15", "antsel16", "antsel17"; - }; - }; - - eth_pins: eth-pins { - mux { - function = "eth"; - groups = "mdc_mdio", "rgmii_via_gmac2"; - }; - }; - - pcie0_pins: pcie0-pins { - mux { - function = "pcie"; - groups = "pcie0_pad_perst", - "pcie0_1_waken", - "pcie0_1_clkreq"; - }; - }; - - pcie1_pins: pcie1-pins { - mux { - function = "pcie"; - groups = "pcie1_pad_perst", - "pcie1_0_waken", - "pcie1_0_clkreq"; - }; - }; - - pmic_bus_pins: pmic-bus-pins { - mux { - function = "pmic"; - groups = "pmic_bus"; - }; - }; - - /* Serial NAND is shared pin with SPI-NOR */ - serial_nand_pins: serial-nand-pins { - mux { - function = "flash"; - groups = "snfi"; - }; - }; - - uart0_pins: uart0-pins { - mux { - function = "uart"; - groups = "uart0_0_tx_rx"; - }; - }; - - watchdog_pins: watchdog-pins { - mux { - function = "watchdog"; - groups = "watchdog"; - }; +&odm_partition { + macaddr_odm: macaddr@83 { + compatible = "mac-base"; + reg = <0x83 0x6>; + #nvmem-cell-cells = <1>; }; }; -&pwrap { - pinctrl-names = "default"; - pinctrl-0 = <&pmic_bus_pins>; - status = "okay"; -}; - -&rtc { - status = "disabled"; -}; - -&sata { - status = "disabled"; -}; - -&sata_phy { - status = "disabled"; -}; - -&slot0 { - wmac1: mt7915@0,0 { - reg = <0x0000 0 0 0 0>; - ieee80211-freq-limit = <5000000 6000000>; - mediatek,mtd-eeprom = <&factory 0x05000>; - }; -}; - -&snfi { - pinctrl-names = "default"; - pinctrl-0 = <&serial_nand_pins>; - status = "okay"; - - snand: flash@0 { - compatible = "spi-nand"; - mediatek,bmt-table-size = <0x1000>; - mediatek,bmt-v2; - nand-ecc-engine = <&snfi>; - reg = <0>; - spi-rx-bus-width = <4>; - spi-tx-bus-width = <4>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "Preloader"; - reg = <0x00000000 0x00080000>; - read-only; - }; - - partition@80000 { - label = "ATF"; - reg = <0x00080000 0x00040000>; - read-only; - }; - - partition@C0000 { - label = "Bootloader"; - reg = <0x000C0000 0x00080000>; - read-only; - }; - - partition@140000 { - label = "BootConfig"; - reg = <0x00140000 0x00040000>; - read-only; - }; - - odm: partition@180000 { - label = "Odm"; - reg = <0x00180000 0x00040000>; - read-only; - - nvmem-layout { - compatible = "fixed-layout"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_odm_83: macaddr@83 { - reg = <0x83 0x6>; - }; - }; - }; - - config1: partition@1C0000 { - label = "Config1"; - reg = <0x001C0000 0x00080000>; - read-only; - }; - - partition@240000 { - label = "Config2"; - reg = <0x00240000 0x00080000>; - read-only; - }; - - partition@2C0000 { - label = "Kernel1"; - reg = <0x002C0000 0x02D00000>; - - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - partition@0 { - label = "kernel"; - reg = <0x00000000 0x00800000>; - }; - - partition@800000 { - label = "ubi"; - reg = <0x00800000 0x02500000>; - }; - }; - - partition@2FC0000 { - label = "Kernel2"; - reg = <0x02FC0000 0x02D00000>; - read-only; - }; - - factory: partition@5CC0000 { - label = "Factory"; - reg = <0x05CC0000 0x00100000>; - read-only; - }; - - partition@5DC0000 { - label = "Mydlink"; - reg = <0x05DC0000 0x00200000>; - read-only; - }; - - partition@5FC0000 { - label = "Storage"; - reg = <0x05FC0000 0x00300000>; - read-only; - }; - }; - }; -}; - -&ssusb { - status = "disabled"; -}; - -&u3phy { - status = "disabled"; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins>; - status = "okay"; -}; - -&watchdog { - pinctrl-names = "default"; - pinctrl-0 = <&watchdog_pins>; - status = "okay"; -}; - -&wmac { - pinctrl-names = "default"; - pinctrl-0 = <&epa_elna_pins>; - mediatek,mtd-eeprom = <&factory 0x0000>; - status = "okay"; -}; - diff --git a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts new file mode 100644 index 0000000000..b21ba36cfc --- /dev/null +++ b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-r32-a1.dts @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi" +#include + +/ { + model = "D-Link EAGLE PRO AI R32 A1"; + compatible = "dlink,eagle-pro-ai-r32-a1", "mediatek,mt7622"; + + aliases { + led-boot = &led_power_orange; + led-failsafe = &led_power_orange; + led-running = &led_power_white; + led-upgrade = &led_power_orange; + }; + + leds { + compatible = "gpio-leds"; + + led_power_orange: led-power-orange { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 20 GPIO_ACTIVE_HIGH>; + }; + + led_power_white: led-power-white { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 85 GPIO_ACTIVE_LOW>; + }; + + led_internet_orange: led-internet-orange { + color = ; + function = "internet"; // LED_FUNCTION_INTERNET; + gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + }; + + led_internet_white: led-internet-white { + color = ; + function = "internet"; // LED_FUNCTION_INTERNET; + gpios = <&pio 17 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&switch { + ports { + port@0 { + reg = <0>; + label = "lan4"; + }; + + port@1 { + reg = <1>; + label = "lan3"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + }; + }; +}; + +&odm_partition { + macaddr_odm: macaddr@81 { + compatible = "mac-base"; + reg = <0x81 0x6>; + #nvmem-cell-cells = <1>; + }; +}; + diff --git a/target/linux/mediatek/image/mt7622.mk b/target/linux/mediatek/image/mt7622.mk index d0f5280dcf..e393b8433e 100644 --- a/target/linux/mediatek/image/mt7622.mk +++ b/target/linux/mediatek/image/mt7622.mk @@ -37,9 +37,15 @@ define Build/bl31-uboot cat $(STAGING_DIR_IMAGE)/mt7622_$1-u-boot.fip >> $@ endef -# Append header to a D-Link M32 Kernel 1 partition -define Build/m32-recovery-header-kernel1 - echo -en "DLK6E6010001\x00\x00\xCF\x33" > "$@.header" +# Append header to a D-Link M32/R32 Kernel 1 partition +define Build/m32-r32-recovery-header-kernel1 + $(eval header_start=$(word 1,$(1))) +# create $@.header without the checksum + echo -en "$(header_start)\x00\x00" > "$@.header" +# Calculate checksum over data area ($@) and append it to the header. +# The checksum is the 2byte-sum over the whole data area. +# Every overflow during the checksum calculation must increment the current checksum value by 1. + od -v -w2 -tu2 -An --endian little "$@" | awk '{ s+=$$1; } END { s%=65535; printf "%c%c",s%256,s/256; }' >> "$@.header" echo -en "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x8D\x57\x30\x0B" >> "$@.header" # Byte 0-3: Erase Start 0x002C0000 # Byte 4-7: Erase Length 0x02D00000 @@ -48,9 +54,11 @@ define Build/m32-recovery-header-kernel1 echo -en "\x00\x00\x2C\x00\x00\x00\xD0\x02\x00\x00\x2C\x00\x00\x00\xD0\x02" >> "$@.header" # Only zeros echo -en "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" >> "$@.header" -# Note: The last 2 bytes of the following line are the checksum of the header -# If any data in the header will be changed, the checksum must be re-calculated - echo -en "\x42\x48\x02\x00\x00\x00\x08\x00\x00\x00\x00\x00\x60\x6E\x68\x61" >> "$@.header" +# Last 16 bytes, but without checksum + echo -en "\x42\x48\x02\x00\x00\x00\x08\x00\x00\x00\x00\x00\x60\x6E" >> "$@.header" +# Calculate and append checksum: The checksum must be set so that the 2byte-sum of the whole header is 0. +# Every overflow during the checksum calculation must increment the current checksum value by 1. + od -v -w2 -tu2 -An --endian little "$@.header" | awk '{s+=65535-$$1;}END{s%=65535;printf "%c%c",s%256,s/256;}' >> "$@.header" cat "$@.header" "$@" > "$@.new" mv "$@.new" "$@" rm "$@.header" @@ -168,12 +176,10 @@ define Device/buffalo_wsr-3200ax4s endef TARGET_DEVICES += buffalo_wsr-3200ax4s -define Device/dlink_eagle-pro-ai-m32-a1 +define Device/dlink_eagle-pro-ai-ax3200-a1 IMAGE_SIZE := 46080k DEVICE_VENDOR := D-Link - DEVICE_MODEL := EAGLE PRO AI M32 DEVICE_VARIANT := A1 - DEVICE_DTS := mt7622-dlink-eagle-pro-ai-m32-a1 DEVICE_DTS_DIR := ../dts DEVICE_PACKAGES := kmod-mt7915-firmware KERNEL_SIZE := 8192k @@ -183,10 +189,24 @@ define Device/dlink_eagle-pro-ai-m32-a1 IMAGES += tftp.bin recovery.bin IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata IMAGE/tftp.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | check-size - IMAGE/recovery.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | pad-to $$(IMAGE_SIZE) | m32-recovery-header-kernel1 +endef + +define Device/dlink_eagle-pro-ai-m32-a1 + $(Device/dlink_eagle-pro-ai-ax3200-a1) + DEVICE_MODEL := EAGLE PRO AI M32 + DEVICE_DTS := mt7622-dlink-eagle-pro-ai-m32-a1 + IMAGE/recovery.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | pad-to $$(IMAGE_SIZE) | m32-r32-recovery-header-kernel1 DLK6E6010001 endef TARGET_DEVICES += dlink_eagle-pro-ai-m32-a1 +define Device/dlink_eagle-pro-ai-r32-a1 + $(Device/dlink_eagle-pro-ai-ax3200-a1) + DEVICE_MODEL := EAGLE PRO AI R32 + DEVICE_DTS := mt7622-dlink-eagle-pro-ai-r32-a1 + IMAGE/recovery.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | pad-to $$(IMAGE_SIZE) | m32-r32-recovery-header-kernel1 DLK6E6015001 +endef +TARGET_DEVICES += dlink_eagle-pro-ai-r32-a1 + define Device/elecom_wrc-2533gent DEVICE_VENDOR := Elecom DEVICE_MODEL := WRC-2533GENT diff --git a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network index 75c5e37be1..6c43e46222 100644 --- a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network @@ -10,6 +10,7 @@ mediatek_setup_interfaces() case $board in bananapi,bpi-r64|\ buffalo,wsr-3200ax4s|\ + dlink,eagle-pro-ai-r32-a1|\ elecom,wrc-x3200gst3|\ linksys,e8450|\ linksys,e8450-ubi|\ @@ -64,10 +65,6 @@ mediatek_setup_macs() wan_mac=$lan_mac label_mac=$lan_mac ;; - dlink,eagle-pro-ai-m32-a1) - wan_mac=$(get_mac_label) - lan_mac=$(macaddr_add $(get_mac_label) 1) - ;; reyee,ax3200-e5|\ ruijie,rg-ew3200gx-pro) lan_mac=$(macaddr_add $(get_mac_label) 1) diff --git a/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index e9cc592237..7ee9f24071 100644 --- a/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/mediatek/mt7622/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -18,10 +18,6 @@ case "$board" in [ "$PHYNBR" = "0" ] && macaddr_add $basemac 1 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $basemac 8 > /sys${DEVPATH}/macaddress ;; - dlink,eagle-pro-ai-m32-a1) - [ "$PHYNBR" = "0" ] && macaddr_add $(cat /sys/class/net/eth0/address) 2 > /sys${DEVPATH}/macaddress - [ "$PHYNBR" = "1" ] && macaddr_add $(cat /sys/class/net/eth0/address) 3 > /sys${DEVPATH}/macaddress - ;; reyee,ax3200-e5|\ ruijie,rg-ew3200gx-pro) [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 3 > /sys${DEVPATH}/macaddress diff --git a/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount b/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount index bc4eeb6530..19a321b48b 100755 --- a/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount +++ b/target/linux/mediatek/mt7622/base-files/etc/init.d/bootcount @@ -4,6 +4,14 @@ START=99 boot() { case $(board_name) in + dlink,eagle-pro-ai-m32-a1|\ + dlink,eagle-pro-ai-r32-a1) + if grep -q boot_part=Kernel1 /proc/cmdline; then + fw_setenv boot_part 1 + else + fw_setenv boot_part 2 + fi + ;; linksys,e8450) mtd erase senv || true ;; diff --git a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh index e256d2b533..3a2d7a4cd6 100755 --- a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh @@ -35,6 +35,7 @@ platform_do_upgrade() { fi ;; dlink,eagle-pro-ai-m32-a1|\ + dlink,eagle-pro-ai-r32-a1|\ elecom,wrc-x3200gst3|\ mediatek,mt7622-rfb1-ubi|\ netgear,wax206|\ @@ -73,7 +74,8 @@ platform_check_image() { buffalo,wsr-3200ax4s) buffalo_check_image "$board" "$magic" "$1" || return 1 ;; - dlink,eagle-pro-ai-m32-a1|\ + dlink,eagle-pro-ai-m32-a1|\ + dlink,eagle-pro-ai-r32-a1|\ elecom,wrc-x3200gst3|\ mediatek,mt7622-rfb1-ubi|\ netgear,wax206|\ From 3f1be8edee29fe79fc33c88cbd9d647a490410e5 Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Fri, 15 Dec 2023 17:15:47 +0100 Subject: [PATCH 005/222] ramips: mtk_eth_soc: allow multiple resets Use devm_reset_control_array_get_exclusive to register multiple reset lines in FE driver. This is required to reattach ESW reset to FE driver again, based on device tree bindings. While at that, remove unused fe_priv.rst_ppe field, and add error message if getting the reset fails. Fixes: 60fadae62b64 ("ramips: ethernet: ralink: move reset of the esw into the esw instead of fe") Co-developed-by: Maxim Anisimov Signed-off-by: Maxim Anisimov [Split out of the bigger commit, provide commit mesage, refactor error handling] Signed-off-by: Lech Perczak --- .../drivers/net/ethernet/ralink/mtk_eth_soc.c | 14 ++++++++------ .../drivers/net/ethernet/ralink/mtk_eth_soc.h | 3 +-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c index b79b348938..78b17605d2 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c @@ -143,12 +143,12 @@ void fe_reset(u32 reset_bits) void fe_reset_fe(struct fe_priv *priv) { - if (!priv->rst_fe) + if (!priv->resets) return; - reset_control_assert(priv->rst_fe); + reset_control_assert(priv->resets); usleep_range(60, 120); - reset_control_deassert(priv->rst_fe); + reset_control_deassert(priv->resets); usleep_range(60, 120); } @@ -1595,9 +1595,11 @@ static int fe_probe(struct platform_device *pdev) priv = netdev_priv(netdev); spin_lock_init(&priv->page_lock); - priv->rst_fe = devm_reset_control_get(&pdev->dev, "fe"); - if (IS_ERR(priv->rst_fe)) - priv->rst_fe = NULL; + priv->resets = devm_reset_control_array_get_exclusive(&pdev->dev); + if (IS_ERR(priv->resets)) { + dev_err(&pdev->dev, "Failed to get resets for FE and ESW cores: %pe\n", priv->resets); + priv->resets = NULL; + } if (soc->init_data) soc->init_data(soc, netdev); diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h index 968db366cf..892ffb2126 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h @@ -497,8 +497,7 @@ struct fe_priv { struct work_struct pending_work; DECLARE_BITMAP(pending_flags, FE_FLAG_MAX); - struct reset_control *rst_ppe; - struct reset_control *rst_fe; + struct reset_control *resets; struct mtk_foe_entry *foe_table; dma_addr_t foe_table_phys; struct flow_offload __rcu **foe_flow_table; From 7eb0458c1f7e4f681b16d2721cfc3fcb69774c95 Mon Sep 17 00:00:00 2001 From: Maxim Anisimov Date: Sun, 10 Dec 2023 16:27:32 +0100 Subject: [PATCH 006/222] ramips: mtk_eth_soc: wait longer after FE core reset to settle Enabling the FE core too early causes the system to hang during boot uncondtionally, after the reset is released. Increate it to 1-1.2ms range. Fixes: 60fadae62b64 ("ramips: ethernet: ralink: move reset of the esw into the esw instead of fe") Signed-off-by: Maxim Anisimov [Split previous commit, provide rationale] Signed-off-by: Lech Perczak --- .../ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c index 78b17605d2..dab8a173f7 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c @@ -149,7 +149,7 @@ void fe_reset_fe(struct fe_priv *priv) reset_control_assert(priv->resets); usleep_range(60, 120); reset_control_deassert(priv->resets); - usleep_range(60, 120); + usleep_range(1000, 1200); } static inline void fe_int_disable(u32 mask) From 8d75b1de0ff7b9e9e0138f822a5475bb8ad7fedf Mon Sep 17 00:00:00 2001 From: Maxim Anisimov Date: Fri, 8 Dec 2023 08:34:30 +0300 Subject: [PATCH 007/222] ramips: dts: rt3352: reset FE and ESW cores together Failing to do so will cause the DMA engine to not initialize properly and fail to forward packets between them, and in some cases will cause spurious transmission with size exceeding allowed packet size, causing a kernel panic. Fixes: 60fadae62b64 ("ramips: ethernet: ralink: move reset of the esw into the esw instead of fe") Signed-off-by: Maxim Anisimov [Provide commit description, split into logical changes] Signed-off-by: Lech Perczak --- target/linux/ramips/dts/rt3352.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/ramips/dts/rt3352.dtsi b/target/linux/ramips/dts/rt3352.dtsi index 0ac3227ce0..b4829cb1b1 100644 --- a/target/linux/ramips/dts/rt3352.dtsi +++ b/target/linux/ramips/dts/rt3352.dtsi @@ -319,8 +319,8 @@ clocks = <&sysc 12>; - resets = <&sysc 21>; - reset-names = "fe"; + resets = <&sysc 21>, <&sysc 23>; + reset-names = "fe", "esw"; interrupt-parent = <&cpuintc>; interrupts = <5>; @@ -332,8 +332,8 @@ compatible = "ralink,rt3352-esw", "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>, <&sysc 24>; - reset-names = "esw", "ephy"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; From c5a399f372535886582f89f3da624ae7465c8ff4 Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Tue, 12 Dec 2023 00:22:04 +0100 Subject: [PATCH 008/222] ramips: dts: rt3050: reset FE and ESW cores together Failing to do so will cause the DMA engine to not initialize properly and fail to forward packets between them, and in some cases will cause spurious transmission with size exceeding allowed packet size, causing a kernel panic. This is behaviour of downstream driver as well, however I haven't observed bug reports about this SoC in the wild, so this commit's purpose is to align this chip with all other SoC's - MT7620 were already using this arrangement. Fixes: 60fadae62b64 ("ramips: ethernet: ralink: move reset of the esw into the esw instead of fe") Signed-off-by: Lech Perczak --- target/linux/ramips/dts/rt3050.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/ramips/dts/rt3050.dtsi b/target/linux/ramips/dts/rt3050.dtsi index 4d70773ed1..d23303964f 100644 --- a/target/linux/ramips/dts/rt3050.dtsi +++ b/target/linux/ramips/dts/rt3050.dtsi @@ -301,8 +301,8 @@ clocks = <&sysc 11>; - resets = <&sysc 21>; - reset-names = "fe"; + resets = <&sysc 21>, <&sysc 23>; + reset-names = "fe", "esw"; interrupt-parent = <&cpuintc>; interrupts = <5>; @@ -314,8 +314,8 @@ compatible = "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>, <&sysc 24>; - reset-names = "esw", "ephy"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; From fc92fecfc7ddf19bbfd7d1305a29c666f00543af Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Tue, 12 Dec 2023 00:25:02 +0100 Subject: [PATCH 009/222] ramips: dts: rt5350: reset FE and ESW cores together Failing to do so will cause the DMA engine to not initialize properly and fail to forward packets between them, and in some cases will cause spurious transmission with size exceeding allowed packet size, causing a kernel panic. This is behaviour of downstream driver as well, however I haven't observed bug reports about this SoC in the wild, so this commit's purpose is to align this chip with all other SoC's - MT7620 were already using this arrangement. Fixes: #9284 Fixes: 60fadae62b64 ("ramips: ethernet: ralink: move reset of the esw into the esw instead of fe") Signed-off-by: Lech Perczak --- target/linux/ramips/dts/rt5350.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/ramips/dts/rt5350.dtsi b/target/linux/ramips/dts/rt5350.dtsi index 9bbbc611ed..30f6435842 100644 --- a/target/linux/ramips/dts/rt5350.dtsi +++ b/target/linux/ramips/dts/rt5350.dtsi @@ -340,8 +340,8 @@ clocks = <&sysc 12>; - resets = <&sysc 21>; - reset-names = "fe"; + resets = <&sysc 21>, <&sysc 23>; + reset-names = "fe", "esw"; interrupt-parent = <&cpuintc>; interrupts = <5>; @@ -353,8 +353,8 @@ compatible = "ralink,rt5350-esw", "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>, <&sysc 24>; - reset-names = "esw", "ephy"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; From f87b66507e9245e6e02dbc76e2e7b27c9e0bf364 Mon Sep 17 00:00:00 2001 From: Maxim Anisimov Date: Sun, 10 Dec 2023 16:40:39 +0100 Subject: [PATCH 010/222] ramips: dts: mt7628an: reset FE and ESW cores together Failing to do so will cause the DMA engine to not initialize properly and fail to forward packets between them, and in some cases will cause spurious transmission with size exceeding allowed packet size, causing a kernel panic. Fixes: 60fadae62b64 ("ramips: ethernet: ralink: move reset of the esw into the esw instead of fe") Signed-off-by: Maxim Anisimov [Provide commit description, split into logical changes] Signed-off-by: Lech Perczak --- target/linux/ramips/dts/mt7628an.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/ramips/dts/mt7628an.dtsi b/target/linux/ramips/dts/mt7628an.dtsi index ddc3011aab..97f77f6b38 100644 --- a/target/linux/ramips/dts/mt7628an.dtsi +++ b/target/linux/ramips/dts/mt7628an.dtsi @@ -411,8 +411,8 @@ interrupt-parent = <&cpuintc>; interrupts = <5>; - resets = <&sysc 21>; - reset-names = "fe"; + resets = <&sysc 21>, <&sysc 23>; + reset-names = "fe", "esw"; mediatek,switch = <&esw>; }; @@ -421,8 +421,8 @@ compatible = "mediatek,mt7628-esw", "ralink,rt3050-esw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>, <&sysc 24>; - reset-names = "esw", "ephy"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; From f393ffcac163926bf9dbbda47c25cc7809952609 Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Fri, 15 Dec 2023 17:25:05 +0100 Subject: [PATCH 011/222] raimps: mtk_eth_soc: drop rst_esw from ESW driver The ESW core needs to be reset together with FE core, so after the relevant reset controller lines are moved under FE, drop rst_esw and all related code, which would not execute anyway, because rst_esw would be NULL. While at that, ensure that if reset line for EPHY cannot be claimed, a proper error message is reported. Fixes: 60fadae62b64 ("ramips: ethernet: ralink: move reset of the esw into the esw instead of fe") Co-developed-by: Maxim Anisimov Signed-off-by: Maxim Anisimov [Split out of the bigger commit, provide commit mesage, refactor error handling] Signed-off-by: Lech Perczak --- .../drivers/net/ethernet/ralink/esw_rt3050.c | 24 ++++--------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c index 47471eb197..5a36652a11 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3050.c @@ -237,7 +237,6 @@ struct rt305x_esw { int led_frequency; struct esw_vlan vlans[RT305X_ESW_NUM_VLANS]; struct esw_port ports[RT305X_ESW_NUM_PORTS]; - struct reset_control *rst_esw; struct reset_control *rst_ephy; }; @@ -261,18 +260,6 @@ static inline void esw_rmw_raw(struct rt305x_esw *esw, unsigned reg, __raw_writel(t | val, esw->base + reg); } -static void esw_reset(struct rt305x_esw *esw) -{ - if (!esw->rst_esw) - return; - - reset_control_assert(esw->rst_esw); - usleep_range(60, 120); - reset_control_deassert(esw->rst_esw); - /* the esw takes long to reset otherwise the board hang */ - msleep(10); -} - static void esw_reset_ephy(struct rt305x_esw *esw) { if (!esw->rst_ephy) @@ -466,8 +453,6 @@ static void esw_hw_init(struct rt305x_esw *esw) u8 port_disable = 0; u8 port_map = RT305X_ESW_PMAP_LLLLLL; - esw_reset(esw); - /* vodoo from original driver */ esw_w32(esw, 0xC8A07850, RT305X_ESW_REG_FCT0); esw_w32(esw, 0x00000000, RT305X_ESW_REG_SGC2); @@ -1441,12 +1426,11 @@ static int esw_probe(struct platform_device *pdev) if (reg_init) esw->reg_led_source = be32_to_cpu(*reg_init); - esw->rst_esw = devm_reset_control_get(&pdev->dev, "esw"); - if (IS_ERR(esw->rst_esw)) - esw->rst_esw = NULL; - esw->rst_ephy = devm_reset_control_get(&pdev->dev, "ephy"); - if (IS_ERR(esw->rst_ephy)) + esw->rst_ephy = devm_reset_control_get_exclusive(&pdev->dev, "ephy"); + if (IS_ERR(esw->rst_ephy)) { + dev_err(esw->dev, "failed to get EPHY reset: %pe\n", esw->rst_ephy); esw->rst_ephy = NULL; + } spin_lock_init(&esw->reg_rw_lock); platform_set_drvdata(pdev, esw); From 4c1e9bd8581e01793b26f3bc964975311450ece0 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 5 Dec 2023 18:36:42 -0500 Subject: [PATCH 012/222] ramips: lzma-loader: use virtual memory segments for uart base address The native bus address for UART was entered for rt305x UART_BASE, but the bootloaders have memory space remapped with the same virtual memory map the kernel uses for program addressing at boot time. In UBoot, the remapped address is often defined as TEXT_BASE. In the kernel, for rt305x this remapped address is RT305X_SYSC_BASE. (arch/mips/include/asm/mach-ralink/rt305x.h) Because the ralink I/O busses begin at a low address of 0x10000000, they are remapped using KSEG0 or KSEG1, which for all 32-bit MIPS SOCs (arch/mips/include/asm/addrspace.h) are offsets of 0x80000000 and 0xa0000000 respectively. This is consistent with the other UART_BASE macros here and with MIPS memory map documentation. Before the recent rework of the lzma-loader for ramips, the original board-$(PLATFORM).c files also did not use KSEG1ADDR for UART_BASE despite being defined, which made this mistake easier to occur. Fix this by defining KSEG1ADDR again and actually use it. Copy and paste from the kernel's macros for consistency. Link: https://training.mips.com/basic_mips/PDF/Memory_Map.pdf Fixes: c31319b66 ("ramips: lzma-loader: Refactor loader") Reported-by: Lech Perczak Signed-off-by: Michael Pratt --- .../ramips/image/lzma-loader/src/board.c | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/target/linux/ramips/image/lzma-loader/src/board.c b/target/linux/ramips/image/lzma-loader/src/board.c index ae9da38073..050ef695f9 100644 --- a/target/linux/ramips/image/lzma-loader/src/board.c +++ b/target/linux/ramips/image/lzma-loader/src/board.c @@ -11,19 +11,33 @@ */ #include +#include + +#define KSEG0 0x80000000 +#define KSEG1 0xa0000000 + +#define _ATYPE_ __PTRDIFF_TYPE__ +#define _ATYPE32_ int + +#define _ACAST32_ (_ATYPE_)(_ATYPE32_) + +#define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff) + +#define KSEG0ADDR(a) (CPHYSADDR(a) | KSEG0) +#define KSEG1ADDR(a) (CPHYSADDR(a) | KSEG1) #if defined(SOC_MT7620) || defined(SOC_RT3883) -#define UART_BASE 0xb0000c00 +#define UART_BASE KSEG1ADDR(0x10000c00) #define UART_THR (UART_BASE + 0x04) #define UART_LSR (UART_BASE + 0x1c) #define UART_LSR_THRE_MASK 0x40 #elif defined(SOC_MT7621) -#define UART_BASE 0xbe000c00 +#define UART_BASE KSEG1ADDR(0x1e000c00) #define UART_THR (UART_BASE + 0x00) #define UART_LSR (UART_BASE + 0x14) #define UART_LSR_THRE_MASK 0x20 #elif defined(SOC_RT305X) -#define UART_BASE 0x10000500 +#define UART_BASE KSEG1ADDR(0x10000500) #define UART_THR (UART_BASE + 0x04) #define UART_LSR (UART_BASE + 0x1c) #define UART_LSR_THRE_MASK 0x20 From 2e47913c644c59aa25fbac2bc6c4297956406b82 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 6 Dec 2023 14:12:03 -0500 Subject: [PATCH 013/222] ramips: lzma-loader: use proper register names Before this was reworked, in the file for mt7621 subtarget (target/linux/ramips/image/lzma-loader/src/board-mt7621.c) the "Transmitter shift register empty" bit TEMT was used instead of the "Transmitter holding register empty" bit THRE, but after the rework, this value was labeled as the THRE bit instead. Functionally there is no difference, but this is confusing to read, as it suggests that the subtargets have different bits for the same register in UART when in reality they are exactly the same. One can use either bit, or both, at user's descretion in order to determine whether the UART TX buffer is ready. The generic kernel early-printk uses both, (arch/mips/kernel/early_printk_8250.c) while the ralink-specific early-printk uses only THRE, (arch/mips/ralink/early_printk.c). Define both bits and rewrite macros for readability, keep the same values, as changing which to use should be tested first. Ref: c31319b66 ("ramips: lzma-loader: Refactor loader") Signed-off-by: Michael Pratt --- target/linux/ramips/image/lzma-loader/src/board.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/target/linux/ramips/image/lzma-loader/src/board.c b/target/linux/ramips/image/lzma-loader/src/board.c index 050ef695f9..9f87cddec7 100644 --- a/target/linux/ramips/image/lzma-loader/src/board.c +++ b/target/linux/ramips/image/lzma-loader/src/board.c @@ -26,21 +26,24 @@ #define KSEG0ADDR(a) (CPHYSADDR(a) | KSEG0) #define KSEG1ADDR(a) (CPHYSADDR(a) | KSEG1) +#define UART_LSR_THRE 0x20 +#define UART_LSR_TEMT 0x40 + #if defined(SOC_MT7620) || defined(SOC_RT3883) #define UART_BASE KSEG1ADDR(0x10000c00) #define UART_THR (UART_BASE + 0x04) #define UART_LSR (UART_BASE + 0x1c) -#define UART_LSR_THRE_MASK 0x40 +#define UART_LSR_MASK UART_LSR_TEMT #elif defined(SOC_MT7621) #define UART_BASE KSEG1ADDR(0x1e000c00) #define UART_THR (UART_BASE + 0x00) #define UART_LSR (UART_BASE + 0x14) -#define UART_LSR_THRE_MASK 0x20 +#define UART_LSR_MASK UART_LSR_THRE #elif defined(SOC_RT305X) #define UART_BASE KSEG1ADDR(0x10000500) #define UART_THR (UART_BASE + 0x04) #define UART_LSR (UART_BASE + 0x1c) -#define UART_LSR_THRE_MASK 0x20 +#define UART_LSR_MASK UART_LSR_THRE #else #error "Unsupported SOC..." #endif @@ -56,7 +59,7 @@ void board_init(void) void board_putc(int ch) { - while ((READREG(UART_LSR) & UART_LSR_THRE_MASK) == 0); + while ((READREG(UART_LSR) & UART_LSR_MASK) == 0); WRITEREG(UART_THR, ch); - while ((READREG(UART_LSR) & UART_LSR_THRE_MASK) == 0); + while ((READREG(UART_LSR) & UART_LSR_MASK) == 0); } From bc00c78b4338779ca1b7cd08411f76218d1f3205 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 6 Dec 2023 14:29:26 -0500 Subject: [PATCH 014/222] ramips: lzma-loader: use default uart for rt305x The rt305x series SOC have two UART devices, and the one at bus address 0x500 is disabled by default. Some boards do not even have a pinout for the first one, so use the same one that the kernel uses at 0xc00 instead. This allows the lzma-loader printing to be visible alongside the kernel log in the same console. Tested-by: Lech Perczak # zte,mf283plus Signed-off-by: Michael Pratt --- target/linux/ramips/image/lzma-loader/src/board.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ramips/image/lzma-loader/src/board.c b/target/linux/ramips/image/lzma-loader/src/board.c index 9f87cddec7..de02f58b9f 100644 --- a/target/linux/ramips/image/lzma-loader/src/board.c +++ b/target/linux/ramips/image/lzma-loader/src/board.c @@ -40,7 +40,7 @@ #define UART_LSR (UART_BASE + 0x14) #define UART_LSR_MASK UART_LSR_THRE #elif defined(SOC_RT305X) -#define UART_BASE KSEG1ADDR(0x10000500) +#define UART_BASE KSEG1ADDR(0x10000c00) #define UART_THR (UART_BASE + 0x04) #define UART_LSR (UART_BASE + 0x1c) #define UART_LSR_MASK UART_LSR_THRE From 443e3bd1c6e61aa39f4fc176b22ad2d75f33bcb4 Mon Sep 17 00:00:00 2001 From: David Bentham Date: Mon, 25 Dec 2023 11:51:16 +0000 Subject: [PATCH 015/222] ramips: unielec-u7621-01: Increase SPI frequency to 50MHz Flash: 16MB SPI NOR flash (Macronix MX25L12805D) Based on the manufactured datasheet this chip is capable of 50MHz. We dont enable fast-read as mt7621 are only capable of 44mhz in a read state. Tested on this unit without any issues. Signed-off-by: David Bentham --- target/linux/ramips/dts/mt7621_unielec_u7621-01-16m.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ramips/dts/mt7621_unielec_u7621-01-16m.dts b/target/linux/ramips/dts/mt7621_unielec_u7621-01-16m.dts index c933e443c1..d6189f3d58 100644 --- a/target/linux/ramips/dts/mt7621_unielec_u7621-01-16m.dts +++ b/target/linux/ramips/dts/mt7621_unielec_u7621-01-16m.dts @@ -13,7 +13,7 @@ flash@0 { compatible = "jedec,spi-nor"; reg = <0>; - spi-max-frequency = <14000000>; + spi-max-frequency = <50000000>; partitions { compatible = "fixed-partitions"; From 7ddd3abd278e6105fb00794fe0d3b2c25f969c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Wed, 3 Jan 2024 07:54:46 +0000 Subject: [PATCH 016/222] ipq807x: cax1800: fix blsp1_spi1 status with okay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ok` status is obsolete and thus `okay` should be used instead: spi@78b9000: status:0: 'ok' is not one of ['okay', 'disabled', 'reserved'] Signed-off-by: Petr Štetiar --- .../files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts index 622b8662fa..0ca2edcb2c 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8070-cax1800.dts @@ -123,7 +123,7 @@ pinctrl-0 = <&spi_0_pins>; pinctrl-names = "default"; cs-select = <0>; - status = "ok"; + status = "okay"; m25p80@0 { #address-cells = <1>; From 0f1b3d5c02cc249437192d48be69f6628d7de4f4 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 4 Jan 2024 12:30:19 +0100 Subject: [PATCH 017/222] netifd: update to Git HEAD (2024-01-04) 4219e99eeec7 system-linux: fix race condition in netlink socket error handing f01345ec13b9 device: restore cleared flags on device down Signed-off-by: Felix Fietkau --- package/network/config/netifd/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile index 790bcfec63..558463e8ea 100644 --- a/package/network/config/netifd/Makefile +++ b/package/network/config/netifd/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git -PKG_SOURCE_DATE:=2023-12-19 -PKG_SOURCE_VERSION:=a2d32f0dcf16880226680d07b07b249f77a3af58 -PKG_MIRROR_HASH:=765f51335ffa0a143421efbe129d484a90d7c4a0f3e08cb7840cc85408f3e60c +PKG_SOURCE_DATE:=2024-01-04 +PKG_SOURCE_VERSION:=f01345ec13b9b27ffd314d8689fb2d3f9c81a47d +PKG_MIRROR_HASH:=58e92e9ce1a2c8ccb487e95dadf806f38b38abbe7cb3cde61ff880de5eb85c2f PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 From 08ad3c963377ee853f87935929d33f19e5e34ef9 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Thu, 4 Jan 2024 00:30:57 +0100 Subject: [PATCH 018/222] libxml2: update to 2.12.3 Release Notes: - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.12.2 - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.12.3 Signed-off-by: Nick Hainke --- package/libs/libxml2/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/libs/libxml2/Makefile b/package/libs/libxml2/Makefile index d65085c9c1..9e70a0bd0a 100644 --- a/package/libs/libxml2/Makefile +++ b/package/libs/libxml2/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libxml2 -PKG_VERSION:=2.12.1 +PKG_VERSION:=2.12.3 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@GNOME/libxml2/$(basename $(PKG_VERSION)) -PKG_HASH:=8982b9ccdf7f456e30d8f7012d50858c6623e495333b6191def455c7e95427eb +PKG_HASH:=8c8f1092340a89ff32bc44ad5c9693aff9bc8a7a3e161bb239666e5d15ac9aaa PKG_LICENSE:=MIT PKG_LICENSE_FILES:=COPYING From adf91335472f786c9d49911865a2a2bdfd523e7b Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Thu, 4 Jan 2024 00:44:45 +0100 Subject: [PATCH 019/222] libnl: update to 3.9.0 Changes: bdf83151 libnl-3.9.0 release aa7353fd include/linux-private: import 'seg6 local' headers from kernel tree 9466f680 lib: remove unused assignment in nl_addr_parse() acd05d6e route/tc: avoid integer overflow in rtnl_tc_calc_cell_log() daa8efcb xfrm: return -NLE_MISSING_ATTR from xfrmnl_sa_get_auth_params() d8a1ff30 xfrm: fix leaking usertemplate in xfrmnl_sp_parse() 4fcb0757 socket: workaround coverity warning about time_t handling f743c62f github: update Fedora image and version for clang-format f33e8cd6 clang-format: rework container script aea3f9f2 lib: fix signed overflow warning in nl_object_diff() 57e01706 socket: explicitly cast time() to uint32_t 46e8739e src: fix leak in "nl-cls-add" a06c8f76 route/cls: add get/take wrappers for rtnl_act_append() 7912b4f9 route/cls: fix leak in error handling of rtnl_flower_append_action() efd65feb route: fix just introduced use-after-free in rtnl_act_parse() 105a6be1 route: use cleanup macro in rtnl_act_parse() 78246da7 nl-aux-route: add cleanup macro for rtnl_act_put_all() 72762b20 base: add _NL_AUTO_DEFINE_FCN_INDIRECT0() macro a70f789a route: fix memleak in rtnl_act_parse() 65ab16f2 base: don't use static array indices for buffer argument of _nl_inet_ntop() 444e2c04 route/can: implement can_device_stats a4718e67 github: build with "-fexceptions" CFLAGS 2f485cc7 xfrm: refactor error handling in XFRM parsing 01bd8fb0 include: add "nl-aux-xfrm" helpers 49c20efa xfrm: fix crashes in case of ENOMEM 9e7b5c86 xfrm: refactor nl_addr_build() calls in XFRM code dbfd87b1 xfrm: use cleanup attribute for nl_addr in XFRM parsing db424835 xfrm: fix error code for NLE_ENOMEM in xfrmnl_ae_parse() 9c97deff xfrm: fix parsing address in xfrmnl_ae_parse() 8b6dc834 nl-aux-core: add _nl_addr_build() helper 057aac13 nl-base-utils: add _nl_addr_family_to_size() helper 664f8f1b xfrm: clear XFRM_SP_ATTR_TMPL when removing the last template from a policy c4c22d26 xfrm/sp: fix reference counters of sa selector/tmpl addresses 5979fcb0 route/link: add bonding interface options set rtnl apis a735989c build: fix declaring special targets as ".PHONY" 052a97cb Makefile.am: avoid use of non-portable echo arguments 9aab12df python: Use correct decorator syntax in HTBQdisc Signed-off-by: Nick Hainke --- package/libs/libnl/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/libs/libnl/Makefile b/package/libs/libnl/Makefile index 56f2c2825d..93817e5f40 100644 --- a/package/libs/libnl/Makefile +++ b/package/libs/libnl/Makefile @@ -6,12 +6,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libnl -PKG_VERSION:=3.8.0 +PKG_VERSION:=3.9.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/thom311/libnl/releases/download/libnl$(subst .,_,$(PKG_VERSION)) -PKG_HASH:=bb726c6d7a08b121978d73ff98425bf313fa26a27a331d465e4f1d7ec5b838c6 +PKG_HASH:=aed507004d728a5cf11eab48ca4bf9e6e1874444e33939b9d3dfed25018ee9bb PKG_LICENSE:=LGPL-2.1 PKG_LICENSE_FILES:=COPYING From 438a97fab69b41387e25cbec45271e7fe159a330 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 3 Jan 2024 15:13:32 +0100 Subject: [PATCH 020/222] mac80211: fix a race condition related to enabling fast-xmit fast-xmit must only be enabled after the sta has been uploaded to the driver, otherwise it could end up passing the not-yet-uploaded sta via drv_tx calls to the driver, leading to potential crashes because of uninitialized drv_priv data. Add a missing sta->uploaded check and re-check fast xmit after inserting a sta. Signed-off-by: Felix Fietkau --- ...x-race-condition-on-enabling-fast-xm.patch | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 package/kernel/mac80211/patches/subsys/314-wifi-mac80211-fix-race-condition-on-enabling-fast-xm.patch diff --git a/package/kernel/mac80211/patches/subsys/314-wifi-mac80211-fix-race-condition-on-enabling-fast-xm.patch b/package/kernel/mac80211/patches/subsys/314-wifi-mac80211-fix-race-condition-on-enabling-fast-xm.patch new file mode 100644 index 0000000000..191eb67e8e --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/314-wifi-mac80211-fix-race-condition-on-enabling-fast-xm.patch @@ -0,0 +1,34 @@ +From: Felix Fietkau +Date: Wed, 3 Jan 2024 15:10:18 +0100 +Subject: [PATCH] wifi: mac80211: fix race condition on enabling fast-xmit + +fast-xmit must only be enabled after the sta has been uploaded to the driver, +otherwise it could end up passing the not-yet-uploaded sta via drv_tx calls +to the driver, leading to potential crashes because of uninitialized drv_priv +data. +Add a missing sta->uploaded check and re-check fast xmit after inserting a sta. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -911,6 +911,7 @@ static int sta_info_insert_finish(struct + + if (ieee80211_vif_is_mesh(&sdata->vif)) + mesh_accept_plinks_update(sdata); ++ ieee80211_check_fast_xmit(sta); + + return 0; + out_remove: +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3033,7 +3033,7 @@ void ieee80211_check_fast_xmit(struct st + sdata->vif.type == NL80211_IFTYPE_STATION) + goto out; + +- if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED)) ++ if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED) || !sta->uploaded) + goto out; + + if (test_sta_flag(sta, WLAN_STA_PS_STA) || From 3645ac8a10d9abb1451343beaf7d65b53eeecffd Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Mon, 25 Dec 2023 11:23:58 +0800 Subject: [PATCH 021/222] rockchip: configure eth pad driver strength for orangepi r1 plus lts The default strength is not enough to provide stable connection under 3.3v LDO voltage. Fixes: 32d5921b8b55 ("rockchip: add Orange Pi R1 Plus LTS support") Fixes: #13117 Fixes: #13759 Signed-off-by: Tianling Shen --- ...m-Add-pad-drive-strength-cfg-support.patch | 170 ++++++++++++++++++ ...m-Add-pad-drive-strength-cfg-support.patch | 170 ++++++++++++++++++ ...nfigure-eth-pad-driver-strength-for-.patch | 33 ++++ 3 files changed, 373 insertions(+) create mode 100644 target/linux/generic/backport-5.15/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch create mode 100644 target/linux/generic/backport-6.1/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch create mode 100644 target/linux/rockchip/patches-6.1/015-v6.8-arm64-dts-rockchip-configure-eth-pad-driver-strength-for-.patch diff --git a/target/linux/generic/backport-5.15/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch b/target/linux/generic/backport-5.15/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch new file mode 100644 index 0000000000..010ca9b68a --- /dev/null +++ b/target/linux/generic/backport-5.15/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch @@ -0,0 +1,170 @@ +From 7a561e9351ae7e3fb1f08584d40b49c1e55dde60 Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Thu, 20 Jul 2023 19:15:09 +0800 +Subject: [PATCH] net: phy: motorcomm: Add pad drive strength cfg support + +The motorcomm phy (YT8531) supports the ability to adjust the drive +strength of the rx_clk/rx_data, and the default strength may not be +suitable for all boards. So add configurable options to better match +the boards.(e.g. StarFive VisionFive 2) + +When we configure the drive strength, we need to read the current +LDO voltage value to ensure that it is a legal value at that LDO +voltage. + +Reviewed-by: Hal Feng +Signed-off-by: Samin Guo +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/motorcomm.c | 118 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 118 insertions(+) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -163,6 +163,10 @@ + + #define YT8521_CHIP_CONFIG_REG 0xA001 + #define YT8521_CCR_SW_RST BIT(15) ++#define YT8531_RGMII_LDO_VOL_MASK GENMASK(5, 4) ++#define YT8531_LDO_VOL_3V3 0x0 ++#define YT8531_LDO_VOL_1V8 0x2 ++ + /* 1b0 disable 1.9ns rxc clock delay *default* + * 1b1 enable 1.9ns rxc clock delay + */ +@@ -236,6 +240,12 @@ + */ + #define YTPHY_WCR_TYPE_PULSE BIT(0) + ++#define YTPHY_PAD_DRIVE_STRENGTH_REG 0xA010 ++#define YT8531_RGMII_RXC_DS_MASK GENMASK(15, 13) ++#define YT8531_RGMII_RXD_DS_HI_MASK BIT(12) /* Bit 2 of rxd_ds */ ++#define YT8531_RGMII_RXD_DS_LOW_MASK GENMASK(5, 4) /* Bit 1/0 of rxd_ds */ ++#define YT8531_RGMII_RX_DS_DEFAULT 0x3 ++ + #define YTPHY_SYNCE_CFG_REG 0xA012 + #define YT8521_SCR_SYNCE_ENABLE BIT(5) + /* 1b0 output 25m clock +@@ -835,6 +845,110 @@ static int ytphy_rgmii_clk_delay_config_ + } + + /** ++ * struct ytphy_ldo_vol_map - map a current value to a register value ++ * @vol: ldo voltage ++ * @ds: value in the register ++ * @cur: value in device configuration ++ */ ++struct ytphy_ldo_vol_map { ++ u32 vol; ++ u32 ds; ++ u32 cur; ++}; ++ ++static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = { ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 0, .cur = 1200}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 1, .cur = 2100}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 2, .cur = 2700}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 3, .cur = 2910}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 4, .cur = 3110}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 5, .cur = 3600}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 6, .cur = 3970}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 7, .cur = 4350}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 0, .cur = 3070}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 1, .cur = 4080}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 2, .cur = 4370}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 3, .cur = 4680}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 4, .cur = 5020}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 5, .cur = 5450}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 6, .cur = 5740}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 7, .cur = 6140}, ++}; ++ ++static u32 yt8531_get_ldo_vol(struct phy_device *phydev) ++{ ++ u32 val; ++ ++ val = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); ++ val = FIELD_GET(YT8531_RGMII_LDO_VOL_MASK, val); ++ ++ return val <= YT8531_LDO_VOL_1V8 ? val : YT8531_LDO_VOL_1V8; ++} ++ ++static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur) ++{ ++ u32 vol; ++ int i; ++ ++ vol = yt8531_get_ldo_vol(phydev); ++ for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) { ++ if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur) ++ return yt8531_ldo_vol[i].ds; ++ } ++ ++ return -EINVAL; ++} ++ ++static int yt8531_set_ds(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ u32 ds_field_low, ds_field_hi, val; ++ int ret, ds; ++ ++ /* set rgmii rx clk driver strength */ ++ if (!of_property_read_u32(node, "motorcomm,rx-clk-drv-microamp", &val)) { ++ ds = yt8531_get_ds_map(phydev, val); ++ if (ds < 0) ++ return dev_err_probe(&phydev->mdio.dev, ds, ++ "No matching current value was found.\n"); ++ } else { ++ ds = YT8531_RGMII_RX_DS_DEFAULT; ++ } ++ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YTPHY_PAD_DRIVE_STRENGTH_REG, ++ YT8531_RGMII_RXC_DS_MASK, ++ FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds)); ++ if (ret < 0) ++ return ret; ++ ++ /* set rgmii rx data driver strength */ ++ if (!of_property_read_u32(node, "motorcomm,rx-data-drv-microamp", &val)) { ++ ds = yt8531_get_ds_map(phydev, val); ++ if (ds < 0) ++ return dev_err_probe(&phydev->mdio.dev, ds, ++ "No matching current value was found.\n"); ++ } else { ++ ds = YT8531_RGMII_RX_DS_DEFAULT; ++ } ++ ++ ds_field_hi = FIELD_GET(BIT(2), ds); ++ ds_field_hi = FIELD_PREP(YT8531_RGMII_RXD_DS_HI_MASK, ds_field_hi); ++ ++ ds_field_low = FIELD_GET(GENMASK(1, 0), ds); ++ ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low); ++ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YTPHY_PAD_DRIVE_STRENGTH_REG, ++ YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK, ++ ds_field_low | ds_field_hi); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++/** + * yt8521_probe() - read chip config then set suitable polling_mode + * @phydev: a pointer to a &struct phy_device + * +@@ -1518,6 +1632,10 @@ static int yt8531_config_init(struct phy + return ret; + } + ++ ret = yt8531_set_ds(phydev); ++ if (ret < 0) ++ return ret; ++ + return 0; + } + diff --git a/target/linux/generic/backport-6.1/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch b/target/linux/generic/backport-6.1/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch new file mode 100644 index 0000000000..010ca9b68a --- /dev/null +++ b/target/linux/generic/backport-6.1/791-v6.6-11-net-phy-motorcomm-Add-pad-drive-strength-cfg-support.patch @@ -0,0 +1,170 @@ +From 7a561e9351ae7e3fb1f08584d40b49c1e55dde60 Mon Sep 17 00:00:00 2001 +From: Samin Guo +Date: Thu, 20 Jul 2023 19:15:09 +0800 +Subject: [PATCH] net: phy: motorcomm: Add pad drive strength cfg support + +The motorcomm phy (YT8531) supports the ability to adjust the drive +strength of the rx_clk/rx_data, and the default strength may not be +suitable for all boards. So add configurable options to better match +the boards.(e.g. StarFive VisionFive 2) + +When we configure the drive strength, we need to read the current +LDO voltage value to ensure that it is a legal value at that LDO +voltage. + +Reviewed-by: Hal Feng +Signed-off-by: Samin Guo +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/motorcomm.c | 118 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 118 insertions(+) + +--- a/drivers/net/phy/motorcomm.c ++++ b/drivers/net/phy/motorcomm.c +@@ -163,6 +163,10 @@ + + #define YT8521_CHIP_CONFIG_REG 0xA001 + #define YT8521_CCR_SW_RST BIT(15) ++#define YT8531_RGMII_LDO_VOL_MASK GENMASK(5, 4) ++#define YT8531_LDO_VOL_3V3 0x0 ++#define YT8531_LDO_VOL_1V8 0x2 ++ + /* 1b0 disable 1.9ns rxc clock delay *default* + * 1b1 enable 1.9ns rxc clock delay + */ +@@ -236,6 +240,12 @@ + */ + #define YTPHY_WCR_TYPE_PULSE BIT(0) + ++#define YTPHY_PAD_DRIVE_STRENGTH_REG 0xA010 ++#define YT8531_RGMII_RXC_DS_MASK GENMASK(15, 13) ++#define YT8531_RGMII_RXD_DS_HI_MASK BIT(12) /* Bit 2 of rxd_ds */ ++#define YT8531_RGMII_RXD_DS_LOW_MASK GENMASK(5, 4) /* Bit 1/0 of rxd_ds */ ++#define YT8531_RGMII_RX_DS_DEFAULT 0x3 ++ + #define YTPHY_SYNCE_CFG_REG 0xA012 + #define YT8521_SCR_SYNCE_ENABLE BIT(5) + /* 1b0 output 25m clock +@@ -835,6 +845,110 @@ static int ytphy_rgmii_clk_delay_config_ + } + + /** ++ * struct ytphy_ldo_vol_map - map a current value to a register value ++ * @vol: ldo voltage ++ * @ds: value in the register ++ * @cur: value in device configuration ++ */ ++struct ytphy_ldo_vol_map { ++ u32 vol; ++ u32 ds; ++ u32 cur; ++}; ++ ++static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = { ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 0, .cur = 1200}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 1, .cur = 2100}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 2, .cur = 2700}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 3, .cur = 2910}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 4, .cur = 3110}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 5, .cur = 3600}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 6, .cur = 3970}, ++ {.vol = YT8531_LDO_VOL_1V8, .ds = 7, .cur = 4350}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 0, .cur = 3070}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 1, .cur = 4080}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 2, .cur = 4370}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 3, .cur = 4680}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 4, .cur = 5020}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 5, .cur = 5450}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 6, .cur = 5740}, ++ {.vol = YT8531_LDO_VOL_3V3, .ds = 7, .cur = 6140}, ++}; ++ ++static u32 yt8531_get_ldo_vol(struct phy_device *phydev) ++{ ++ u32 val; ++ ++ val = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); ++ val = FIELD_GET(YT8531_RGMII_LDO_VOL_MASK, val); ++ ++ return val <= YT8531_LDO_VOL_1V8 ? val : YT8531_LDO_VOL_1V8; ++} ++ ++static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur) ++{ ++ u32 vol; ++ int i; ++ ++ vol = yt8531_get_ldo_vol(phydev); ++ for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) { ++ if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur) ++ return yt8531_ldo_vol[i].ds; ++ } ++ ++ return -EINVAL; ++} ++ ++static int yt8531_set_ds(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ u32 ds_field_low, ds_field_hi, val; ++ int ret, ds; ++ ++ /* set rgmii rx clk driver strength */ ++ if (!of_property_read_u32(node, "motorcomm,rx-clk-drv-microamp", &val)) { ++ ds = yt8531_get_ds_map(phydev, val); ++ if (ds < 0) ++ return dev_err_probe(&phydev->mdio.dev, ds, ++ "No matching current value was found.\n"); ++ } else { ++ ds = YT8531_RGMII_RX_DS_DEFAULT; ++ } ++ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YTPHY_PAD_DRIVE_STRENGTH_REG, ++ YT8531_RGMII_RXC_DS_MASK, ++ FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds)); ++ if (ret < 0) ++ return ret; ++ ++ /* set rgmii rx data driver strength */ ++ if (!of_property_read_u32(node, "motorcomm,rx-data-drv-microamp", &val)) { ++ ds = yt8531_get_ds_map(phydev, val); ++ if (ds < 0) ++ return dev_err_probe(&phydev->mdio.dev, ds, ++ "No matching current value was found.\n"); ++ } else { ++ ds = YT8531_RGMII_RX_DS_DEFAULT; ++ } ++ ++ ds_field_hi = FIELD_GET(BIT(2), ds); ++ ds_field_hi = FIELD_PREP(YT8531_RGMII_RXD_DS_HI_MASK, ds_field_hi); ++ ++ ds_field_low = FIELD_GET(GENMASK(1, 0), ds); ++ ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low); ++ ++ ret = ytphy_modify_ext_with_lock(phydev, ++ YTPHY_PAD_DRIVE_STRENGTH_REG, ++ YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK, ++ ds_field_low | ds_field_hi); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++/** + * yt8521_probe() - read chip config then set suitable polling_mode + * @phydev: a pointer to a &struct phy_device + * +@@ -1518,6 +1632,10 @@ static int yt8531_config_init(struct phy + return ret; + } + ++ ret = yt8531_set_ds(phydev); ++ if (ret < 0) ++ return ret; ++ + return 0; + } + diff --git a/target/linux/rockchip/patches-6.1/015-v6.8-arm64-dts-rockchip-configure-eth-pad-driver-strength-for-.patch b/target/linux/rockchip/patches-6.1/015-v6.8-arm64-dts-rockchip-configure-eth-pad-driver-strength-for-.patch new file mode 100644 index 0000000000..01efaa3a9d --- /dev/null +++ b/target/linux/rockchip/patches-6.1/015-v6.8-arm64-dts-rockchip-configure-eth-pad-driver-strength-for-.patch @@ -0,0 +1,33 @@ +From fc5a80a432607d05e85bba37971712405f75c546 Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Sat, 16 Dec 2023 12:07:23 +0800 +Subject: [PATCH] arm64: dts: rockchip: configure eth pad driver strength + for orangepi r1 plus lts + +The default strength is not enough to provide stable connection +under 3.3v LDO voltage. + +Fixes: 387b3bbac5ea ("arm64: dts: rockchip: Add Xunlong OrangePi R1 Plus LTS") +Cc: stable@vger.kernel.org # 6.6+ +Signed-off-by: Tianling Shen +Link: https://lore.kernel.org/r/20231216040723.17864-1-cnsztl@gmail.com +Signed-off-by: Heiko Stuebner +--- + arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus-lts.dts +@@ -26,9 +26,11 @@ + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + ++ motorcomm,auto-sleep-disabled; + motorcomm,clk-out-frequency-hz = <125000000>; + motorcomm,keep-pll-enabled; +- motorcomm,auto-sleep-disabled; ++ motorcomm,rx-clk-drv-microamp = <5020>; ++ motorcomm,rx-data-drv-microamp = <5020>; + + pinctrl-0 = <ð_phy_reset_pin>; + pinctrl-names = "default"; From 5067863d67e4585f166133e1b9d6e482fde4c80f Mon Sep 17 00:00:00 2001 From: John Audia Date: Wed, 27 Dec 2023 04:49:23 -0500 Subject: [PATCH 022/222] linux/modules: remove deprecated module Remove upstream deprecated module from our build, see[1] 1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit?h=v5.15.145&id=6cd90c01b032f335d18966b2d979eef43eb2cfc1 Suggested-by: Shiji Yang Signed-off-by: John Audia --- package/kernel/linux/modules/fs.mk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package/kernel/linux/modules/fs.mk b/package/kernel/linux/modules/fs.mk index f2acaa7439..58af180c28 100644 --- a/package/kernel/linux/modules/fs.mk +++ b/package/kernel/linux/modules/fs.mk @@ -359,8 +359,7 @@ define KernelPackage/fs-ksmbd DEPENDS:= \ +kmod-nls-base \ +kmod-nls-utf8 \ - +kmod-crypto-md4 \ - +kmod-crypto-md5 \ + +kmod-crypto-md5 \ +kmod-crypto-hmac \ +kmod-crypto-ecb \ +kmod-crypto-des \ From 500931c0ce016f73f2c4408ae33a2b07d266aaf9 Mon Sep 17 00:00:00 2001 From: John Audia Date: Wed, 27 Dec 2023 04:42:41 -0500 Subject: [PATCH 023/222] kernel/ksmbd: fix build for 5.15.145 Include a patch[1] under review to fix the modpost error due to upstream changes: ... ERROR: modpost: "cifs_arc4_crypt" [fs/ksmbd/ksmbd.ko] undefined! ERROR: modpost: "cifs_arc4_setkey" [fs/ksmbd/ksmbd.ko] undefined! scripts/Makefile.modpost:133: recipe for target 'modules-only.symvers' failed 1. https://lore.kernel.org/all/20231227102605.4766-2-linkinjeon@kernel.org/ Signed-off-by: John Audia --- ...ksmbd-have-a-dependency-on-cifs-arc4.patch | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 target/linux/generic/hack-5.15/940-ksmbd-have-a-dependency-on-cifs-arc4.patch diff --git a/target/linux/generic/hack-5.15/940-ksmbd-have-a-dependency-on-cifs-arc4.patch b/target/linux/generic/hack-5.15/940-ksmbd-have-a-dependency-on-cifs-arc4.patch new file mode 100644 index 0000000000..4cf420a859 --- /dev/null +++ b/target/linux/generic/hack-5.15/940-ksmbd-have-a-dependency-on-cifs-arc4.patch @@ -0,0 +1,31 @@ +From: Namjae Jeon +To: sashal@kernel.org, gregkh@linuxfoundation.org, stable@vger.kernel.org +Cc: smfrench@gmail.com, Namjae Jeon +Subject: [PATCH v2 5.15.y 1/8] ksmbd: have a dependency on cifs ARC4 +Date: Wed, 27 Dec 2023 19:25:58 +0900 [thread overview] +Message-ID: <20231227102605.4766-2-linkinjeon@kernel.org> (raw) +In-Reply-To: <20231227102605.4766-1-linkinjeon@kernel.org> + +Omitted the change that has a dependency on cifs ARC4 from backporting +commit f9929ef6a2a5("ksmbd: add support for key exchange"). +This patch make ksmbd have a dependeny on cifs ARC4. + +Fixes: c5049d2d73b2 ("ksmbd: add support for key exchange") +Signed-off-by: Namjae Jeon +--- + fs/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -369,8 +369,8 @@ source "fs/ksmbd/Kconfig" + + config SMBFS_COMMON + tristate +- default y if CIFS=y +- default m if CIFS=m ++ default y if CIFS=y || SMB_SERVER=y ++ default m if CIFS=m || SMB_SERVER=m + + source "fs/coda/Kconfig" + source "fs/afs/Kconfig" From 309c2cd4fbd2876a144bb4423428363f36c67a3f Mon Sep 17 00:00:00 2001 From: Hannu Nyman Date: Sun, 10 Dec 2023 00:04:49 +0200 Subject: [PATCH 024/222] mpfr: import from packages feed Import mpfr from the packages feed to the main OpenWrt repo, as gdb 14 requires mpfr. Signed-off-by: Hannu Nyman --- package/libs/mpfr/Makefile | 64 ++++++++++++++++++++ package/libs/mpfr/patches/001-only-src.patch | 22 +++++++ 2 files changed, 86 insertions(+) create mode 100644 package/libs/mpfr/Makefile create mode 100644 package/libs/mpfr/patches/001-only-src.patch diff --git a/package/libs/mpfr/Makefile b/package/libs/mpfr/Makefile new file mode 100644 index 0000000000..39d6a035ab --- /dev/null +++ b/package/libs/mpfr/Makefile @@ -0,0 +1,64 @@ +# +# Copyright (C) 2023 Jeffery To +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=mpfr +PKG_VERSION:=4.2.1 +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=@GNU/mpfr http://www.mpfr.org/mpfr-$(PKG_VERSION) +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_HASH:=277807353a6726978996945af13e52829e3abd7a9a5b7fb2793894e18f1fcbb2 + +PKG_LICENSE:=LGPL-3.0-or-later +PKG_LICENSE_FILES:=COPYING.LESSER +PKG_MAINTAINER:=Jeffery To +PKG_CPE_ID:=cpe:/a:mpfr:gnu_mpfr + +PKG_BUILD_PARALLEL:=1 +PKG_FIXUP:=autoreconf +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/libmpfr + SECTION:=libs + CATEGORY:=Libraries + TITLE:=GNU MPFR library + URL:=https://www.mpfr.org/ + DEPENDS:=+libgmp + ABI_VERSION:=6 +endef + +define Package/libmpfr/description +MPFR is a portable library written in C for arbitrary precision +arithmetic on floating-point numbers. It is based on the GNU MP library. +It aims to provide a class of floating-point numbers with precise +semantics. +endef + +CONFIGURE_ARGS += \ + --enable-thread-safe + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/mpf* $(1)/usr/include/ + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmpfr.{a,so*} $(1)/usr/lib/ + + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/mpfr.pc $(1)/usr/lib/pkgconfig/ +endef + +define Package/libmpfr/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libmpfr.so.* $(1)/usr/lib/ +endef + +$(eval $(call BuildPackage,libmpfr)) diff --git a/package/libs/mpfr/patches/001-only-src.patch b/package/libs/mpfr/patches/001-only-src.patch new file mode 100644 index 0000000000..bd9e38aefb --- /dev/null +++ b/package/libs/mpfr/patches/001-only-src.patch @@ -0,0 +1,22 @@ +--- a/Makefile.am ++++ b/Makefile.am +@@ -38,7 +38,7 @@ AUTOMAKE_OPTIONS = gnu + # old Automake version. + ACLOCAL_AMFLAGS = -I m4 + +-SUBDIRS = doc src tests tune tools/bench ++SUBDIRS = src + + pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = mpfr.pc +--- a/Makefile.in ++++ b/Makefile.in +@@ -401,7 +401,7 @@ AUTOMAKE_OPTIONS = gnu + # libtoolize and in case some developer needs to switch back to an + # old Automake version. + ACLOCAL_AMFLAGS = -I m4 +-SUBDIRS = doc src tests tune tools/bench ++SUBDIRS = src + pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = mpfr.pc + nobase_dist_doc_DATA = AUTHORS BUGS COPYING COPYING.LESSER NEWS TODO \ From 4a5d1d0e95d6ec6ac9c9418af9d93a0ad2e7c100 Mon Sep 17 00:00:00 2001 From: Hannu Nyman Date: Sun, 10 Dec 2023 00:08:15 +0200 Subject: [PATCH 025/222] devel/gdb: Update to 14.1 Update the gdb package to 14.1 * mpfr is now required, remove the 'without' and add dependency * remove mpc 'without' that is parsed wrongly, causing "-Lno/lib" * refresh patches Signed-off-by: Hannu Nyman --- package/devel/gdb/Makefile | 10 ++++------ package/devel/gdb/patches/110-shared_libgcc.patch | 12 ++++++------ package/devel/gdb/patches/130-gdb-ctrl-c.patch | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/package/devel/gdb/Makefile b/package/devel/gdb/Makefile index 3efbce28f4..cf897b79f2 100644 --- a/package/devel/gdb/Makefile +++ b/package/devel/gdb/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gdb -PKG_VERSION:=13.2 -PKG_RELEASE:=2 +PKG_VERSION:=14.1 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@GNU/gdb -PKG_HASH:=fd5bebb7be1833abdb6e023c2f498a354498281df9d05523d8915babeb893f0a +PKG_HASH:=d66df51276143451fcbff464cc8723d68f1e9df45a6a2d5635a54e71643edb80 PKG_BUILD_PARALLEL:=1 PKG_INSTALL:=1 @@ -33,7 +33,7 @@ endef define Package/gdb $(call Package/gdb/Default) TITLE:=GNU Debugger - DEPENDS+=+libreadline +libncurses +zlib +libgmp + DEPENDS+=+libreadline +libncurses +zlib +libgmp +libmpfr endef define Package/gdb/description @@ -64,8 +64,6 @@ CONFIGURE_ARGS+= \ --disable-sim \ --disable-werror \ --disable-source-highlight \ - --without-mpc \ - --without-mpfr \ --without-isl \ --without-xxhash \ --with-libgmp-prefix=$(STAGING_DIR)/usr diff --git a/package/devel/gdb/patches/110-shared_libgcc.patch b/package/devel/gdb/patches/110-shared_libgcc.patch index 44d4ffa77f..1a02ad1160 100644 --- a/package/devel/gdb/patches/110-shared_libgcc.patch +++ b/package/devel/gdb/patches/110-shared_libgcc.patch @@ -1,6 +1,6 @@ --- a/configure.ac +++ b/configure.ac -@@ -1435,13 +1435,13 @@ if test -z "$LD"; then +@@ -1400,13 +1400,13 @@ if test -z "$LD"; then fi fi @@ -17,7 +17,7 @@ AC_LANG_PUSH(C++) AC_LINK_IFELSE([AC_LANG_SOURCE([ #if (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 5) -@@ -1838,7 +1838,7 @@ AC_ARG_WITH(stage1-ldflags, +@@ -1836,7 +1836,7 @@ AC_ARG_WITH(stage1-ldflags, # trust that they are doing what they want. if test "$with_static_standard_libraries" = yes -a "$stage1_libs" = "" \ -a "$have_static_libs" = yes; then @@ -26,7 +26,7 @@ fi]) AC_SUBST(stage1_ldflags) -@@ -1867,7 +1867,7 @@ AC_ARG_WITH(boot-ldflags, +@@ -1865,7 +1865,7 @@ AC_ARG_WITH(boot-ldflags, # statically. But if the user explicitly specified the libraries to # use, trust that they are doing what they want. if test "$poststage1_libs" = ""; then @@ -37,7 +37,7 @@ --- a/configure +++ b/configure -@@ -5442,14 +5442,14 @@ if test -z "$LD"; then +@@ -5413,14 +5413,14 @@ if test -z "$LD"; then fi fi @@ -56,7 +56,7 @@ ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -@@ -8440,7 +8440,7 @@ else +@@ -8464,7 +8464,7 @@ else # trust that they are doing what they want. if test "$with_static_standard_libraries" = yes -a "$stage1_libs" = "" \ -a "$have_static_libs" = yes; then @@ -65,7 +65,7 @@ fi fi -@@ -8476,7 +8476,7 @@ else +@@ -8500,7 +8500,7 @@ else # statically. But if the user explicitly specified the libraries to # use, trust that they are doing what they want. if test "$poststage1_libs" = ""; then diff --git a/package/devel/gdb/patches/130-gdb-ctrl-c.patch b/package/devel/gdb/patches/130-gdb-ctrl-c.patch index 8650ce844c..5272b7e969 100644 --- a/package/devel/gdb/patches/130-gdb-ctrl-c.patch +++ b/package/devel/gdb/patches/130-gdb-ctrl-c.patch @@ -24,7 +24,7 @@ Signed-off-by: Khem Raj --- a/gdbserver/linux-low.cc +++ b/gdbserver/linux-low.cc -@@ -5467,7 +5467,7 @@ linux_process_target::request_interrupt +@@ -5481,7 +5481,7 @@ linux_process_target::request_interrupt { /* Send a SIGINT to the process group. This acts just like the user typed a ^C on the controlling terminal. */ From c1ad78318c3e6421e60dd187477f38ca5f9a5752 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 5 Jan 2024 11:58:15 +0100 Subject: [PATCH 026/222] kernel: fix bridge proxyarp issue with some broken DHCP clients There are broken devices in the wild that handle duplicate IP address detection by sending out ARP requests for the IP that they received from a DHCP server and refuse the address if they get a reply. When proxyarp is enabled, they would go into a loop of requesting an address and then NAKing it again. Fixes: https://github.com/openwrt/openwrt/issues/14309 Signed-off-by: Felix Fietkau --- ...t-send-arp-replies-if-src-and-target.patch | 37 +++++++++++++++++++ ...t-send-arp-replies-if-src-and-target.patch | 37 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 target/linux/generic/pending-5.15/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch create mode 100644 target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch diff --git a/target/linux/generic/pending-5.15/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch b/target/linux/generic/pending-5.15/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch new file mode 100644 index 0000000000..f420d210c2 --- /dev/null +++ b/target/linux/generic/pending-5.15/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch @@ -0,0 +1,37 @@ +From: Felix Fietkau +Date: Thu, 4 Jan 2024 15:21:21 +0100 +Subject: [PATCH] net: bridge: do not send arp replies if src and target hw + addr is the same + +There are broken devices in the wild that handle duplicate IP address +detection by sending out ARP requests for the IP that they received from a +DHCP server and refuse the address if they get a reply. +When proxyarp is enabled, they would go into a loop of requesting an address +and then NAKing it again. + +Link: https://github.com/openwrt/openwrt/issues/14309 +Signed-off-by: Felix Fietkau +--- + +--- a/net/bridge/br_arp_nd_proxy.c ++++ b/net/bridge/br_arp_nd_proxy.c +@@ -204,7 +204,10 @@ void br_do_proxy_suppress_arp(struct sk_ + if ((p && (p->flags & BR_PROXYARP)) || + (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI | + BR_NEIGH_SUPPRESS)))) { +- if (!vid) ++ replied = true; ++ if (!memcmp(n->ha, sha, dev->addr_len)) ++ replied = false; ++ else if (!vid) + br_arp_send(br, p, skb->dev, sip, tip, + sha, n->ha, sha, 0, 0); + else +@@ -212,7 +215,6 @@ void br_do_proxy_suppress_arp(struct sk_ + sha, n->ha, sha, + skb->vlan_proto, + skb_vlan_tag_get(skb)); +- replied = true; + } + + /* If we have replied or as long as we know the diff --git a/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch b/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch new file mode 100644 index 0000000000..f420d210c2 --- /dev/null +++ b/target/linux/generic/pending-6.1/151-net-bridge-do-not-send-arp-replies-if-src-and-target.patch @@ -0,0 +1,37 @@ +From: Felix Fietkau +Date: Thu, 4 Jan 2024 15:21:21 +0100 +Subject: [PATCH] net: bridge: do not send arp replies if src and target hw + addr is the same + +There are broken devices in the wild that handle duplicate IP address +detection by sending out ARP requests for the IP that they received from a +DHCP server and refuse the address if they get a reply. +When proxyarp is enabled, they would go into a loop of requesting an address +and then NAKing it again. + +Link: https://github.com/openwrt/openwrt/issues/14309 +Signed-off-by: Felix Fietkau +--- + +--- a/net/bridge/br_arp_nd_proxy.c ++++ b/net/bridge/br_arp_nd_proxy.c +@@ -204,7 +204,10 @@ void br_do_proxy_suppress_arp(struct sk_ + if ((p && (p->flags & BR_PROXYARP)) || + (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI | + BR_NEIGH_SUPPRESS)))) { +- if (!vid) ++ replied = true; ++ if (!memcmp(n->ha, sha, dev->addr_len)) ++ replied = false; ++ else if (!vid) + br_arp_send(br, p, skb->dev, sip, tip, + sha, n->ha, sha, 0, 0); + else +@@ -212,7 +215,6 @@ void br_do_proxy_suppress_arp(struct sk_ + sha, n->ha, sha, + skb->vlan_proto, + skb_vlan_tag_get(skb)); +- replied = true; + } + + /* If we have replied or as long as we know the From 511c7ff03231752ea2adbdf7cc1af4be962c9b65 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 16 Dec 2023 17:12:33 -0800 Subject: [PATCH 027/222] kernel: backport ethtool_puts Will be used for conversions in the following commit. Signed-off-by: Rosen Penev --- ...8-net-ethtool-implement-ethtool_puts.patch | 139 ++++++++++++++++++ ...8-net-ethtool-implement-ethtool_puts.patch | 139 ++++++++++++++++++ 2 files changed, 278 insertions(+) create mode 100644 target/linux/generic/backport-5.15/894-v6.8-net-ethtool-implement-ethtool_puts.patch create mode 100644 target/linux/generic/backport-6.1/894-v6.8-net-ethtool-implement-ethtool_puts.patch diff --git a/target/linux/generic/backport-5.15/894-v6.8-net-ethtool-implement-ethtool_puts.patch b/target/linux/generic/backport-5.15/894-v6.8-net-ethtool-implement-ethtool_puts.patch new file mode 100644 index 0000000000..ef9e706cb4 --- /dev/null +++ b/target/linux/generic/backport-5.15/894-v6.8-net-ethtool-implement-ethtool_puts.patch @@ -0,0 +1,139 @@ +From mboxrd@z Thu Jan 1 00:00:00 1970 +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="sMUeie/T" +Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 84BB8D6D + for ; Wed, 6 Dec 2023 15:16:16 -0800 (PST) +Received: by mail-yb1-xb49.google.com with SMTP id 3f1490d57ef6-db5416d0fccso403298276.1 + for ; Wed, 06 Dec 2023 15:16:16 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=google.com; s=20230601; t=1701904575; x=1702509375; darn=vger.kernel.org; + h=cc:to:from:subject:message-id:references:mime-version:in-reply-to + :date:from:to:cc:subject:date:message-id:reply-to; + bh=/7eYcPC4ZNNyPcPPs0B5tDplF0arxw3r0vINNNou0rY=; + b=sMUeie/TxdytzC0EyT11QWi1TqTtiv7KCTs1F2vLmUUvPKNA3+1MHFo8ECW+0gQuDE + FGrgdZKGK5mXQgkF0N3JiSLvKO8tpQOIB57JLCG5IVy5dr2vVv0ExU3Dag2Cc4oBIBIO + w/cH95O1oPlvluIpATmAsxenVr7mFomU63BqYiRGLaEhWeb2hJ636GO8lubtsDfdFFoi + GPOL2tQwV93VnqmywBBpFaNAULN0UoCFhfkKv5prvpkXq19sWI7zyorVZ+rdTYem5m4T + dXsDaLXPtC3Dh2JOad1duSQIah/wCHYYUcV3IoFhwj2y0Uk/TTCrnZPORweSADcEy6Ho + vDrA== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20230601; t=1701904575; x=1702509375; + h=cc:to:from:subject:message-id:references:mime-version:in-reply-to + :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; + bh=/7eYcPC4ZNNyPcPPs0B5tDplF0arxw3r0vINNNou0rY=; + b=Dmc6aSntxPlxAk72zVO1G9WoZnFtLolxENlLscYYAHG3VE+PQ8gGN2rPzcGoKb2Btb + 4b0PvjOzSlPQyghahdhdlz04RtAeeGG/MkfNiYjFql5OifIoovb51kroiPYrVsa7Ps7Y + +Pxug0+NPdTm5s9TNz940ZKl3GRME8UTmVxpWJRX03XMOqb6Wgsh2SK9ahXKc4yRsi62 + 3a3J72WmmSgvimxwM/99fXwvoUQpiv2J1xCoqc1Ng4q4qSuZvzmHN7ZTGaUhLxOqLeLK + 3W4RKHW6rZ7UjppuB6I3NXW+D344By2rdKp1sRXpjdQ0GS3YUcvlRETcJBXJudHfQP5Y + CLOw== +X-Gm-Message-State: AOJu0YzdCTLdwny+N99zeMgyKqFsEZhfIhL2cbgKA6zC1U/OLkxxRLoM + XrYVBC9DmxCGmP4o+M/Z/kHUew/9faHlCiLGxw== +X-Google-Smtp-Source: AGHT+IFRXxBV6JuX5Cl/k2o1+WKkCwkR8j20MJSkmoGCedPAtqFttH8OVh1/6vdfnq8MPN++A2h89peZQhyG8OsJ8A== +X-Received: from jstitt-linux1.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:23b5]) + (user=justinstitt job=sendgmr) by 2002:a25:dac7:0:b0:da0:3117:f35 with SMTP + id n190-20020a25dac7000000b00da031170f35mr28652ybf.3.1701904575576; Wed, 06 + Dec 2023 15:16:15 -0800 (PST) +Date: Wed, 06 Dec 2023 23:16:10 +0000 +In-Reply-To: <20231206-ethtool_puts_impl-v5-0-5a2528e17bf8@google.com> +Precedence: bulk +X-Mailing-List: bpf@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +Mime-Version: 1.0 +References: <20231206-ethtool_puts_impl-v5-0-5a2528e17bf8@google.com> +X-Developer-Key: i=justinstitt@google.com; a=ed25519; pk=tC3hNkJQTpNX/gLKxTNQKDmiQl6QjBNCGKJINqAdJsE= +X-Developer-Signature: v=1; a=ed25519-sha256; t=1701904573; l=1840; + i=justinstitt@google.com; s=20230717; h=from:subject:message-id; + bh=UMdetIL2ZsPIkSodqhw2fM21NHJVjCu0lRImFuNhVoM=; b=a8rMnXfVVQ5gsxHWG4WRMwOLxZgflqXZtNuKx26vv4DwYvvCtCiYjl3f1frOjV/Ul2kaxq5g/ + b/UOv678JKCDASVokxG5GJifAnU7/kqRxdhcwfRkrD8RUfcsmiZOfyF +X-Mailer: b4 0.12.3 +Message-ID: <20231206-ethtool_puts_impl-v5-1-5a2528e17bf8@google.com> +Subject: [PATCH net-next v5 1/3] ethtool: Implement ethtool_puts() +From: justinstitt@google.com +To: "David S. Miller" , Eric Dumazet , + Jakub Kicinski , Paolo Abeni , Shay Agroskin , + Arthur Kiyanovski , David Arinzon , Noam Dagan , + Saeed Bishara , Rasesh Mody , + Sudarsana Kalluru , GR-Linux-NIC-Dev@marvell.com, + Dimitris Michailidis , Yisen Zhuang , + Salil Mehta , Jesse Brandeburg , + Tony Nguyen , Louis Peens , + Shannon Nelson , Brett Creeley , drivers@pensando.io, + "K. Y. Srinivasan" , Haiyang Zhang , Wei Liu , + Dexuan Cui , Ronak Doshi , + VMware PV-Drivers Reviewers , Andy Whitcroft , Joe Perches , + Dwaipayan Ray , Lukas Bulwahn , + Hauke Mehrtens , Andrew Lunn , + Florian Fainelli , Vladimir Oltean , + "=?utf-8?q?Ar=C4=B1n=C3=A7_=C3=9CNAL?=" , Daniel Golle , + Landen Chao , DENG Qingfang , + Sean Wang , Matthias Brugger , + AngeloGioacchino Del Regno , + Linus Walleij , + "=?utf-8?q?Alvin_=C5=A0ipraga?=" , Wei Fang , + Shenwei Wang , Clark Wang , + NXP Linux Team , Lars Povlsen , + Steen Hegelund , Daniel Machon , + UNGLinuxDriver@microchip.com, Jiawen Wu , + Mengyuan Lou , Heiner Kallweit , + Russell King , Alexei Starovoitov , + Daniel Borkmann , Jesper Dangaard Brouer , + John Fastabend +Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, + Nick Desaulniers , Nathan Chancellor , + Kees Cook , intel-wired-lan@lists.osuosl.org, + oss-drivers@corigine.com, linux-hyperv@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, + bpf@vger.kernel.org, Justin Stitt +Content-Type: text/plain; charset="utf-8" + +Use strscpy() to implement ethtool_puts(). + +Functionally the same as ethtool_sprintf() when it's used with two +arguments or with just "%s" format specifier. + +Signed-off-by: Justin Stitt +--- + include/linux/ethtool.h | 13 +++++++++++++ + net/ethtool/ioctl.c | 7 +++++++ + 2 files changed, 20 insertions(+) + +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -788,4 +788,17 @@ int ethtool_get_phc_vclocks(struct net_d + * next string. + */ + extern __printf(2, 3) void ethtool_sprintf(u8 **data, const char *fmt, ...); ++ ++/** ++ * ethtool_puts - Write string to ethtool string data ++ * @data: Pointer to a pointer to the start of string to update ++ * @str: String to write ++ * ++ * Write string to *data without a trailing newline. Update *data ++ * to point at start of next string. ++ * ++ * Prefer this function to ethtool_sprintf() when given only ++ * two arguments or if @fmt is just "%s". ++ */ ++extern void ethtool_puts(u8 **data, const char *str); + #endif /* _LINUX_ETHTOOL_H */ +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1953,6 +1953,13 @@ __printf(2, 3) void ethtool_sprintf(u8 * + } + EXPORT_SYMBOL(ethtool_sprintf); + ++void ethtool_puts(u8 **data, const char *str) ++{ ++ strscpy(*data, str, ETH_GSTRING_LEN); ++ *data += ETH_GSTRING_LEN; ++} ++EXPORT_SYMBOL(ethtool_puts); ++ + static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) + { + struct ethtool_value id; diff --git a/target/linux/generic/backport-6.1/894-v6.8-net-ethtool-implement-ethtool_puts.patch b/target/linux/generic/backport-6.1/894-v6.8-net-ethtool-implement-ethtool_puts.patch new file mode 100644 index 0000000000..5094a6d774 --- /dev/null +++ b/target/linux/generic/backport-6.1/894-v6.8-net-ethtool-implement-ethtool_puts.patch @@ -0,0 +1,139 @@ +From mboxrd@z Thu Jan 1 00:00:00 1970 +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="sMUeie/T" +Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 84BB8D6D + for ; Wed, 6 Dec 2023 15:16:16 -0800 (PST) +Received: by mail-yb1-xb49.google.com with SMTP id 3f1490d57ef6-db5416d0fccso403298276.1 + for ; Wed, 06 Dec 2023 15:16:16 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=google.com; s=20230601; t=1701904575; x=1702509375; darn=vger.kernel.org; + h=cc:to:from:subject:message-id:references:mime-version:in-reply-to + :date:from:to:cc:subject:date:message-id:reply-to; + bh=/7eYcPC4ZNNyPcPPs0B5tDplF0arxw3r0vINNNou0rY=; + b=sMUeie/TxdytzC0EyT11QWi1TqTtiv7KCTs1F2vLmUUvPKNA3+1MHFo8ECW+0gQuDE + FGrgdZKGK5mXQgkF0N3JiSLvKO8tpQOIB57JLCG5IVy5dr2vVv0ExU3Dag2Cc4oBIBIO + w/cH95O1oPlvluIpATmAsxenVr7mFomU63BqYiRGLaEhWeb2hJ636GO8lubtsDfdFFoi + GPOL2tQwV93VnqmywBBpFaNAULN0UoCFhfkKv5prvpkXq19sWI7zyorVZ+rdTYem5m4T + dXsDaLXPtC3Dh2JOad1duSQIah/wCHYYUcV3IoFhwj2y0Uk/TTCrnZPORweSADcEy6Ho + vDrA== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20230601; t=1701904575; x=1702509375; + h=cc:to:from:subject:message-id:references:mime-version:in-reply-to + :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; + bh=/7eYcPC4ZNNyPcPPs0B5tDplF0arxw3r0vINNNou0rY=; + b=Dmc6aSntxPlxAk72zVO1G9WoZnFtLolxENlLscYYAHG3VE+PQ8gGN2rPzcGoKb2Btb + 4b0PvjOzSlPQyghahdhdlz04RtAeeGG/MkfNiYjFql5OifIoovb51kroiPYrVsa7Ps7Y + +Pxug0+NPdTm5s9TNz940ZKl3GRME8UTmVxpWJRX03XMOqb6Wgsh2SK9ahXKc4yRsi62 + 3a3J72WmmSgvimxwM/99fXwvoUQpiv2J1xCoqc1Ng4q4qSuZvzmHN7ZTGaUhLxOqLeLK + 3W4RKHW6rZ7UjppuB6I3NXW+D344By2rdKp1sRXpjdQ0GS3YUcvlRETcJBXJudHfQP5Y + CLOw== +X-Gm-Message-State: AOJu0YzdCTLdwny+N99zeMgyKqFsEZhfIhL2cbgKA6zC1U/OLkxxRLoM + XrYVBC9DmxCGmP4o+M/Z/kHUew/9faHlCiLGxw== +X-Google-Smtp-Source: AGHT+IFRXxBV6JuX5Cl/k2o1+WKkCwkR8j20MJSkmoGCedPAtqFttH8OVh1/6vdfnq8MPN++A2h89peZQhyG8OsJ8A== +X-Received: from jstitt-linux1.c.googlers.com ([fda3:e722:ac3:cc00:2b:ff92:c0a8:23b5]) + (user=justinstitt job=sendgmr) by 2002:a25:dac7:0:b0:da0:3117:f35 with SMTP + id n190-20020a25dac7000000b00da031170f35mr28652ybf.3.1701904575576; Wed, 06 + Dec 2023 15:16:15 -0800 (PST) +Date: Wed, 06 Dec 2023 23:16:10 +0000 +In-Reply-To: <20231206-ethtool_puts_impl-v5-0-5a2528e17bf8@google.com> +Precedence: bulk +X-Mailing-List: bpf@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +Mime-Version: 1.0 +References: <20231206-ethtool_puts_impl-v5-0-5a2528e17bf8@google.com> +X-Developer-Key: i=justinstitt@google.com; a=ed25519; pk=tC3hNkJQTpNX/gLKxTNQKDmiQl6QjBNCGKJINqAdJsE= +X-Developer-Signature: v=1; a=ed25519-sha256; t=1701904573; l=1840; + i=justinstitt@google.com; s=20230717; h=from:subject:message-id; + bh=UMdetIL2ZsPIkSodqhw2fM21NHJVjCu0lRImFuNhVoM=; b=a8rMnXfVVQ5gsxHWG4WRMwOLxZgflqXZtNuKx26vv4DwYvvCtCiYjl3f1frOjV/Ul2kaxq5g/ + b/UOv678JKCDASVokxG5GJifAnU7/kqRxdhcwfRkrD8RUfcsmiZOfyF +X-Mailer: b4 0.12.3 +Message-ID: <20231206-ethtool_puts_impl-v5-1-5a2528e17bf8@google.com> +Subject: [PATCH net-next v5 1/3] ethtool: Implement ethtool_puts() +From: justinstitt@google.com +To: "David S. Miller" , Eric Dumazet , + Jakub Kicinski , Paolo Abeni , Shay Agroskin , + Arthur Kiyanovski , David Arinzon , Noam Dagan , + Saeed Bishara , Rasesh Mody , + Sudarsana Kalluru , GR-Linux-NIC-Dev@marvell.com, + Dimitris Michailidis , Yisen Zhuang , + Salil Mehta , Jesse Brandeburg , + Tony Nguyen , Louis Peens , + Shannon Nelson , Brett Creeley , drivers@pensando.io, + "K. Y. Srinivasan" , Haiyang Zhang , Wei Liu , + Dexuan Cui , Ronak Doshi , + VMware PV-Drivers Reviewers , Andy Whitcroft , Joe Perches , + Dwaipayan Ray , Lukas Bulwahn , + Hauke Mehrtens , Andrew Lunn , + Florian Fainelli , Vladimir Oltean , + "=?utf-8?q?Ar=C4=B1n=C3=A7_=C3=9CNAL?=" , Daniel Golle , + Landen Chao , DENG Qingfang , + Sean Wang , Matthias Brugger , + AngeloGioacchino Del Regno , + Linus Walleij , + "=?utf-8?q?Alvin_=C5=A0ipraga?=" , Wei Fang , + Shenwei Wang , Clark Wang , + NXP Linux Team , Lars Povlsen , + Steen Hegelund , Daniel Machon , + UNGLinuxDriver@microchip.com, Jiawen Wu , + Mengyuan Lou , Heiner Kallweit , + Russell King , Alexei Starovoitov , + Daniel Borkmann , Jesper Dangaard Brouer , + John Fastabend +Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, + Nick Desaulniers , Nathan Chancellor , + Kees Cook , intel-wired-lan@lists.osuosl.org, + oss-drivers@corigine.com, linux-hyperv@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, + bpf@vger.kernel.org, Justin Stitt +Content-Type: text/plain; charset="utf-8" + +Use strscpy() to implement ethtool_puts(). + +Functionally the same as ethtool_sprintf() when it's used with two +arguments or with just "%s" format specifier. + +Signed-off-by: Justin Stitt +--- + include/linux/ethtool.h | 13 +++++++++++++ + net/ethtool/ioctl.c | 7 +++++++ + 2 files changed, 20 insertions(+) + +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -843,4 +843,17 @@ int ethtool_get_phc_vclocks(struct net_d + * next string. + */ + extern __printf(2, 3) void ethtool_sprintf(u8 **data, const char *fmt, ...); ++ ++/** ++ * ethtool_puts - Write string to ethtool string data ++ * @data: Pointer to a pointer to the start of string to update ++ * @str: String to write ++ * ++ * Write string to *data without a trailing newline. Update *data ++ * to point at start of next string. ++ * ++ * Prefer this function to ethtool_sprintf() when given only ++ * two arguments or if @fmt is just "%s". ++ */ ++extern void ethtool_puts(u8 **data, const char *str); + #endif /* _LINUX_ETHTOOL_H */ +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1974,6 +1974,13 @@ __printf(2, 3) void ethtool_sprintf(u8 * + } + EXPORT_SYMBOL(ethtool_sprintf); + ++void ethtool_puts(u8 **data, const char *str) ++{ ++ strscpy(*data, str, ETH_GSTRING_LEN); ++ *data += ETH_GSTRING_LEN; ++} ++EXPORT_SYMBOL(ethtool_puts); ++ + static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) + { + struct ethtool_value id; From 89ff407d68ca152a28811f94c0a8e9ebb11f44d7 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 10 Dec 2023 15:12:24 -0800 Subject: [PATCH 028/222] treewide: use ethtool_puts instead of memcpy The former is a safer and more readable version. Signed-off-by: Rosen Penev --- .../files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c | 3 +-- .../700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch | 2 +- .../linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c | 2 +- target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c index e5adc821d2..b022a3e9fb 100644 --- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c @@ -169,8 +169,7 @@ static void ag71xx_ethtool_get_strings(struct net_device *netdev, u32 sset, int i; for (i = 0; i < ARRAY_SIZE(ag71xx_statistics); i++) - memcpy(data + i * ETH_GSTRING_LEN, - ag71xx_statistics[i].name, ETH_GSTRING_LEN); + ethtool_puts(&data, ag71xx_statistics[i].name); } } diff --git a/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch b/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch index 254e85c284..ccc56d115e 100644 --- a/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch +++ b/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch @@ -1953,7 +1953,7 @@ Signed-off-by: Maxime Chevallier + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ARRAY_SIZE(ipqess_stats); i++) -+ ethtool_sprintf(&p, ipqess_stats[i].string); ++ ethtool_puts(&p, ipqess_stats[i].string); + break; + } +} diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c index 5732c28536..a3abf30c71 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/ethtool.c @@ -161,7 +161,7 @@ static void fe_get_strings(struct net_device *dev, u32 stringset, u8 *data) { switch (stringset) { case ETH_SS_STATS: - memcpy(data, *fe_gdma_str, sizeof(fe_gdma_str)); + ethtool_puts(&data, *fe_gdma_str); break; } } diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c index d246e60cb2..9f608950c0 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c @@ -944,8 +944,7 @@ static void rtl83xx_get_strings(struct dsa_switch *ds, return; for (int i = 0; i < ARRAY_SIZE(rtl83xx_mib); i++) - strncpy(data + i * ETH_GSTRING_LEN, rtl83xx_mib[i].name, - ETH_GSTRING_LEN); + ethtool_puts(&data, rtl83xx_mib[i].name); } static void rtl83xx_get_ethtool_stats(struct dsa_switch *ds, int port, From 14362f22af62b74f61d6e7365fbf6960b048849e Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 30 Nov 2023 12:08:31 -0800 Subject: [PATCH 029/222] ramips: fix dtc warnings Mostly leading 0 removals and wrong addresses. Signed-off-by: Rosen Penev --- target/linux/ramips/dts/mt7620a_engenius_epg600.dts | 4 ++-- target/linux/ramips/dts/mt7621_cudy_wr2100.dts | 2 +- target/linux/ramips/dts/mt7621_yuncore_fap640.dts | 6 +++--- target/linux/ramips/dts/mt7621_yuncore_fap690.dts | 6 +++--- target/linux/ramips/dts/mt7628an_wiznet_wizfi630s.dts | 3 --- target/linux/ramips/dts/rt3662_engenius_esr600h.dts | 4 ++-- target/linux/ramips/dts/rt3883.dtsi | 4 +++- target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi | 2 +- 8 files changed, 15 insertions(+), 16 deletions(-) diff --git a/target/linux/ramips/dts/mt7620a_engenius_epg600.dts b/target/linux/ramips/dts/mt7620a_engenius_epg600.dts index f64676d8fb..4b3332d2f0 100644 --- a/target/linux/ramips/dts/mt7620a_engenius_epg600.dts +++ b/target/linux/ramips/dts/mt7620a_engenius_epg600.dts @@ -215,9 +215,9 @@ }; &pcie0 { - wifi@0,1,0 { + wifi@0,0 { compatible = "pci1814,3091"; - reg = <0x0 1 0 0 0>; + reg = <0x0000 0 0 0 0>; nvmem-cells = <&eeprom_factory_0>; nvmem-cell-names = "eeprom"; }; diff --git a/target/linux/ramips/dts/mt7621_cudy_wr2100.dts b/target/linux/ramips/dts/mt7621_cudy_wr2100.dts index fc38e27ac1..afccce15cc 100644 --- a/target/linux/ramips/dts/mt7621_cudy_wr2100.dts +++ b/target/linux/ramips/dts/mt7621_cudy_wr2100.dts @@ -97,7 +97,7 @@ }; &pcie1 { - wifi@1,0 { + wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; nvmem-cells = <&eeprom_factory_8000>; diff --git a/target/linux/ramips/dts/mt7621_yuncore_fap640.dts b/target/linux/ramips/dts/mt7621_yuncore_fap640.dts index 8c662b86cd..ddbeceaff8 100644 --- a/target/linux/ramips/dts/mt7621_yuncore_fap640.dts +++ b/target/linux/ramips/dts/mt7621_yuncore_fap640.dts @@ -129,8 +129,8 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_factory_0004: macaddr@0004 { - reg = <0x0004 0x6>; + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; }; macaddr_factory_e006: macaddr@e006 { @@ -171,7 +171,7 @@ label = "wan"; phy-handle = <ðphy4>; - nvmem-cells = <&macaddr_factory_0004>; + nvmem-cells = <&macaddr_factory_4>; nvmem-cell-names = "mac-address"; }; diff --git a/target/linux/ramips/dts/mt7621_yuncore_fap690.dts b/target/linux/ramips/dts/mt7621_yuncore_fap690.dts index ce6a60215e..ccfb0847aa 100644 --- a/target/linux/ramips/dts/mt7621_yuncore_fap690.dts +++ b/target/linux/ramips/dts/mt7621_yuncore_fap690.dts @@ -99,8 +99,8 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_factory_0004: macaddr@0004 { - reg = <0x0004 0x6>; + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; }; }; }; @@ -128,7 +128,7 @@ }; &gmac0 { - nvmem-cells = <&macaddr_factory_0004>; + nvmem-cells = <&macaddr_factory_4>; nvmem-cell-names = "mac-address"; }; diff --git a/target/linux/ramips/dts/mt7628an_wiznet_wizfi630s.dts b/target/linux/ramips/dts/mt7628an_wiznet_wizfi630s.dts index 3bdb06cec9..01c8bb942a 100644 --- a/target/linux/ramips/dts/mt7628an_wiznet_wizfi630s.dts +++ b/target/linux/ramips/dts/mt7628an_wiznet_wizfi630s.dts @@ -49,9 +49,6 @@ keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; - reset { label = "reset"; gpios = <&gpio 11 GPIO_ACTIVE_LOW>; diff --git a/target/linux/ramips/dts/rt3662_engenius_esr600h.dts b/target/linux/ramips/dts/rt3662_engenius_esr600h.dts index 6770e4cc9a..e142fe5347 100644 --- a/target/linux/ramips/dts/rt3662_engenius_esr600h.dts +++ b/target/linux/ramips/dts/rt3662_engenius_esr600h.dts @@ -161,9 +161,9 @@ &pci1 { status = "okay"; - wifi@0,1,0 { + wifi@0,0 { compatible = "pci1814,3091"; - reg = <0x0 1 0 0 0>; + reg = <0x10000 0 0 0 0>; ralink,5ghz = <0>; nvmem-cells = <&eeprom_factory_8000>; nvmem-cell-names = "eeprom"; diff --git a/target/linux/ramips/dts/rt3883.dtsi b/target/linux/ramips/dts/rt3883.dtsi index 148922e8b9..8c76eb6631 100644 --- a/target/linux/ramips/dts/rt3883.dtsi +++ b/target/linux/ramips/dts/rt3883.dtsi @@ -399,7 +399,7 @@ 0x9000 0 0 4 &pciintc 19 >; - pci1: pci@1 { + pci1: pci@1,0 { reg = <0x0800 0 0 0 0>; device_type = "pci"; #interrupt-cells = <1>; @@ -421,6 +421,7 @@ #address-cells = <3>; #size-cells = <2>; + interrupt-controller; status = "disabled"; }; @@ -430,6 +431,7 @@ #address-cells = <3>; #size-cells = <2>; + interrupt-controller; status = "disabled"; }; }; diff --git a/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi b/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi index 4a64d8a7fe..17c982a314 100644 --- a/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi +++ b/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi @@ -102,7 +102,7 @@ &pci1 { status = "okay"; - wifi@1,0 { + wifi@0,0 { compatible = "pci1814,3091"; reg = <0x10000 0 0 0 0>; ralink,5ghz = <0>; From a94abfadc42b02c2dd6c55df6c494ed8efdc41d7 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 1 Dec 2023 15:02:46 -0800 Subject: [PATCH 030/222] image.mk: reorder DTC_WARN_FLAGS based on upstream pci warnings got reenabled as they were fixed upstream. Signed-off-by: Rosen Penev --- include/image.mk | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/include/image.mk b/include/image.mk index 096ccb5f18..f5ab1d7953 100644 --- a/include/image.mk +++ b/include/image.mk @@ -151,17 +151,13 @@ endif # Disable noisy checks by default as in upstream DTC_WARN_FLAGS := \ + -Wno-interrupt_provider \ + -Wno-unique_unit_address \ -Wno-unit_address_vs_reg \ - -Wno-simple_bus_reg \ - -Wno-unit_address_format \ - -Wno-pci_bridge \ - -Wno-pci_device_bus_num \ - -Wno-pci_device_reg \ -Wno-avoid_unnecessary_addr_size \ -Wno-alias_paths \ -Wno-graph_child_address \ - -Wno-graph_port \ - -Wno-unique_unit_address + -Wno-simple_bus_reg DTC_FLAGS += $(DTC_WARN_FLAGS) DTCO_FLAGS += $(DTC_WARN_FLAGS) From b07b8aade7174f915932dc16120bfe0c02de7133 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 1 Dec 2023 12:42:00 -0800 Subject: [PATCH 031/222] ath79: rename pcie-controller to pcie pcie-controller was renamed to pcie since at least kernel 4.14. Match it here to get rid of dtc warnings. Signed-off-by: Rosen Penev --- target/linux/ath79/dts/ar7100.dtsi | 2 +- target/linux/ath79/dts/ar724x.dtsi | 2 +- target/linux/ath79/dts/ar9344.dtsi | 2 +- target/linux/ath79/dts/qca953x.dtsi | 2 +- target/linux/ath79/dts/qca955x.dtsi | 4 ++-- target/linux/ath79/dts/qca956x.dtsi | 2 +- .../310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch | 2 +- .../312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch | 2 +- .../310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch | 2 +- .../312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/target/linux/ath79/dts/ar7100.dtsi b/target/linux/ath79/dts/ar7100.dtsi index a03f282a0f..6648311619 100644 --- a/target/linux/ath79/dts/ar7100.dtsi +++ b/target/linux/ath79/dts/ar7100.dtsi @@ -113,7 +113,7 @@ #reset-cells = <1>; }; - pcie0: pcie-controller@17010000 { + pcie0: pcie@17010000 { compatible = "qca,ar7100-pci"; #address-cells = <3>; #size-cells = <2>; diff --git a/target/linux/ath79/dts/ar724x.dtsi b/target/linux/ath79/dts/ar724x.dtsi index c090eb5e0f..c758fc244e 100644 --- a/target/linux/ath79/dts/ar724x.dtsi +++ b/target/linux/ath79/dts/ar724x.dtsi @@ -121,7 +121,7 @@ #reset-cells = <1>; }; - pcie: pcie-controller@180c0000 { + pcie: pcie@180c0000 { compatible = "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; diff --git a/target/linux/ath79/dts/ar9344.dtsi b/target/linux/ath79/dts/ar9344.dtsi index fb23c53d41..dff912f8ca 100644 --- a/target/linux/ath79/dts/ar9344.dtsi +++ b/target/linux/ath79/dts/ar9344.dtsi @@ -32,7 +32,7 @@ }; &ahb { - pcie: pcie-controller@180c0000 { + pcie: pcie@180c0000 { compatible = "qcom,ar9340-pci", "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; diff --git a/target/linux/ath79/dts/qca953x.dtsi b/target/linux/ath79/dts/qca953x.dtsi index 4300c741ad..cc26db5ba2 100644 --- a/target/linux/ath79/dts/qca953x.dtsi +++ b/target/linux/ath79/dts/qca953x.dtsi @@ -150,7 +150,7 @@ reg = <0x18070000 0x4>; }; - pcie0: pcie-controller@180c0000 { + pcie0: pcie@180c0000 { compatible = "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; diff --git a/target/linux/ath79/dts/qca955x.dtsi b/target/linux/ath79/dts/qca955x.dtsi index e7daa9d827..13b051de20 100644 --- a/target/linux/ath79/dts/qca955x.dtsi +++ b/target/linux/ath79/dts/qca955x.dtsi @@ -185,7 +185,7 @@ reg = <0x18070000 0x58>; }; - pcie0: pcie-controller@180c0000 { + pcie0: pcie@180c0000 { compatible = "qcom,qca9550-pci", "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; @@ -222,7 +222,7 @@ status = "disabled"; }; - pcie1: pcie-controller@18250000 { + pcie1: pcie@18250000 { compatible = "qcom,qca9550-pci", "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; diff --git a/target/linux/ath79/dts/qca956x.dtsi b/target/linux/ath79/dts/qca956x.dtsi index e46f0676e2..8b261568f0 100644 --- a/target/linux/ath79/dts/qca956x.dtsi +++ b/target/linux/ath79/dts/qca956x.dtsi @@ -157,7 +157,7 @@ status = "disabled"; }; - pcie: pcie-controller@18250000 { + pcie: pcie@18250000 { compatible = "qcom,ar7240-pci"; #address-cells = <3>; #size-cells = <2>; diff --git a/target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch b/target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch index bf7eb691a5..cf0a75c791 100644 --- a/target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch +++ b/target/linux/ath79/patches-5.15/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch @@ -37,7 +37,7 @@ Signed-off-by: John Crispin +- interrupt-parent: phandle to the MIPS IRQ controller + +* Example for ar7100 -+ pcie-controller@180c0000 { ++ pcie@180c0000 { + compatible = "qca,ar7100-pci"; + #address-cells = <3>; + #size-cells = <2>; diff --git a/target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch b/target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch index a0af79cb4d..a32c9bdcde 100644 --- a/target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch +++ b/target/linux/ath79/patches-5.15/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch @@ -39,7 +39,7 @@ Signed-off-by: John Crispin +- interrupt-controller: define to enable the builtin IRQ cascade. + +* Example for qca9557 -+ pcie-controller@180c0000 { ++ pcie@180c0000 { + compatible = "qcom,ar7240-pci"; + #address-cells = <3>; + #size-cells = <2>; diff --git a/target/linux/ath79/patches-6.1/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch b/target/linux/ath79/patches-6.1/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch index bf7eb691a5..cf0a75c791 100644 --- a/target/linux/ath79/patches-6.1/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch +++ b/target/linux/ath79/patches-6.1/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch @@ -37,7 +37,7 @@ Signed-off-by: John Crispin +- interrupt-parent: phandle to the MIPS IRQ controller + +* Example for ar7100 -+ pcie-controller@180c0000 { ++ pcie@180c0000 { + compatible = "qca,ar7100-pci"; + #address-cells = <3>; + #size-cells = <2>; diff --git a/target/linux/ath79/patches-6.1/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch b/target/linux/ath79/patches-6.1/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch index a0af79cb4d..a32c9bdcde 100644 --- a/target/linux/ath79/patches-6.1/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch +++ b/target/linux/ath79/patches-6.1/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch @@ -39,7 +39,7 @@ Signed-off-by: John Crispin +- interrupt-controller: define to enable the builtin IRQ cascade. + +* Example for qca9557 -+ pcie-controller@180c0000 { ++ pcie@180c0000 { + compatible = "qcom,ar7240-pci"; + #address-cells = <3>; + #size-cells = <2>; From 2607e3fe247b87c193deb86d1c42930eb655cc54 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 1 Dec 2023 12:51:58 -0800 Subject: [PATCH 032/222] ath79: fix avoid_unnecessary_addr_size warnings Raised to dtc. Signed-off-by: Rosen Penev --- target/linux/ath79/dts/ar9344_qihoo_c301.dts | 4 ---- target/linux/ath79/dts/ar934x.dtsi | 3 --- target/linux/ath79/dts/qca9533_tplink_cpexxx.dtsi | 2 -- target/linux/ath79/dts/qca9533_tplink_tl-wa850re-v2.dts | 2 -- target/linux/ath79/dts/qca955x.dtsi | 3 --- 5 files changed, 14 deletions(-) diff --git a/target/linux/ath79/dts/ar9344_qihoo_c301.dts b/target/linux/ath79/dts/ar9344_qihoo_c301.dts index 616036fcfc..bf6706716f 100644 --- a/target/linux/ath79/dts/ar9344_qihoo_c301.dts +++ b/target/linux/ath79/dts/ar9344_qihoo_c301.dts @@ -103,8 +103,6 @@ pinctrl-0 = <&pmx_spi_cs1>; flash@0 { - #address-cells = <1>; - #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <25000000>; @@ -164,8 +162,6 @@ }; flash@1 { - #address-cells = <1>; - #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <1>; spi-max-frequency = <25000000>; diff --git a/target/linux/ath79/dts/ar934x.dtsi b/target/linux/ath79/dts/ar934x.dtsi index 94dfde4125..98cd76629f 100644 --- a/target/linux/ath79/dts/ar934x.dtsi +++ b/target/linux/ath79/dts/ar934x.dtsi @@ -197,9 +197,6 @@ nand-ecc-mode = "hw"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; }; diff --git a/target/linux/ath79/dts/qca9533_tplink_cpexxx.dtsi b/target/linux/ath79/dts/qca9533_tplink_cpexxx.dtsi index e7044b60a4..f17dd513e2 100644 --- a/target/linux/ath79/dts/qca9533_tplink_cpexxx.dtsi +++ b/target/linux/ath79/dts/qca9533_tplink_cpexxx.dtsi @@ -53,8 +53,6 @@ status = "okay"; flash@0 { - #address-cells = <1>; - #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <25000000>; diff --git a/target/linux/ath79/dts/qca9533_tplink_tl-wa850re-v2.dts b/target/linux/ath79/dts/qca9533_tplink_tl-wa850re-v2.dts index 762197f255..c3d42a8b35 100644 --- a/target/linux/ath79/dts/qca9533_tplink_tl-wa850re-v2.dts +++ b/target/linux/ath79/dts/qca9533_tplink_tl-wa850re-v2.dts @@ -95,8 +95,6 @@ status = "okay"; flash@0 { - #address-cells = <1>; - #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <25000000>; diff --git a/target/linux/ath79/dts/qca955x.dtsi b/target/linux/ath79/dts/qca955x.dtsi index 13b051de20..c17a15c55e 100644 --- a/target/linux/ath79/dts/qca955x.dtsi +++ b/target/linux/ath79/dts/qca955x.dtsi @@ -313,9 +313,6 @@ nand-ecc-mode = "hw"; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; }; From 6dbc300bafa34a229f342701551d3c4d65c9d22a Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 1 Dec 2023 12:54:08 -0800 Subject: [PATCH 033/222] ath79: fix unit_address_format warning Raised by dtc. Signed-off-by: Rosen Penev --- .../dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts | 2 +- target/linux/ath79/dts/qca9558_jjplus_jwap230.dts | 2 +- .../linux/ath79/dts/qca9561_tplink_tl-wdr6500-v2.dts | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts index f14e138026..9faddcc37f 100644 --- a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts @@ -77,7 +77,7 @@ compatible = "gpio-keys-polled"; poll-interval = <20>; - button@0 { + button-reset { label = "reset"; linux,code = ; gpios = <&gpio_key 1 GPIO_ACTIVE_LOW>; diff --git a/target/linux/ath79/dts/qca9558_jjplus_jwap230.dts b/target/linux/ath79/dts/qca9558_jjplus_jwap230.dts index 6cd93f6b33..ee2e82ef10 100644 --- a/target/linux/ath79/dts/qca9558_jjplus_jwap230.dts +++ b/target/linux/ath79/dts/qca9558_jjplus_jwap230.dts @@ -109,7 +109,7 @@ &mdio0 { status = "okay"; - switch { + switch@0 { compatible = "qca,ar8327"; reg = <0>; diff --git a/target/linux/ath79/dts/qca9561_tplink_tl-wdr6500-v2.dts b/target/linux/ath79/dts/qca9561_tplink_tl-wdr6500-v2.dts index 04567e6b88..8767693c82 100644 --- a/target/linux/ath79/dts/qca9561_tplink_tl-wdr6500-v2.dts +++ b/target/linux/ath79/dts/qca9561_tplink_tl-wdr6500-v2.dts @@ -86,9 +86,9 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_uboot_0fc00: macaddr@0fc00 { + macaddr_uboot_fc00: macaddr@fc00 { compatible = "mac-base"; - reg = <0x0fc00 0x6>; + reg = <0xfc00 0x6>; #nvmem-cell-cells = <1>; }; }; @@ -134,7 +134,7 @@ compatible = "qcom,ath10k"; reg = <0 0 0 0 0>; - nvmem-cells = <&macaddr_uboot_0fc00 (-2)>, <&calibration_ath10k>; + nvmem-cells = <&macaddr_uboot_fc00 (-2)>, <&calibration_ath10k>; nvmem-cell-names = "mac-address", "calibration"; }; }; @@ -148,21 +148,21 @@ phy-handle = <&swphy4>; - nvmem-cells = <&macaddr_uboot_0fc00 1>; + nvmem-cells = <&macaddr_uboot_fc00 1>; nvmem-cell-names = "mac-address"; }; ð1 { status = "okay"; - nvmem-cells = <&macaddr_uboot_0fc00 0>; + nvmem-cells = <&macaddr_uboot_fc00 0>; nvmem-cell-names = "mac-address"; }; &wmac { status = "okay"; - nvmem-cells = <&macaddr_uboot_0fc00 (-1)>, <&calibration_ath9k>; + nvmem-cells = <&macaddr_uboot_fc00 (-1)>, <&calibration_ath9k>; nvmem-cell-names = "mac-address", "calibration"; }; From 991c8cabed6538455a7562c2aef1143b171ccff8 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 1 Dec 2023 13:11:39 -0800 Subject: [PATCH 034/222] ath79: fix pci_device_reg errors Found by dtc. Wrong numbers and wrong ordering. Signed-off-by: Rosen Penev --- target/linux/ath79/dts/ar7161_aruba_ap-105.dts | 4 ++-- target/linux/ath79/dts/ar7161_aruba_ap-175.dts | 4 ++-- target/linux/ath79/dts/ar7161_buffalo_wzr-hp-ag300h.dtsi | 4 ++-- target/linux/ath79/dts/ar7161_dlink_dir-825-b1.dts | 4 ++-- target/linux/ath79/dts/ar7161_fortinet_fap-220-b.dts | 4 ++-- target/linux/ath79/dts/ar7161_meraki_mr16.dts | 4 ++-- target/linux/ath79/dts/ar7161_netgear_wndap360.dts | 4 ++-- target/linux/ath79/dts/ar7161_netgear_wndr.dtsi | 4 ++-- target/linux/ath79/dts/ar7161_ruckus_gd11.dtsi | 4 ++-- target/linux/ath79/dts/ar7161_trendnet_tew-673gru.dts | 4 ++-- target/linux/ath79/dts/ar7242_engenius_eap350-v1.dts | 2 +- target/linux/ath79/dts/ar7242_engenius_ecb350-v1.dts | 2 +- target/linux/ath79/dts/ar7242_meraki_mr12.dts | 2 +- target/linux/ath79/dts/ar9344_araknis_an-300-ap-i-n.dts | 2 +- target/linux/ath79/dts/ar9344_engenius_eap600.dts | 2 +- target/linux/ath79/dts/ar9344_engenius_ecb600.dts | 2 +- target/linux/ath79/dts/ar9344_fortinet_ap-dual.dtsi | 2 +- target/linux/ath79/dts/ar9344_netgear_r6100.dts | 2 +- target/linux/ath79/dts/ar9344_senao_ap-dual.dtsi | 2 +- target/linux/ath79/dts/ar9344_watchguard_ap100.dts | 2 +- target/linux/ath79/dts/ar9344_watchguard_ap200.dts | 2 +- target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts | 1 - .../linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts | 2 +- target/linux/ath79/dts/qca9558_engenius_esr900.dts | 2 +- target/linux/ath79/dts/qca955x_engenius_ecb1xxx.dtsi | 2 +- target/linux/ath79/dts/qca955x_senao_loader.dtsi | 6 +++--- target/linux/ath79/dts/qca955x_senao_router-dual.dtsi | 2 +- 27 files changed, 38 insertions(+), 39 deletions(-) diff --git a/target/linux/ath79/dts/ar7161_aruba_ap-105.dts b/target/linux/ath79/dts/ar7161_aruba_ap-105.dts index c8510a8944..dd110fc185 100644 --- a/target/linux/ath79/dts/ar7161_aruba_ap-105.dts +++ b/target/linux/ath79/dts/ar7161_aruba_ap-105.dts @@ -94,7 +94,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { /* 2.4 GHz */ + ath9k0: wifi@11,0 { /* 2.4 GHz */ compatible = "pci168c,0029"; nvmem-cells = <&macaddr_hwinfo_1c 1>; nvmem-cell-names = "mac-address"; @@ -103,7 +103,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { /* 5 GHz */ + ath9k1: wifi@12,0 { /* 5 GHz */ compatible = "pci168c,0029"; nvmem-cells = <&macaddr_hwinfo_1c 2>; nvmem-cell-names = "mac-address"; diff --git a/target/linux/ath79/dts/ar7161_aruba_ap-175.dts b/target/linux/ath79/dts/ar7161_aruba_ap-175.dts index 96a76a3cfc..62a2083d20 100644 --- a/target/linux/ath79/dts/ar7161_aruba_ap-175.dts +++ b/target/linux/ath79/dts/ar7161_aruba_ap-175.dts @@ -120,7 +120,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { + ath9k0: wifi@11,0 { compatible = "pci168c,0029"; nvmem-cells = <&macaddr_hwinfo_1c 1>; nvmem-cell-names = "mac-address"; @@ -129,7 +129,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { + ath9k1: wifi@12,0 { compatible = "pci168c,0029"; nvmem-cells = <&macaddr_hwinfo_1c 2>; nvmem-cell-names = "mac-address"; diff --git a/target/linux/ath79/dts/ar7161_buffalo_wzr-hp-ag300h.dtsi b/target/linux/ath79/dts/ar7161_buffalo_wzr-hp-ag300h.dtsi index e3f48fee85..50c0748a38 100644 --- a/target/linux/ath79/dts/ar7161_buffalo_wzr-hp-ag300h.dtsi +++ b/target/linux/ath79/dts/ar7161_buffalo_wzr-hp-ag300h.dtsi @@ -196,7 +196,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { + ath9k0: wifi@11,0 { compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; qca,no-eeprom; @@ -204,7 +204,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { + ath9k1: wifi@12,0 { compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; qca,no-eeprom; diff --git a/target/linux/ath79/dts/ar7161_dlink_dir-825-b1.dts b/target/linux/ath79/dts/ar7161_dlink_dir-825-b1.dts index b62111c110..639736d9c4 100644 --- a/target/linux/ath79/dts/ar7161_dlink_dir-825-b1.dts +++ b/target/linux/ath79/dts/ar7161_dlink_dir-825-b1.dts @@ -136,7 +136,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { + ath9k0: wifi@11,0 { compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; nvmem-cells = <&macaddr_lan 0>, <&cal_art_1000>; @@ -145,7 +145,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { + ath9k1: wifi@12,0 { compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; nvmem-cells = <&macaddr_wan 1>, <&cal_art_5000>; diff --git a/target/linux/ath79/dts/ar7161_fortinet_fap-220-b.dts b/target/linux/ath79/dts/ar7161_fortinet_fap-220-b.dts index ddcf68970d..e0aa5704cd 100644 --- a/target/linux/ath79/dts/ar7161_fortinet_fap-220-b.dts +++ b/target/linux/ath79/dts/ar7161_fortinet_fap-220-b.dts @@ -95,7 +95,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { /* 2.4 GHz */ + ath9k0: wifi@11,0 { /* 2.4 GHz */ compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; ieee80211-freq-limit = <2402000 2482000>; @@ -105,7 +105,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { /* 5 GHz */ + ath9k1: wifi@12,0 { /* 5 GHz */ compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; ieee80211-freq-limit = <2402000 2482000 4900000 5990000>; diff --git a/target/linux/ath79/dts/ar7161_meraki_mr16.dts b/target/linux/ath79/dts/ar7161_meraki_mr16.dts index 6b8574e880..b732010446 100644 --- a/target/linux/ath79/dts/ar7161_meraki_mr16.dts +++ b/target/linux/ath79/dts/ar7161_meraki_mr16.dts @@ -70,7 +70,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { /* 2.4 GHz */ + ath9k0: wifi@11,0 { /* 2.4 GHz */ compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; qca,no-eeprom; @@ -80,7 +80,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { /* 5 GHz */ + ath9k1: wifi@12,0 { /* 5 GHz */ compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; qca,no-eeprom; diff --git a/target/linux/ath79/dts/ar7161_netgear_wndap360.dts b/target/linux/ath79/dts/ar7161_netgear_wndap360.dts index 9761234714..020b45d9e1 100644 --- a/target/linux/ath79/dts/ar7161_netgear_wndap360.dts +++ b/target/linux/ath79/dts/ar7161_netgear_wndap360.dts @@ -147,7 +147,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { + ath9k0: wifi@11,0 { compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; nvmem-cells = <&macaddr_art_120c>, <&calibration_art_1000>; @@ -156,7 +156,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { + ath9k1: wifi@12,0 { compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; nvmem-cells = <&macaddr_art_520c 1>, <&calibration_art_5000>; diff --git a/target/linux/ath79/dts/ar7161_netgear_wndr.dtsi b/target/linux/ath79/dts/ar7161_netgear_wndr.dtsi index 296ecc8c4e..d30b4dad30 100644 --- a/target/linux/ath79/dts/ar7161_netgear_wndr.dtsi +++ b/target/linux/ath79/dts/ar7161_netgear_wndr.dtsi @@ -126,7 +126,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { + ath9k0: wifi@11,0 { compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; @@ -153,7 +153,7 @@ }; }; - ath9k1: wifi@0,12 { + ath9k1: wifi@12,0 { compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; diff --git a/target/linux/ath79/dts/ar7161_ruckus_gd11.dtsi b/target/linux/ath79/dts/ar7161_ruckus_gd11.dtsi index 065068571c..54a15c49c1 100644 --- a/target/linux/ath79/dts/ar7161_ruckus_gd11.dtsi +++ b/target/linux/ath79/dts/ar7161_ruckus_gd11.dtsi @@ -131,7 +131,7 @@ &pcie0 { status = "okay"; - ath9k0: wifi@0,11 { /* 2.4 GHz */ + ath9k0: wifi@11,0 { /* 2.4 GHz */ compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; nvmem-cells = <&macaddr_bdata_60>; @@ -140,7 +140,7 @@ gpio-controller; }; - ath9k1: wifi@0,12 { /* 5 GHz */ + ath9k1: wifi@12,0 { /* 5 GHz */ compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; nvmem-cells = <&macaddr_bdata_76>; diff --git a/target/linux/ath79/dts/ar7161_trendnet_tew-673gru.dts b/target/linux/ath79/dts/ar7161_trendnet_tew-673gru.dts index a770ca04a8..7508be1df1 100644 --- a/target/linux/ath79/dts/ar7161_trendnet_tew-673gru.dts +++ b/target/linux/ath79/dts/ar7161_trendnet_tew-673gru.dts @@ -92,13 +92,13 @@ &pcie0 { status = "okay"; - wifi@0,11 { + wifi@11,0 { compatible = "pci168c,0029"; reg = <0x8800 0 0 0 0>; qca,no-eeprom; }; - wifi@0,12 { + wifi@12,0 { compatible = "pci168c,0029"; reg = <0x9000 0 0 0 0>; qca,no-eeprom; diff --git a/target/linux/ath79/dts/ar7242_engenius_eap350-v1.dts b/target/linux/ath79/dts/ar7242_engenius_eap350-v1.dts index 8e8deba933..861964fdfc 100644 --- a/target/linux/ath79/dts/ar7242_engenius_eap350-v1.dts +++ b/target/linux/ath79/dts/ar7242_engenius_eap350-v1.dts @@ -75,7 +75,7 @@ &pcie { status = "okay"; - ath9k: wifi@0,0,0 { + ath9k: wifi@0,0 { compatible = "pci168c,002a"; reg = <0x0 0 0 0 0>; nvmem-cells = <&macaddr_art_0 1>; diff --git a/target/linux/ath79/dts/ar7242_engenius_ecb350-v1.dts b/target/linux/ath79/dts/ar7242_engenius_ecb350-v1.dts index 69629335b3..a7def14c73 100644 --- a/target/linux/ath79/dts/ar7242_engenius_ecb350-v1.dts +++ b/target/linux/ath79/dts/ar7242_engenius_ecb350-v1.dts @@ -75,7 +75,7 @@ &pcie { status = "okay"; - ath9k: wifi@0,0,0 { + ath9k: wifi@0,0 { compatible = "pci168c,002a"; reg = <0x0 0 0 0 0>; nvmem-cells = <&macaddr_art_0 (-1)>; diff --git a/target/linux/ath79/dts/ar7242_meraki_mr12.dts b/target/linux/ath79/dts/ar7242_meraki_mr12.dts index adea2778ea..5218a5ce27 100644 --- a/target/linux/ath79/dts/ar7242_meraki_mr12.dts +++ b/target/linux/ath79/dts/ar7242_meraki_mr12.dts @@ -70,7 +70,7 @@ &pcie { status = "okay"; - wifi@0,0,0 { + wifi@0,0 { compatible = "pci168c,002a"; reg = <0x0000 0 0 0 0>; qca,no-eeprom; diff --git a/target/linux/ath79/dts/ar9344_araknis_an-300-ap-i-n.dts b/target/linux/ath79/dts/ar9344_araknis_an-300-ap-i-n.dts index a45aa444de..c2c7cbb960 100644 --- a/target/linux/ath79/dts/ar9344_araknis_an-300-ap-i-n.dts +++ b/target/linux/ath79/dts/ar9344_araknis_an-300-ap-i-n.dts @@ -84,7 +84,7 @@ &pcie { status = "okay"; - ath9k: wifi@0,0,0 { + ath9k: wifi@0,0 { compatible = "pci168c,0030"; reg = <0x0 0 0 0 0>; nvmem-cells = <&macaddr_art_0 1>, <&calibration_art_5000>; diff --git a/target/linux/ath79/dts/ar9344_engenius_eap600.dts b/target/linux/ath79/dts/ar9344_engenius_eap600.dts index 888e3f82ad..4d3a149e3e 100644 --- a/target/linux/ath79/dts/ar9344_engenius_eap600.dts +++ b/target/linux/ath79/dts/ar9344_engenius_eap600.dts @@ -34,7 +34,7 @@ }; &pcie { - wifi@0,0,0 { + wifi@0,0 { nvmem-cells = <&macaddr_art_0 0>, <&calibration_art_5000>; nvmem-cell-names = "mac-address", "calibration"; }; diff --git a/target/linux/ath79/dts/ar9344_engenius_ecb600.dts b/target/linux/ath79/dts/ar9344_engenius_ecb600.dts index ac9bbea5d4..e7b8b9c3ce 100644 --- a/target/linux/ath79/dts/ar9344_engenius_ecb600.dts +++ b/target/linux/ath79/dts/ar9344_engenius_ecb600.dts @@ -29,7 +29,7 @@ }; &pcie { - wifi@0,0,0 { + wifi@0,0 { nvmem-cells = <&macaddr_art_0 (-2)>, <&calibration_art_5000>; nvmem-cell-names = "mac-address", "calibration"; }; diff --git a/target/linux/ath79/dts/ar9344_fortinet_ap-dual.dtsi b/target/linux/ath79/dts/ar9344_fortinet_ap-dual.dtsi index c8f12a1bfb..6b1ae8ac93 100644 --- a/target/linux/ath79/dts/ar9344_fortinet_ap-dual.dtsi +++ b/target/linux/ath79/dts/ar9344_fortinet_ap-dual.dtsi @@ -56,7 +56,7 @@ &pcie { status = "okay"; - ath9k: wifi@0,0,0 { + ath9k: wifi@0,0 { compatible = "pci168c,0030"; reg = <0x0 0 0 0 0>; }; diff --git a/target/linux/ath79/dts/ar9344_netgear_r6100.dts b/target/linux/ath79/dts/ar9344_netgear_r6100.dts index 419fa51f61..5952e0140f 100644 --- a/target/linux/ath79/dts/ar9344_netgear_r6100.dts +++ b/target/linux/ath79/dts/ar9344_netgear_r6100.dts @@ -203,7 +203,7 @@ &pcie { status = "okay"; - wifi@0,0,0 { + wifi@0,0 { compatible = "qcom,ath10k"; reg = <0x0000 0 0 0 0>; diff --git a/target/linux/ath79/dts/ar9344_senao_ap-dual.dtsi b/target/linux/ath79/dts/ar9344_senao_ap-dual.dtsi index c0e95065d5..f1d6ffda7c 100644 --- a/target/linux/ath79/dts/ar9344_senao_ap-dual.dtsi +++ b/target/linux/ath79/dts/ar9344_senao_ap-dual.dtsi @@ -59,7 +59,7 @@ &pcie { status = "okay"; - ath9k: wifi@0,0,0 { + ath9k: wifi@0,0 { compatible = "pci168c,0030"; reg = <0x0 0 0 0 0>; ieee80211-freq-limit = <2402000 2482000>; diff --git a/target/linux/ath79/dts/ar9344_watchguard_ap100.dts b/target/linux/ath79/dts/ar9344_watchguard_ap100.dts index 2fd9a6e51b..e09d539c56 100644 --- a/target/linux/ath79/dts/ar9344_watchguard_ap100.dts +++ b/target/linux/ath79/dts/ar9344_watchguard_ap100.dts @@ -63,7 +63,7 @@ &pcie { status = "disabled"; - wifi@0,0,0 { + wifi@0,0 { nvmem-cells = <&calibration_art_5000>; nvmem-cell-names = "calibration"; }; diff --git a/target/linux/ath79/dts/ar9344_watchguard_ap200.dts b/target/linux/ath79/dts/ar9344_watchguard_ap200.dts index 9cf6819958..c3d7c50813 100644 --- a/target/linux/ath79/dts/ar9344_watchguard_ap200.dts +++ b/target/linux/ath79/dts/ar9344_watchguard_ap200.dts @@ -61,7 +61,7 @@ }; &pcie { - wifi@0,0,0 { + wifi@0,0 { nvmem-cells = <&macaddr_art_0 (-1)>, <&calibration_art_5000>; nvmem-cell-names = "mac-address", "calibration"; }; diff --git a/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts b/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts index 1c6dcee8bf..b81485f465 100644 --- a/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts +++ b/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts @@ -72,7 +72,6 @@ wifi@0,0 { compatible = "qcom,ath10k"; reg = <0 0 0 0 0>; - device_type = "pci"; }; }; diff --git a/target/linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts b/target/linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts index 59dd83d5f8..4a68f53075 100644 --- a/target/linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts +++ b/target/linux/ath79/dts/qca9557_extreme-networks_ws-ap3805i.dts @@ -75,7 +75,7 @@ &pcie0 { status = "okay"; - wifi@0,0,0 { + wifi@0,0 { compatible = "qcom,ath10k"; reg = <0x0 0 0 0 0>; }; diff --git a/target/linux/ath79/dts/qca9558_engenius_esr900.dts b/target/linux/ath79/dts/qca9558_engenius_esr900.dts index 269f743223..ef0e21a3b5 100644 --- a/target/linux/ath79/dts/qca9558_engenius_esr900.dts +++ b/target/linux/ath79/dts/qca9558_engenius_esr900.dts @@ -76,7 +76,7 @@ &pcie0 { status = "okay"; - wifi@0,0,0 { + wifi@0,0 { compatible = "pci168c,0033"; reg = <0x0000 0 0 0 0>; nvmem-cells = <&calibration_art_5000>; diff --git a/target/linux/ath79/dts/qca955x_engenius_ecb1xxx.dtsi b/target/linux/ath79/dts/qca955x_engenius_ecb1xxx.dtsi index e448cd3012..66f2e38853 100644 --- a/target/linux/ath79/dts/qca955x_engenius_ecb1xxx.dtsi +++ b/target/linux/ath79/dts/qca955x_engenius_ecb1xxx.dtsi @@ -119,7 +119,7 @@ &pcie0 { status = "okay"; - wifi@0,0,0 { + wifi@0,0 { compatible = "qcom,ath10k"; reg = <0x0 0 0 0 0>; qca,no-eeprom; diff --git a/target/linux/ath79/dts/qca955x_senao_loader.dtsi b/target/linux/ath79/dts/qca955x_senao_loader.dtsi index cf82c050b6..31e00ce063 100644 --- a/target/linux/ath79/dts/qca955x_senao_loader.dtsi +++ b/target/linux/ath79/dts/qca955x_senao_loader.dtsi @@ -26,16 +26,16 @@ }; &pcie0 { - ath10k_0: wifi@0,0,0 { + ath10k_0: wifi@0,0 { compatible = "qcom,ath10k"; reg = <0x0 0 0 0 0>; }; }; &pcie1 { - ath10k_1: wifi@0,1,0 { + ath10k_1: wifi@0,0 { compatible = "qcom,ath10k"; - reg = <0x0 1 0 0 0>; + reg = <0x0 0 0 0 0>; }; }; diff --git a/target/linux/ath79/dts/qca955x_senao_router-dual.dtsi b/target/linux/ath79/dts/qca955x_senao_router-dual.dtsi index 61446263c4..8f62cf442c 100644 --- a/target/linux/ath79/dts/qca955x_senao_router-dual.dtsi +++ b/target/linux/ath79/dts/qca955x_senao_router-dual.dtsi @@ -43,7 +43,7 @@ &pcie0 { status = "okay"; - ath10k_0: wifi@0,0,0 { + ath10k_0: wifi@0,0 { compatible = "qcom,ath10k"; reg = <0x0000 0 0 0 0>; }; From 506b4d563eb735b6e1597cb9c58f9eb02e1d0221 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 1 Dec 2023 15:44:34 -0800 Subject: [PATCH 035/222] ath79: gpio to gpios Fixes deprecated_gpio_property dtc warning Signed-off-by: Rosen Penev --- target/linux/ath79/dts/ar7242_avm_fritz300e.dts | 2 +- target/linux/ath79/dts/ar9331_glinet_gl-mifi.dts | 2 +- target/linux/ath79/dts/ar9331_hiwifi_hc6361.dts | 2 +- target/linux/ath79/dts/ar9331_onion_omega.dts | 2 +- target/linux/ath79/dts/ar9331_pisen_wmm003n.dts | 2 +- target/linux/ath79/dts/ar9331_teltonika_rut230-v1.dts | 2 +- target/linux/ath79/dts/ar9331_tplink_tl-mr10u.dts | 2 +- target/linux/ath79/dts/ar9331_tplink_tl-mr3020-v1.dts | 2 +- target/linux/ath79/dts/ar9331_tplink_tl-mr3040-v2.dts | 2 +- target/linux/ath79/dts/ar9331_tplink_tl-wr703n.dts | 2 +- target/linux/ath79/dts/ar9331_tplink_tl-wr710n.dtsi | 2 +- .../ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts | 2 +- target/linux/ath79/dts/ar9344_qihoo_c301.dts | 4 ++-- target/linux/ath79/dts/qca9531_tplink_tl-wr810n-v1.dts | 2 +- target/linux/ath79/dts/qca9558_aruba_ap-115.dts | 2 +- target/linux/ath79/dts/qca9558_sophos_ap.dtsi | 2 +- target/linux/ath79/dts/qca9558_tplink_archer-d7.dtsi | 4 ++-- 17 files changed, 19 insertions(+), 19 deletions(-) diff --git a/target/linux/ath79/dts/ar7242_avm_fritz300e.dts b/target/linux/ath79/dts/ar7242_avm_fritz300e.dts index 310a2b1ee2..7a0d7dd268 100644 --- a/target/linux/ath79/dts/ar7242_avm_fritz300e.dts +++ b/target/linux/ath79/dts/ar7242_avm_fritz300e.dts @@ -85,7 +85,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpio 11 GPIO_ACTIVE_LOW>; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; startup-delay-us = <300000>; enable-active-high; diff --git a/target/linux/ath79/dts/ar9331_glinet_gl-mifi.dts b/target/linux/ath79/dts/ar9331_glinet_gl-mifi.dts index 211c565c24..e4d2ff1e11 100644 --- a/target/linux/ath79/dts/ar9331_glinet_gl-mifi.dts +++ b/target/linux/ath79/dts/ar9331_glinet_gl-mifi.dts @@ -54,7 +54,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; }; gpio-export { diff --git a/target/linux/ath79/dts/ar9331_hiwifi_hc6361.dts b/target/linux/ath79/dts/ar9331_hiwifi_hc6361.dts index 3751374af6..b10f7fc965 100644 --- a/target/linux/ath79/dts/ar9331_hiwifi_hc6361.dts +++ b/target/linux/ath79/dts/ar9331_hiwifi_hc6361.dts @@ -52,7 +52,7 @@ regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; enable-active-high; - gpio = <&gpio 20 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 20 GPIO_ACTIVE_HIGH>; }; }; diff --git a/target/linux/ath79/dts/ar9331_onion_omega.dts b/target/linux/ath79/dts/ar9331_onion_omega.dts index 81fab872b5..5d9e96e048 100644 --- a/target/linux/ath79/dts/ar9331_onion_omega.dts +++ b/target/linux/ath79/dts/ar9331_onion_omega.dts @@ -43,7 +43,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9331_pisen_wmm003n.dts b/target/linux/ath79/dts/ar9331_pisen_wmm003n.dts index 61cbb1aae2..63f394a4f9 100644 --- a/target/linux/ath79/dts/ar9331_pisen_wmm003n.dts +++ b/target/linux/ath79/dts/ar9331_pisen_wmm003n.dts @@ -41,7 +41,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9331_teltonika_rut230-v1.dts b/target/linux/ath79/dts/ar9331_teltonika_rut230-v1.dts index 69965f86a8..ad987dbca1 100644 --- a/target/linux/ath79/dts/ar9331_teltonika_rut230-v1.dts +++ b/target/linux/ath79/dts/ar9331_teltonika_rut230-v1.dts @@ -101,7 +101,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 19 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 19 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9331_tplink_tl-mr10u.dts b/target/linux/ath79/dts/ar9331_tplink_tl-mr10u.dts index 3597a0d1bb..20f412e918 100644 --- a/target/linux/ath79/dts/ar9331_tplink_tl-mr10u.dts +++ b/target/linux/ath79/dts/ar9331_tplink_tl-mr10u.dts @@ -8,5 +8,5 @@ }; ®_usb_vbus { - gpio = <&gpio 18 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; }; diff --git a/target/linux/ath79/dts/ar9331_tplink_tl-mr3020-v1.dts b/target/linux/ath79/dts/ar9331_tplink_tl-mr3020-v1.dts index 7a1a577ed7..7b307cd6d0 100644 --- a/target/linux/ath79/dts/ar9331_tplink_tl-mr3020-v1.dts +++ b/target/linux/ath79/dts/ar9331_tplink_tl-mr3020-v1.dts @@ -76,7 +76,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9331_tplink_tl-mr3040-v2.dts b/target/linux/ath79/dts/ar9331_tplink_tl-mr3040-v2.dts index b07f9a7820..91023111a6 100644 --- a/target/linux/ath79/dts/ar9331_tplink_tl-mr3040-v2.dts +++ b/target/linux/ath79/dts/ar9331_tplink_tl-mr3040-v2.dts @@ -72,7 +72,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 18 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9331_tplink_tl-wr703n.dts b/target/linux/ath79/dts/ar9331_tplink_tl-wr703n.dts index 0806bcc170..7fb87dab0f 100644 --- a/target/linux/ath79/dts/ar9331_tplink_tl-wr703n.dts +++ b/target/linux/ath79/dts/ar9331_tplink_tl-wr703n.dts @@ -8,5 +8,5 @@ }; ®_usb_vbus { - gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; }; diff --git a/target/linux/ath79/dts/ar9331_tplink_tl-wr710n.dtsi b/target/linux/ath79/dts/ar9331_tplink_tl-wr710n.dtsi index 329822ad10..303cb566ab 100644 --- a/target/linux/ath79/dts/ar9331_tplink_tl-wr710n.dtsi +++ b/target/linux/ath79/dts/ar9331_tplink_tl-wr710n.dtsi @@ -38,7 +38,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts index 9faddcc37f..121a5d0396 100644 --- a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts @@ -20,7 +20,7 @@ compatible = "mikrotik,gpio-rb91x-key"; gpio-controller; #gpio-cells = <2>; - gpio = <&gpio 15 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; gpio_latch: gpio_latch { diff --git a/target/linux/ath79/dts/ar9344_qihoo_c301.dts b/target/linux/ath79/dts/ar9344_qihoo_c301.dts index bf6706716f..d7e2e24239 100644 --- a/target/linux/ath79/dts/ar9344_qihoo_c301.dts +++ b/target/linux/ath79/dts/ar9344_qihoo_c301.dts @@ -48,7 +48,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; - gpio = <&gpio 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; }; usb_vbus: reg_usb_vbus { @@ -57,7 +57,7 @@ regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; enable-active-high; - gpio = <&gpio 19 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 19 GPIO_ACTIVE_HIGH>; }; }; diff --git a/target/linux/ath79/dts/qca9531_tplink_tl-wr810n-v1.dts b/target/linux/ath79/dts/qca9531_tplink_tl-wr810n-v1.dts index 227f57b9b4..6f96b61392 100644 --- a/target/linux/ath79/dts/qca9531_tplink_tl-wr810n-v1.dts +++ b/target/linux/ath79/dts/qca9531_tplink_tl-wr810n-v1.dts @@ -11,7 +11,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-always-on; }; diff --git a/target/linux/ath79/dts/qca9558_aruba_ap-115.dts b/target/linux/ath79/dts/qca9558_aruba_ap-115.dts index c15cb677b9..9d95282451 100644 --- a/target/linux/ath79/dts/qca9558_aruba_ap-115.dts +++ b/target/linux/ath79/dts/qca9558_aruba_ap-115.dts @@ -83,7 +83,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 3 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 3 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-always-on; }; diff --git a/target/linux/ath79/dts/qca9558_sophos_ap.dtsi b/target/linux/ath79/dts/qca9558_sophos_ap.dtsi index 8abd3e60b7..0cf5eb6e66 100644 --- a/target/linux/ath79/dts/qca9558_sophos_ap.dtsi +++ b/target/linux/ath79/dts/qca9558_sophos_ap.dtsi @@ -62,7 +62,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-boot-on; status = "disabled"; diff --git a/target/linux/ath79/dts/qca9558_tplink_archer-d7.dtsi b/target/linux/ath79/dts/qca9558_tplink_archer-d7.dtsi index c4d910bf1e..35532f42c8 100644 --- a/target/linux/ath79/dts/qca9558_tplink_archer-d7.dtsi +++ b/target/linux/ath79/dts/qca9558_tplink_archer-d7.dtsi @@ -72,7 +72,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 21 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 21 GPIO_ACTIVE_HIGH>; enable-active-high; }; @@ -81,7 +81,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio 22 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; From 2e6ec200dfe6ee62380821bc001d0b546bc6f799 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 1 Dec 2023 14:32:23 -0800 Subject: [PATCH 036/222] ath79: move kernel and ubi into subnodes Avoids dtc warnings regarding two sections having the same numbers. X: duplicate unit-address (also used in node Y) Signed-off-by: Rosen Penev --- .../linux/ath79/dts/ar9344_netgear_wndr.dtsi | 29 ++++++++++--------- .../linux/ath79/dts/qca9558_zyxel_nbg6716.dts | 20 ++++++++----- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/target/linux/ath79/dts/ar9344_netgear_wndr.dtsi b/target/linux/ath79/dts/ar9344_netgear_wndr.dtsi index d2a3000004..49057548f8 100644 --- a/target/linux/ath79/dts/ar9344_netgear_wndr.dtsi +++ b/target/linux/ath79/dts/ar9344_netgear_wndr.dtsi @@ -90,7 +90,7 @@ #address-cells = <1>; #size-cells = <1>; - ubi@ac0000 { + ubi@0 { label = "ubi"; reg = <0x0 0x7500000>; }; @@ -171,22 +171,23 @@ reg = <0x3c0000 0x300000>; }; - kernel@6c0000 { - label = "kernel"; - reg = <0x6c0000 0x400000>; - }; - - ubiconcat0: partition@ac0000 { - label = "ubiconcat0"; - reg = <0xac0000 0x1500000>; - }; - partition@6c0000 { label = "firmware"; reg = <0x6c0000 0x1900000>; - compatible = "openwrt,uimage", "denx,uimage"; - openwrt,ih-magic = <0x33373033>; - openwrt,ih-type = ; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + kernel@0 { + label = "kernel"; + reg = <0x0 0x400000>; + }; + + ubiconcat0: partition@400000 { + label = "ubiconcat0"; + reg = <0x400000 0x1500000>; + }; }; partition@1fc0000 { diff --git a/target/linux/ath79/dts/qca9558_zyxel_nbg6716.dts b/target/linux/ath79/dts/qca9558_zyxel_nbg6716.dts index 9aee8c362c..20230e684e 100644 --- a/target/linux/ath79/dts/qca9558_zyxel_nbg6716.dts +++ b/target/linux/ath79/dts/qca9558_zyxel_nbg6716.dts @@ -143,16 +143,20 @@ firmware@500000 { label = "firmware"; reg = <0x500000 0x7b00000>; - }; - partition@500000 { - label = "kernel"; - reg = <0x500000 0x400000>; - }; + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; - partition@900000 { - label = "ubi"; - reg = <0x900000 0x7700000>; + partition@0 { + label = "kernel"; + reg = <0x0 0x400000>; + }; + + partition@400000 { + label = "ubi"; + reg = <0x400000 0x7700000>; + }; }; }; }; From e4a43cda0efba562d0ed1973b584c21309040ccc Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 17 May 2022 17:50:23 -0400 Subject: [PATCH 037/222] build: allow var.% targets to bypass the prepare steps These targets are used to input variable values from the Make context into other things like python scripts, so log messages should be silenced and build prerequisites should be skipped. The same thing is done for the other variable print target "val.%". While at it, combine identical target rules into one definition. Signed-off-by: Michael Pratt --- include/toplevel.mk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/toplevel.mk b/include/toplevel.mk index 328214be1b..96f32139d9 100644 --- a/include/toplevel.mk +++ b/include/toplevel.mk @@ -210,9 +210,7 @@ prereq:: prepare-tmpinfo .config @+$(NO_TRACE_MAKE) -r -s $@ check: .config FORCE - @+$(NO_TRACE_MAKE) -r -s $@ QUIET= V=s - -val.%: FORCE +check val.% var.%: FORCE @+$(NO_TRACE_MAKE) -r -s $@ QUIET= V=s WARN_PARALLEL_ERROR = $(if $(BUILD_LOG),,$(and $(filter -j,$(MAKEFLAGS)),$(findstring s,$(OPENWRT_VERBOSE)))) From fd3376c5eeccc1f1753483ed31ffff03808ce31d Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 24 Nov 2023 05:10:12 -0500 Subject: [PATCH 038/222] build: ensure silent Make behavior for json scripts Run the invocation of Make with verbosity in order to prevent the printing of Makefile level and subtarget status. e.g. make[3] -C target/linux val.DEFAULT_PACKAGES val.ARCH_PACKAGES Remove piping of stderr, which is only useful when using the "communicate" method over the "run" method, and this script would not be written to handle a captured error anyway. For error testing, stdout and stderr can be set to a file object with the open() function like this: out = open('json_out', 'w') err = open('json_err', 'w') ... ... stdout=out, stderr=err, Signed-off-by: Michael Pratt --- scripts/json_overview_image_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/json_overview_image_info.py b/scripts/json_overview_image_info.py index 89b7d4fe20..0d2cf7f1ef 100755 --- a/scripts/json_overview_image_info.py +++ b/scripts/json_overview_image_info.py @@ -55,9 +55,9 @@ if output: "target/linux/", "val.DEFAULT_PACKAGES", "val.ARCH_PACKAGES", + "V=s", ], stdout=PIPE, - stderr=PIPE, check=True, env=environ.copy().update({"TOPDIR": Path().cwd()}), universal_newlines=True, From 14a3eadf059dd3f7db75ab88e89cf25d0d1680da Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 17 May 2022 23:06:36 -0400 Subject: [PATCH 039/222] verbose.mk: fallback to standard file descriptors In order to pass a status message at runtime, which is usually listing subtargets of a Makefile target or an error message, from a child invocation of Make (submake) through the parent process to the terminal, the file descriptors 8 and 9 are opened to be used by the functions MESSAGE and ERROR_MESSAGE. However, there are situations where those functions can be called while not in a submake or a subshell or a child process which results in a shell error: /bin/bash: 8: Bad file descriptor Commit aee3594ffcb72ae3e18c3719012d52519ee2d160 ("verbose.mk: print ERROR messages in non-verbose") has exposed this issue to more cases, but it is not the root cause. To solve this, use the exit code of the first printf attempt to the alternative file descriptors in order to tell whether the standard file descriptors need to be used instead. In order to get rid of the "Bad file descriptor" error, stderr is redirected to null after grouping the two printf alternatives into one command to combine outputs. For ERROR_MESSAGE, the real message is redirected to stderr after redirecting the error from the attempted printing to null. For MESSAGE, without redirection, the Make function "shell" will absorb the actual message from stdout and input the value into the Makefile, therefore the dummy variable "_NULL", previously used merely for causing a call to the MESSAGE function to trigger without writing target rules, now has and a real value when defined, so rename it to "_MESSAGE" as a placeholder for the real message when the output should be stdout. When "_MESSAGE" has a value, use Make function "info" to finally bring it from the Makefile to the terminal. This also fixes what is likely a typo, in that while file descriptor 9 is meant to redirect to stderr for use in error messages like in the function ERROR_MESSAGE, that function has printf redirecting to file descriptor 8 instead. Fixes: a4c8d4e37 ("build: make the color of the 'configuration out of sync' warning red") Signed-off-by: Michael Pratt --- include/verbose.mk | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/include/verbose.mk b/include/verbose.mk index 4487a207e8..f6aa0d7012 100644 --- a/include/verbose.mk +++ b/include/verbose.mk @@ -30,12 +30,18 @@ ifeq ($(IS_TTY),1) endif define ERROR_MESSAGE - printf "$(_R)%s$(_N)\n" "$(1)" >&8 + { \ + printf "$(_R)%s$(_N)\n" "$(1)" >&9 || \ + printf "$(_R)%s$(_N)\n" "$(1)"; \ + } >&2 2>/dev/null endef ifeq ($(findstring s,$(OPENWRT_VERBOSE)),) define MESSAGE - printf "$(_Y)%s$(_N)\n" "$(1)" >&8 + { \ + printf "$(_Y)%s$(_N)\n" "$(1)" >&8 || \ + printf "$(_Y)%s$(_N)\n" "$(1)"; \ + } 2>/dev/null endef ifeq ($(QUIET),1) @@ -44,9 +50,12 @@ ifeq ($(findstring s,$(OPENWRT_VERBOSE)),) else _DIR:= endif - _NULL:=$(if $(MAKECMDGOALS),$(shell \ + _MESSAGE:=$(if $(MAKECMDGOALS),$(shell \ $(call MESSAGE, make[$(MAKELEVEL)]$(if $(_DIR), -C $(_DIR)) $(MAKECMDGOALS)); \ )) + ifneq ($(strip $(_MESSAGE)),) + $(info $(_MESSAGE)) + endif SUBMAKE=$(MAKE) else SILENT:=>/dev/null $(if $(findstring w,$(OPENWRT_VERBOSE)),,2>&1) From 6ca8752a9cadac810f8541ec1be67d02265175aa Mon Sep 17 00:00:00 2001 From: Rany Hany Date: Wed, 3 Jan 2024 18:43:33 +0200 Subject: [PATCH 040/222] mac80211: add missing newline for "min_tx_power" This prevents min_tx_power from functioning properly in some circumstances. Add the missing newline. Signed-off-by: Rany Hany --- package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 1bf4db6e5f..b5378e556e 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -145,7 +145,7 @@ mac80211_hostapd_setup_base() { [ "$auto_channel" = 0 ] && [ -z "$channel_list" ] && \ channel_list="$channel" - [ "$min_tx_power" -gt 0 ] && append base_cfg "min_tx_power=$min_tx_power" + [ "$min_tx_power" -gt 0 ] && append base_cfg "min_tx_power=$min_tx_power" "$N" set_default noscan 0 From ce4ee14a46f54403380afac88af912940f8f5ca8 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 15 Oct 2023 13:53:11 -0700 Subject: [PATCH 041/222] ag71xx: fix wrong register definition issue Documentation fix from QCA SDK. Signed-off-by: Rosen Penev --- .../net/ethernet/atheros/ag71xx/ag71xx.h | 38 +++++++++---------- .../net/ethernet/atheros/ag71xx/ag71xx_main.c | 10 ++--- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h index 0773f1a5af..fca072a83a 100644 --- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h @@ -310,11 +310,11 @@ ag71xx_ring_size_order(int size) #define FIFO_CFG4_MC BIT(8) /* Multicast Packet */ #define FIFO_CFG4_BC BIT(9) /* Broadcast Packet */ #define FIFO_CFG4_DR BIT(10) /* Dribble */ -#define FIFO_CFG4_LE BIT(11) /* Long Event */ -#define FIFO_CFG4_CF BIT(12) /* Control Frame */ -#define FIFO_CFG4_PF BIT(13) /* Pause Frame */ -#define FIFO_CFG4_UO BIT(14) /* Unsupported Opcode */ -#define FIFO_CFG4_VT BIT(15) /* VLAN tag detected */ +#define FIFO_CFG4_CF BIT(11) /* Control Frame */ +#define FIFO_CFG4_PF BIT(12) /* Pause Frame */ +#define FIFO_CFG4_UO BIT(13) /* Unsupported Opcode */ +#define FIFO_CFG4_VT BIT(14) /* VLAN tag detected */ +#define FIFO_CFG4_LE BIT(15) /* Long Event */ #define FIFO_CFG4_FT BIT(16) /* Frame Truncated */ #define FIFO_CFG4_UC BIT(17) /* Unicast Packet */ @@ -322,20 +322,20 @@ ag71xx_ring_size_order(int size) #define FIFO_CFG5_DV BIT(1) /* RX_DV Event */ #define FIFO_CFG5_FC BIT(2) /* False Carrier */ #define FIFO_CFG5_CE BIT(3) /* Code Error */ -#define FIFO_CFG5_LM BIT(4) /* Length Mismatch */ -#define FIFO_CFG5_LO BIT(5) /* Length Out of Range */ -#define FIFO_CFG5_OK BIT(6) /* Packet is OK */ -#define FIFO_CFG5_MC BIT(7) /* Multicast Packet */ -#define FIFO_CFG5_BC BIT(8) /* Broadcast Packet */ -#define FIFO_CFG5_DR BIT(9) /* Dribble */ -#define FIFO_CFG5_CF BIT(10) /* Control Frame */ -#define FIFO_CFG5_PF BIT(11) /* Pause Frame */ -#define FIFO_CFG5_UO BIT(12) /* Unsupported Opcode */ -#define FIFO_CFG5_VT BIT(13) /* VLAN tag detected */ -#define FIFO_CFG5_LE BIT(14) /* Long Event */ -#define FIFO_CFG5_FT BIT(15) /* Frame Truncated */ -#define FIFO_CFG5_16 BIT(16) /* unknown */ -#define FIFO_CFG5_17 BIT(17) /* unknown */ +#define FIFO_CFG5_CR BIT(4) /* CRC error */ +#define FIFO_CFG5_LM BIT(5) /* Length Mismatch */ +#define FIFO_CFG5_LO BIT(6) /* Length out of range */ +#define FIFO_CFG5_OK BIT(7) /* Packet is OK */ +#define FIFO_CFG5_MC BIT(8) /* Multicast Packet */ +#define FIFO_CFG5_BC BIT(9) /* Broadcast Packet */ +#define FIFO_CFG5_DR BIT(10) /* Dribble */ +#define FIFO_CFG5_CF BIT(11) /* Control Frame */ +#define FIFO_CFG5_PF BIT(12) /* Pause Frame */ +#define FIFO_CFG5_UO BIT(13) /* Unsupported Opcode */ +#define FIFO_CFG5_VT BIT(14) /* VLAN tag detected */ +#define FIFO_CFG5_LE BIT(15) /* Long Event */ +#define FIFO_CFG5_FT BIT(16) /* Frame Truncated */ +#define FIFO_CFG5_UC BIT(17) /* Unicast Packet */ #define FIFO_CFG5_SF BIT(18) /* Short Frame */ #define FIFO_CFG5_BM BIT(19) /* Byte Mode */ diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c index 8f95210e0f..8a5cd3bcde 100644 --- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c +++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c @@ -407,11 +407,11 @@ static void ag71xx_dma_reset(struct ag71xx *ag) FIFO_CFG4_VT) #define FIFO_CFG5_INIT (FIFO_CFG5_DE | FIFO_CFG5_DV | FIFO_CFG5_FC | \ - FIFO_CFG5_CE | FIFO_CFG5_LO | FIFO_CFG5_OK | \ - FIFO_CFG5_MC | FIFO_CFG5_BC | FIFO_CFG5_DR | \ - FIFO_CFG5_CF | FIFO_CFG5_PF | FIFO_CFG5_VT | \ - FIFO_CFG5_LE | FIFO_CFG5_FT | FIFO_CFG5_16 | \ - FIFO_CFG5_17 | FIFO_CFG5_SF) + FIFO_CFG5_CE | FIFO_CFG5_LM | FIFO_CFG5_LO | \ + FIFO_CFG5_OK | FIFO_CFG5_MC | FIFO_CFG5_BC | \ + FIFO_CFG5_DR | FIFO_CFG5_CF | FIFO_CFG5_UO | \ + FIFO_CFG5_VT | FIFO_CFG5_LE | FIFO_CFG5_FT | \ + FIFO_CFG5_UC | FIFO_CFG5_SF) static void ag71xx_hw_stop(struct ag71xx *ag) { From 3acd5843611fd0902096871e97755ccef47803ba Mon Sep 17 00:00:00 2001 From: Michael 'ASAP' Weinrich Date: Sun, 1 Oct 2023 00:03:51 -0700 Subject: [PATCH 042/222] realtek: fix network connectivity on GS750E Currently OpenWRT does not know how to properly reset the network switch. This would result in a switch that seemed to come up properly but was unable to handle any traffic. Presumably something earlier in the boot chain is configuring a part of the switch that gets wiped out when its reset. For now comment out the reset GPIO entry in the device tree until the driver better supports bringing up the switch after a reset. Signed-off-by: Michael 'ASAP' Weinrich --- target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts b/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts index 750af3e94f..1d1e08db94 100644 --- a/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts +++ b/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts @@ -107,7 +107,8 @@ compatible = "realtek,rtl838x-mdio"; #address-cells = <1>; #size-cells = <0>; - reset-gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; + // Switch doesn't come back properly after a reset so don't. + // reset-gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; /* External phy RTL8218B #1 */ EXTERNAL_PHY(0) From f1de1a090fadc74504b3ee1b5bcb914c9110bc6f Mon Sep 17 00:00:00 2001 From: Michael 'ASAP' Weinrich Date: Thu, 4 Jan 2024 15:42:07 -0500 Subject: [PATCH 043/222] realtek: correct typo in port numbering Port 10 was incorrectly labelled as nonexistent port 0. Signed-off-by: Michael 'ASAP' Weinrich --- target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts b/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts index 1d1e08db94..5a7ed276bf 100644 --- a/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts +++ b/target/linux/realtek/dts-5.15/rtl8393_netgear_gs750e.dts @@ -191,7 +191,7 @@ SWITCH_PORT(7, 8, qsgmii) SWITCH_PORT(8, 9, qsgmii) - SWITCH_PORT(9, 0, qsgmii) + SWITCH_PORT(9, 10, qsgmii) SWITCH_PORT(10, 11, qsgmii) SWITCH_PORT(11, 12, qsgmii) SWITCH_PORT(12, 13, qsgmii) From bcdab304678f0ea5ae2d57eb93c946e9416583cf Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sun, 29 Oct 2023 08:47:17 +0000 Subject: [PATCH 044/222] mediatek: MERCUSYS MR90X v1: remove deprecated led "label" properties This commit: 1. Removes deprecated "label" property from the dts leds subnnodes; 2. Updates "01_leds" script. Link: https://www.kernel.org/doc/Documentation/devicetree/bindings/leds/common.yaml Link: https://www.kernel.org/doc/Documentation/devicetree/bindings/leds/leds-gpio.yaml Signed-off-by: Mikhail Zhilkin --- .../dts/mt7986b-mercusys-mr90x-v1.dts | 24 +++++++++++++------ .../filogic/base-files/etc/board.d/01_leds | 6 ++--- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts b/target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts index 42250be19a..f0a995820e 100644 --- a/target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts +++ b/target/linux/mediatek/dts/mt7986b-mercusys-mr90x-v1.dts @@ -3,6 +3,7 @@ /dts-v1/; #include #include +#include #include "mt7986b.dtsi" @@ -41,34 +42,43 @@ compatible = "gpio-leds"; led-0 { - label = "green:lan2"; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; gpios = <&pio 7 GPIO_ACTIVE_LOW>; }; led-1 { - label = "green:lan1"; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; gpios = <&pio 9 GPIO_ACTIVE_LOW>; }; led-2 { - label = "green:lan0"; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <0>; gpios = <&pio 12 GPIO_ACTIVE_LOW>; }; led-3 { - label = "green:wan"; + color = ; + function = LED_FUNCTION_WAN; gpios = <&pio 13 GPIO_ACTIVE_LOW>; }; led-4 { - label = "orange:status"; + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 16 GPIO_ACTIVE_HIGH>; + panic-indicator; }; led_status_green: led-5 { - label = "green:status"; + color = ; + function = LED_FUNCTION_STATUS; gpios = <&pio 17 GPIO_ACTIVE_HIGH>; - panic-indicator; }; }; }; diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds index 360bdea9c8..b786558618 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds @@ -16,9 +16,9 @@ cudy,wr3000-v1) ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" ;; mercusys,mr90x-v1) - ucidef_set_led_netdev "lan0" "lan0" "green:lan0" "lan0" "link tx rx" - ucidef_set_led_netdev "lan1" "lan2" "green:lan1" "lan1" "link tx rx" - ucidef_set_led_netdev "lan2" "lan2" "green:lan2" "lan2" "link tx rx" + ucidef_set_led_netdev "lan-0" "lan-0" "green:lan-0" "lan0" "link tx rx" + ucidef_set_led_netdev "lan-1" "lan-1" "green:lan-1" "lan1" "link tx rx" + ucidef_set_led_netdev "lan-2" "lan-2" "green:lan-2" "lan2" "link tx rx" ucidef_set_led_netdev "wan" "wan" "green:wan" "eth1" "link tx rx" ;; netgear,wax220) From 37bb3893929fc3277e7d26ff0012d86526c98b77 Mon Sep 17 00:00:00 2001 From: John Audia Date: Fri, 5 Jan 2024 15:40:08 -0500 Subject: [PATCH 045/222] kernel: bump 5.15 to 5.15.146 Changelog: https://cdn.kernel.org/pub/linux/kernel/v5.x/ChangeLog-5.15.146 Removed upstreamed: generic/hack-5.15/940-ksmbd-have-a-dependency-on-cifs-arc4.patch[1] All other patches automatically rebased. 1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.15.146&id=ac385518598f50dd1b9b41bd05f50ce9795481d5 Build system: x86_64 Build-tested: ramips/tplink_archer-a6-v3 Run-tested: ramips/tplink_archer-a6-v3 Signed-off-by: John Audia --- include/kernel-5.15 | 4 +-- .../209-b44-register-adm-switch.patch | 6 ++-- .../patches-5.15/210-b44_phy_fix.patch | 6 ++-- ...net-usb-ax88179_178a-add-TSO-feature.patch | 6 ++-- ...v6.4-0003-of-Rename-of_modalias_node.patch | 2 +- .../721-net-add-packet-mangeling.patch | 2 +- .../780-usb-net-MeigLink_modem_support.patch | 4 +-- ...ksmbd-have-a-dependency-on-cifs-arc4.patch | 31 ------------------- ...T-skip-GRO-for-foreign-MAC-addresses.patch | 10 +++--- ...ional-threading-for-backlog-processi.patch | 18 +++++------ ...-Add-support-for-dynamic-calibration.patch | 6 ++-- ...move-drivers-from-strlcpy-to-strscpy.patch | 2 +- 12 files changed, 33 insertions(+), 64 deletions(-) delete mode 100644 target/linux/generic/hack-5.15/940-ksmbd-have-a-dependency-on-cifs-arc4.patch diff --git a/include/kernel-5.15 b/include/kernel-5.15 index 2948d10bdc..f8ecac5742 100644 --- a/include/kernel-5.15 +++ b/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .145 -LINUX_KERNEL_HASH-5.15.145 = b2a49d87605f3a9491581150315e22337c1afb599efc1e2737481be3a2d6d620 +LINUX_VERSION-5.15 = .146 +LINUX_KERNEL_HASH-5.15.146 = 5a807a5fa2a80ada957d8079681dfb5cc196ec26f43244d1c8a4fd7af592d192 diff --git a/target/linux/bcm47xx/patches-5.15/209-b44-register-adm-switch.patch b/target/linux/bcm47xx/patches-5.15/209-b44-register-adm-switch.patch index 7728ec1094..772e905ecb 100644 --- a/target/linux/bcm47xx/patches-5.15/209-b44-register-adm-switch.patch +++ b/target/linux/bcm47xx/patches-5.15/209-b44-register-adm-switch.patch @@ -19,7 +19,7 @@ Subject: [PATCH 210/210] b44: register adm switch #include #include -@@ -2243,6 +2245,69 @@ static void b44_adjust_link(struct net_d +@@ -2245,6 +2247,69 @@ static void b44_adjust_link(struct net_d } } @@ -89,7 +89,7 @@ Subject: [PATCH 210/210] b44: register adm switch static int b44_register_phy_one(struct b44 *bp) { __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; -@@ -2279,6 +2344,9 @@ static int b44_register_phy_one(struct b +@@ -2281,6 +2346,9 @@ static int b44_register_phy_one(struct b if (!mdiobus_is_registered_device(bp->mii_bus, bp->phy_addr) && (sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM))) { @@ -99,7 +99,7 @@ Subject: [PATCH 210/210] b44: register adm switch dev_info(sdev->dev, "could not find PHY at %i, use fixed one\n", bp->phy_addr); -@@ -2473,6 +2541,7 @@ static void b44_remove_one(struct ssb_de +@@ -2475,6 +2543,7 @@ static void b44_remove_one(struct ssb_de unregister_netdev(dev); if (bp->flags & B44_FLAG_EXTERNAL_PHY) b44_unregister_phy_one(bp); diff --git a/target/linux/bcm47xx/patches-5.15/210-b44_phy_fix.patch b/target/linux/bcm47xx/patches-5.15/210-b44_phy_fix.patch index bedebc415e..ca7123f2a3 100644 --- a/target/linux/bcm47xx/patches-5.15/210-b44_phy_fix.patch +++ b/target/linux/bcm47xx/patches-5.15/210-b44_phy_fix.patch @@ -1,6 +1,6 @@ --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c -@@ -429,10 +429,34 @@ static void b44_wap54g10_workaround(stru +@@ -430,10 +430,34 @@ static void b44_wap54g10_workaround(stru error: pr_warn("PHY: cannot reset MII transceiver isolate bit\n"); } @@ -35,7 +35,7 @@ #endif static int b44_setup_phy(struct b44 *bp) -@@ -441,6 +465,7 @@ static int b44_setup_phy(struct b44 *bp) +@@ -442,6 +466,7 @@ static int b44_setup_phy(struct b44 *bp) int err; b44_wap54g10_workaround(bp); @@ -43,7 +43,7 @@ if (bp->flags & B44_FLAG_EXTERNAL_PHY) return 0; -@@ -2173,6 +2198,8 @@ static int b44_get_invariants(struct b44 +@@ -2175,6 +2200,8 @@ static int b44_get_invariants(struct b44 * valid PHY address. */ bp->phy_addr &= 0x1F; diff --git a/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch b/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch index a2168aaba5..598fa05e9b 100644 --- a/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch +++ b/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch @@ -18,7 +18,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c -@@ -1377,11 +1377,12 @@ static int ax88179_bind(struct usbnet *d +@@ -1363,11 +1363,12 @@ static int ax88179_bind(struct usbnet *d dev->mii.phy_id = 0x03; dev->mii.supports_gmii = 1; @@ -35,7 +35,7 @@ Signed-off-by: David S. Miller /* Enable checksum offload */ *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | -@@ -1587,17 +1588,19 @@ ax88179_tx_fixup(struct usbnet *dev, str +@@ -1573,17 +1574,19 @@ ax88179_tx_fixup(struct usbnet *dev, str { u32 tx_hdr1, tx_hdr2; int frame_size = dev->maxpacket; @@ -57,7 +57,7 @@ Signed-off-by: David S. Miller if ((skb_header_cloned(skb) || headroom < 0) && pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) { dev_kfree_skb_any(skb); -@@ -1608,6 +1611,8 @@ ax88179_tx_fixup(struct usbnet *dev, str +@@ -1594,6 +1597,8 @@ ax88179_tx_fixup(struct usbnet *dev, str put_unaligned_le32(tx_hdr1, ptr); put_unaligned_le32(tx_hdr2, ptr + 4); diff --git a/target/linux/generic/backport-5.15/828-v6.4-0003-of-Rename-of_modalias_node.patch b/target/linux/generic/backport-5.15/828-v6.4-0003-of-Rename-of_modalias_node.patch index 6c20521701..855d45311e 100644 --- a/target/linux/generic/backport-5.15/828-v6.4-0003-of-Rename-of_modalias_node.patch +++ b/target/linux/generic/backport-5.15/828-v6.4-0003-of-Rename-of_modalias_node.patch @@ -148,7 +148,7 @@ Signed-off-by: Greg Kroah-Hartman * of_find_node_by_phandle - Find a node given a phandle --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -2128,8 +2128,8 @@ of_register_spi_device(struct spi_contro +@@ -2140,8 +2140,8 @@ of_register_spi_device(struct spi_contro } /* Select device driver */ diff --git a/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch index 262a58036e..b03b4a674f 100644 --- a/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-5.15/721-net-add-packet-mangeling.patch @@ -116,7 +116,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3597,6 +3597,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3600,6 +3600,11 @@ static int xmit_one(struct sk_buff *skb, if (dev_nit_active(dev)) dev_queue_xmit_nit(skb, dev); diff --git a/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch index 60f02f7143..0060fbbd2a 100644 --- a/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch +++ b/target/linux/generic/hack-5.15/780-usb-net-MeigLink_modem_support.patch @@ -43,7 +43,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support #define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ -@@ -1146,6 +1151,11 @@ static const struct usb_device_id option +@@ -1147,6 +1152,11 @@ static const struct usb_device_id option { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000), /* SIMCom SIM5218 */ .driver_info = NCTRL(0) | NCTRL(1) | NCTRL(2) | NCTRL(3) | RSVD(4) }, @@ -55,7 +55,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support /* Quectel products using Qualcomm vendor ID */ { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)}, { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20), -@@ -1187,6 +1197,11 @@ static const struct usb_device_id option +@@ -1188,6 +1198,11 @@ static const struct usb_device_id option .driver_info = ZLP }, { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), .driver_info = RSVD(4) }, diff --git a/target/linux/generic/hack-5.15/940-ksmbd-have-a-dependency-on-cifs-arc4.patch b/target/linux/generic/hack-5.15/940-ksmbd-have-a-dependency-on-cifs-arc4.patch deleted file mode 100644 index 4cf420a859..0000000000 --- a/target/linux/generic/hack-5.15/940-ksmbd-have-a-dependency-on-cifs-arc4.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Namjae Jeon -To: sashal@kernel.org, gregkh@linuxfoundation.org, stable@vger.kernel.org -Cc: smfrench@gmail.com, Namjae Jeon -Subject: [PATCH v2 5.15.y 1/8] ksmbd: have a dependency on cifs ARC4 -Date: Wed, 27 Dec 2023 19:25:58 +0900 [thread overview] -Message-ID: <20231227102605.4766-2-linkinjeon@kernel.org> (raw) -In-Reply-To: <20231227102605.4766-1-linkinjeon@kernel.org> - -Omitted the change that has a dependency on cifs ARC4 from backporting -commit f9929ef6a2a5("ksmbd: add support for key exchange"). -This patch make ksmbd have a dependeny on cifs ARC4. - -Fixes: c5049d2d73b2 ("ksmbd: add support for key exchange") -Signed-off-by: Namjae Jeon ---- - fs/Kconfig | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/fs/Kconfig -+++ b/fs/Kconfig -@@ -369,8 +369,8 @@ source "fs/ksmbd/Kconfig" - - config SMBFS_COMMON - tristate -- default y if CIFS=y -- default m if CIFS=m -+ default y if CIFS=y || SMB_SERVER=y -+ default m if CIFS=m || SMB_SERVER=m - - source "fs/coda/Kconfig" - source "fs/afs/Kconfig" diff --git a/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index 89b0c9f53c..c6a6c6e797 100644 --- a/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/target/linux/generic/pending-5.15/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau __u8 inner_protocol_type:1; --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -6074,6 +6074,9 @@ static enum gro_result dev_gro_receive(s +@@ -6077,6 +6077,9 @@ static enum gro_result dev_gro_receive(s int same_flow; int grow; @@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau if (netif_elide_gro(skb->dev)) goto normal; -@@ -8088,6 +8091,48 @@ static void __netdev_adjacent_dev_unlink +@@ -8091,6 +8094,48 @@ static void __netdev_adjacent_dev_unlink &upper_dev->adj_list.lower); } @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau static int __netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev, bool master, void *upper_priv, void *upper_info, -@@ -8139,6 +8184,7 @@ static int __netdev_upper_dev_link(struc +@@ -8142,6 +8187,7 @@ static int __netdev_upper_dev_link(struc if (ret) return ret; @@ -99,7 +99,7 @@ Signed-off-by: Felix Fietkau ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); ret = notifier_to_errno(ret); -@@ -8235,6 +8281,7 @@ static void __netdev_upper_dev_unlink(st +@@ -8238,6 +8284,7 @@ static void __netdev_upper_dev_unlink(st __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); @@ -107,7 +107,7 @@ Signed-off-by: Felix Fietkau call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); -@@ -9054,6 +9101,7 @@ int dev_set_mac_address(struct net_devic +@@ -9057,6 +9104,7 @@ int dev_set_mac_address(struct net_devic if (err) return err; dev->addr_assign_type = NET_ADDR_SET; diff --git a/target/linux/generic/pending-5.15/760-net-core-add-optional-threading-for-backlog-processi.patch b/target/linux/generic/pending-5.15/760-net-core-add-optional-threading-for-backlog-processi.patch index 685a11f22d..c8d0bc69f9 100644 --- a/target/linux/generic/pending-5.15/760-net-core-add-optional-threading-for-backlog-processi.patch +++ b/target/linux/generic/pending-5.15/760-net-core-add-optional-threading-for-backlog-processi.patch @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau #endif --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -4583,7 +4583,7 @@ static int rps_ipi_queued(struct softnet +@@ -4586,7 +4586,7 @@ static int rps_ipi_queued(struct softnet #ifdef CONFIG_RPS struct softnet_data *mysd = this_cpu_ptr(&softnet_data); @@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau sd->rps_ipi_next = mysd->rps_ipi_list; mysd->rps_ipi_list = sd; -@@ -5764,6 +5764,8 @@ static DEFINE_PER_CPU(struct work_struct +@@ -5767,6 +5767,8 @@ static DEFINE_PER_CPU(struct work_struct /* Network device is going away, flush any packets still pending */ static void flush_backlog(struct work_struct *work) { @@ -48,7 +48,7 @@ Signed-off-by: Felix Fietkau struct sk_buff *skb, *tmp; struct softnet_data *sd; -@@ -5779,9 +5781,18 @@ static void flush_backlog(struct work_st +@@ -5782,9 +5784,18 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -67,7 +67,7 @@ Signed-off-by: Felix Fietkau skb_queue_walk_safe(&sd->process_queue, skb, tmp) { if (skb->dev->reg_state == NETREG_UNREGISTERING) { __skb_unlink(skb, &sd->process_queue); -@@ -5789,7 +5800,18 @@ static void flush_backlog(struct work_st +@@ -5792,7 +5803,18 @@ static void flush_backlog(struct work_st input_queue_head_incr(sd); } } @@ -86,7 +86,7 @@ Signed-off-by: Felix Fietkau } static bool flush_required(int cpu) -@@ -6472,6 +6494,7 @@ static int process_backlog(struct napi_s +@@ -6475,6 +6497,7 @@ static int process_backlog(struct napi_s local_irq_disable(); rps_lock(sd); @@ -94,7 +94,7 @@ Signed-off-by: Felix Fietkau if (skb_queue_empty(&sd->input_pkt_queue)) { /* * Inline a custom version of __napi_complete(). -@@ -6481,7 +6504,8 @@ static int process_backlog(struct napi_s +@@ -6484,7 +6507,8 @@ static int process_backlog(struct napi_s * We can use a plain write instead of clear_bit(), * and we dont need an smp_mb() memory barrier. */ @@ -104,7 +104,7 @@ Signed-off-by: Felix Fietkau again = false; } else { skb_queue_splice_tail_init(&sd->input_pkt_queue, -@@ -6898,6 +6922,57 @@ int dev_set_threaded(struct net_device * +@@ -6901,6 +6925,57 @@ int dev_set_threaded(struct net_device * } EXPORT_SYMBOL(dev_set_threaded); @@ -162,7 +162,7 @@ Signed-off-by: Felix Fietkau void netif_napi_add(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct *, int), int weight) { -@@ -11378,6 +11453,9 @@ static int dev_cpu_dead(unsigned int old +@@ -11381,6 +11456,9 @@ static int dev_cpu_dead(unsigned int old raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); @@ -172,7 +172,7 @@ Signed-off-by: Felix Fietkau #ifdef CONFIG_RPS remsd = oldsd->rps_ipi_list; oldsd->rps_ipi_list = NULL; -@@ -11717,6 +11795,7 @@ static int __init net_dev_init(void) +@@ -11720,6 +11798,7 @@ static int __init net_dev_init(void) sd->cpu = i; #endif diff --git a/target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch b/target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch index 4c980e9438..e795eda3b2 100644 --- a/target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch +++ b/target/linux/mediatek/patches-5.15/432-drivers-spi-Add-support-for-dynamic-calibration.patch @@ -11,7 +11,7 @@ Signed-off-by: SkyLake.Huang --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -1234,6 +1234,70 @@ static int spi_transfer_wait(struct spi_ +@@ -1246,6 +1246,70 @@ static int spi_transfer_wait(struct spi_ return 0; } @@ -82,7 +82,7 @@ Signed-off-by: SkyLake.Huang static void _spi_transfer_delay_ns(u32 ns) { if (!ns) -@@ -2021,6 +2085,75 @@ void spi_flush_queue(struct spi_controll +@@ -2033,6 +2097,75 @@ void spi_flush_queue(struct spi_controll /*-------------------------------------------------------------------------*/ #if defined(CONFIG_OF) @@ -158,7 +158,7 @@ Signed-off-by: SkyLake.Huang static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, struct device_node *nc) { -@@ -2139,6 +2272,10 @@ of_register_spi_device(struct spi_contro +@@ -2151,6 +2284,10 @@ of_register_spi_device(struct spi_contro if (rc) goto err_out; diff --git a/target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch b/target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch index 69f2d2a545..d5c8a4e300 100644 --- a/target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch +++ b/target/linux/mediatek/patches-5.15/850-v6.0-i2c-move-drivers-from-strlcpy-to-strscpy.patch @@ -72,7 +72,7 @@ Signed-off-by: Wolfram Sang idev->adapter.dev.parent = &pdev->dev; --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c -@@ -1028,7 +1028,7 @@ static int aspeed_i2c_probe_bus(struct p +@@ -1044,7 +1044,7 @@ static int aspeed_i2c_probe_bus(struct p bus->adap.algo = &aspeed_i2c_algo; bus->adap.dev.parent = &pdev->dev; bus->adap.dev.of_node = pdev->dev.of_node; From f45fa6b45abf29a0d74c2f2ea4b8e18b6334f2e2 Mon Sep 17 00:00:00 2001 From: John Audia Date: Fri, 5 Jan 2024 15:37:47 -0500 Subject: [PATCH 046/222] kernel: bump 6.1 to 6.1.71 Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.1.71 Manually rebased: gemini/patches-6.1/0002-usb-fotg210-Collect-pieces-of-dual-mode-controller.patch All patches automatically rebased. Build system: x86/64 Build-tested: x86/64/AMD Cezanne Run-tested: x86/64/AMD Cezanne Signed-off-by: John Audia --- include/kernel-6.1 | 4 ++-- ...-Force-CS_HIGH-if-GPIO-descriptors-are-used.patch | 4 ++-- ...g210-Collect-pieces-of-dual-mode-controller.patch | 5 +---- .../828-v6.4-0003-of-Rename-of_modalias_node.patch | 2 +- ...ers-spi-Add-support-for-dynamic-calibration.patch | 12 ++++++------ 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/include/kernel-6.1 b/include/kernel-6.1 index 8cfdaad6d7..c52b94712f 100644 --- a/include/kernel-6.1 +++ b/include/kernel-6.1 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.1 = .70 -LINUX_KERNEL_HASH-6.1.70 = ed1365266456c07696a7499581aec5d851ca2296f4f6f90f23d189ea5a56afef +LINUX_VERSION-6.1 = .71 +LINUX_KERNEL_HASH-6.1.71 = 2df774dd53f9ffd4e57ebf804cf597709295df6a304fe261d25220a134b7f041 diff --git a/target/linux/bcm27xx/patches-6.1/950-0227-spi-Force-CS_HIGH-if-GPIO-descriptors-are-used.patch b/target/linux/bcm27xx/patches-6.1/950-0227-spi-Force-CS_HIGH-if-GPIO-descriptors-are-used.patch index dfbea6258f..974a516829 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0227-spi-Force-CS_HIGH-if-GPIO-descriptors-are-used.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0227-spi-Force-CS_HIGH-if-GPIO-descriptors-are-used.patch @@ -32,7 +32,7 @@ Signed-off-by: Phil Elwell --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -3633,6 +3633,7 @@ static int __spi_validate_bits_per_word( +@@ -3675,6 +3675,7 @@ static int spi_set_cs_timing(struct spi_ */ int spi_setup(struct spi_device *spi) { @@ -40,7 +40,7 @@ Signed-off-by: Phil Elwell unsigned bad_bits, ugly_bits; int status = 0; -@@ -3653,6 +3654,14 @@ int spi_setup(struct spi_device *spi) +@@ -3695,6 +3696,14 @@ int spi_setup(struct spi_device *spi) (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL))) return -EINVAL; diff --git a/target/linux/gemini/patches-6.1/0002-usb-fotg210-Collect-pieces-of-dual-mode-controller.patch b/target/linux/gemini/patches-6.1/0002-usb-fotg210-Collect-pieces-of-dual-mode-controller.patch index 902bf4c68f..1ee4f27c46 100644 --- a/target/linux/gemini/patches-6.1/0002-usb-fotg210-Collect-pieces-of-dual-mode-controller.patch +++ b/target/linux/gemini/patches-6.1/0002-usb-fotg210-Collect-pieces-of-dual-mode-controller.patch @@ -104,7 +104,7 @@ Signed-off-by: Greg Kroah-Hartman +obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o --- a/drivers/usb/host/fotg210-hcd.c +++ /dev/null -@@ -1,5727 +0,0 @@ +@@ -1,5724 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* Faraday FOTG210 EHCI-like driver - * @@ -536,8 +536,6 @@ Signed-off-by: Greg Kroah-Hartman - temp = size; - size -= temp; - next += temp; -- if (temp == size) -- goto done; - } - - temp = snprintf(next, size, "\n"); @@ -547,7 +545,6 @@ Signed-off-by: Greg Kroah-Hartman - size -= temp; - next += temp; - --done: - *sizep = size; - *nextp = next; -} diff --git a/target/linux/generic/backport-6.1/828-v6.4-0003-of-Rename-of_modalias_node.patch b/target/linux/generic/backport-6.1/828-v6.4-0003-of-Rename-of_modalias_node.patch index f82dc1428a..15af039a16 100644 --- a/target/linux/generic/backport-6.1/828-v6.4-0003-of-Rename-of_modalias_node.patch +++ b/target/linux/generic/backport-6.1/828-v6.4-0003-of-Rename-of_modalias_node.patch @@ -148,7 +148,7 @@ Signed-off-by: Greg Kroah-Hartman * of_find_node_by_phandle - Find a node given a phandle --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -2315,8 +2315,8 @@ of_register_spi_device(struct spi_contro +@@ -2326,8 +2326,8 @@ of_register_spi_device(struct spi_contro } /* Select device driver */ diff --git a/target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch b/target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch index 4f9ad9acef..9aeeb78658 100644 --- a/target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch +++ b/target/linux/mediatek/patches-6.1/432-drivers-spi-Add-support-for-dynamic-calibration.patch @@ -11,7 +11,7 @@ Signed-off-by: SkyLake.Huang --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -1374,6 +1374,70 @@ static int spi_transfer_wait(struct spi_ +@@ -1385,6 +1385,70 @@ static int spi_transfer_wait(struct spi_ return 0; } @@ -82,7 +82,7 @@ Signed-off-by: SkyLake.Huang static void _spi_transfer_delay_ns(u32 ns) { if (!ns) -@@ -2208,6 +2272,75 @@ void spi_flush_queue(struct spi_controll +@@ -2219,6 +2283,75 @@ void spi_flush_queue(struct spi_controll /*-------------------------------------------------------------------------*/ #if defined(CONFIG_OF) @@ -158,7 +158,7 @@ Signed-off-by: SkyLake.Huang static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, struct device_node *nc) { -@@ -2326,6 +2459,10 @@ of_register_spi_device(struct spi_contro +@@ -2337,6 +2470,10 @@ of_register_spi_device(struct spi_contro if (rc) goto err_out; @@ -171,7 +171,7 @@ Signed-off-by: SkyLake.Huang spi->dev.of_node = nc; --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h -@@ -298,6 +298,40 @@ struct spi_driver { +@@ -318,6 +318,40 @@ struct spi_driver { struct device_driver driver; }; @@ -212,7 +212,7 @@ Signed-off-by: SkyLake.Huang static inline struct spi_driver *to_spi_driver(struct device_driver *drv) { return drv ? container_of(drv, struct spi_driver, driver) : NULL; -@@ -683,6 +717,11 @@ struct spi_controller { +@@ -703,6 +737,11 @@ struct spi_controller { void *dummy_rx; void *dummy_tx; @@ -224,7 +224,7 @@ Signed-off-by: SkyLake.Huang int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs); /* -@@ -1490,6 +1529,9 @@ spi_register_board_info(struct spi_board +@@ -1510,6 +1549,9 @@ spi_register_board_info(struct spi_board { return 0; } #endif From ee82d9606fd5cd38778604aabefccd61d4028733 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Tue, 12 Dec 2023 04:58:29 +0000 Subject: [PATCH 047/222] ramips: reset mt7620 frame engine via reset controller Use reset controller to reset mt7620 frame engine instead of directly writing system control registers. Tested on HiWiFi HC5861. Signed-off-by: Shiji Yang --- .../ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c | 7 ++----- .../ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h | 4 ---- .../ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c | 6 ------ 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c index dab8a173f7..9c11e9cc89 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c @@ -141,7 +141,7 @@ void fe_reset(u32 reset_bits) usleep_range(10, 20); } -void fe_reset_fe(struct fe_priv *priv) +static void fe_reset_fe(struct fe_priv *priv) { if (!priv->resets) return; @@ -1366,10 +1366,7 @@ static int __init fe_init(struct net_device *dev) struct device_node *port; int err; - if (priv->soc->reset_fe) - priv->soc->reset_fe(priv); - else - fe_reset_fe(priv); + fe_reset_fe(priv); if (priv->soc->switch_init) { err = priv->soc->switch_init(priv); diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h index 892ffb2126..619319d18e 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h @@ -157,8 +157,6 @@ enum fe_work_flag { #define MT7620A_FE_GDMA1_MAC_ADRL (MT7620A_GDMA_OFFSET + 0x0C) #define MT7620A_FE_GDMA1_MAC_ADRH (MT7620A_GDMA_OFFSET + 0x10) -#define MT7620A_RESET_FE BIT(21) -#define MT7620A_RESET_ESW BIT(23) #define MT7620A_RESET_EPHY BIT(24) #define RT5350_TX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x00) @@ -382,7 +380,6 @@ struct fe_soc_data { const u16 *reg_table; void (*init_data)(struct fe_soc_data *data, struct net_device *netdev); - void (*reset_fe)(struct fe_priv *priv); void (*set_mac)(struct fe_priv *priv, unsigned char *mac); int (*fwd_config)(struct fe_priv *priv); void (*tx_dma)(struct fe_tx_dma *txd); @@ -517,7 +514,6 @@ void fe_reg_w32(u32 val, enum fe_reg reg); u32 fe_reg_r32(enum fe_reg reg); void fe_reset(u32 reset_bits); -void fe_reset_fe(struct fe_priv *priv); static inline void *priv_netdev(struct fe_priv *priv) { diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c index a4b2908d59..172dda11b7 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c @@ -286,11 +286,6 @@ static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) } } -static void mt7620_fe_reset(struct fe_priv *priv) -{ - fe_reset(MT7620A_RESET_FE | MT7620A_RESET_ESW); -} - static void mt7620_rxcsum_config(bool enable) { if (enable) @@ -348,7 +343,6 @@ static void mt7620_init_data(struct fe_soc_data *data, static struct fe_soc_data mt7620_data = { .init_data = mt7620_init_data, - .reset_fe = mt7620_fe_reset, .set_mac = mt7620_set_mac, .fwd_config = mt7620_fwd_config, .tx_dma = mt7620_tx_dma, From f547fc9d579e894257cccfebec3a374e27e69e0c Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Tue, 12 Dec 2023 05:18:45 +0000 Subject: [PATCH 048/222] ramips: reset mt7620 ethernet phy via reset controller Use reset controller to reset mt7620 ethernet phy instead of directly writing system control registers. The reset line of "ephy" is 24, so the DTS resets properties have been updated to get the correct reset signal. Tested on HiWiFi HC5861. Signed-off-by: Shiji Yang --- target/linux/ramips/dts/mt7620a.dtsi | 4 ++-- target/linux/ramips/dts/mt7620n.dtsi | 4 ++-- .../drivers/net/ethernet/ralink/gsw_mt7620.c | 19 ++++++++++++++++++- .../drivers/net/ethernet/ralink/gsw_mt7620.h | 3 +++ .../drivers/net/ethernet/ralink/mtk_eth_soc.c | 16 ---------------- .../drivers/net/ethernet/ralink/mtk_eth_soc.h | 4 ---- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/target/linux/ramips/dts/mt7620a.dtsi b/target/linux/ramips/dts/mt7620a.dtsi index a1dfa8c730..0fa503e7a2 100644 --- a/target/linux/ramips/dts/mt7620a.dtsi +++ b/target/linux/ramips/dts/mt7620a.dtsi @@ -490,8 +490,8 @@ compatible = "mediatek,mt7620-gsw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>; - reset-names = "esw"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/dts/mt7620n.dtsi b/target/linux/ramips/dts/mt7620n.dtsi index f4a5165704..4f07c6bc4b 100644 --- a/target/linux/ramips/dts/mt7620n.dtsi +++ b/target/linux/ramips/dts/mt7620n.dtsi @@ -317,8 +317,8 @@ compatible = "mediatek,mt7620-gsw"; reg = <0x10110000 0x8000>; - resets = <&sysc 23>; - reset-names = "esw"; + resets = <&sysc 24>; + reset-names = "ephy"; interrupt-parent = <&intc>; interrupts = <17>; diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c index 84b6e305a4..dcaff04db1 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.c @@ -61,6 +61,17 @@ static irqreturn_t gsw_interrupt_mt7620(int irq, void *_priv) return IRQ_HANDLED; } +static void gsw_reset_ephy(struct mt7620_gsw *gsw) +{ + if (!gsw->rst_ephy) + return; + + reset_control_assert(gsw->rst_ephy); + usleep_range(10, 20); + reset_control_deassert(gsw->rst_ephy); + usleep_range(10, 20); +} + static void mt7620_ephy_init(struct mt7620_gsw *gsw) { u32 i; @@ -79,7 +90,7 @@ static void mt7620_ephy_init(struct mt7620_gsw *gsw) mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_GPC1) | (gsw->ephy_base << 16), GSW_REG_GPC1); - fe_reset(MT7620A_RESET_EPHY); + gsw_reset_ephy(gsw); pr_info("gsw: ephy base address: %d\n", gsw->ephy_base); } @@ -263,6 +274,12 @@ static int mt7620_gsw_probe(struct platform_device *pdev) gsw->irq = platform_get_irq(pdev, 0); + gsw->rst_ephy = devm_reset_control_get_exclusive(&pdev->dev, "ephy"); + if (IS_ERR(gsw->rst_ephy)) { + dev_err(gsw->dev, "failed to get EPHY reset: %pe\n", gsw->rst_ephy); + gsw->rst_ephy = NULL; + } + platform_set_drvdata(pdev, gsw); return 0; diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h index cb5d098e9c..12cab39b77 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620.h @@ -12,6 +12,8 @@ * Copyright (C) 2013-2015 Michael Lee */ +#include + #ifndef _RALINK_GSW_MT7620_H__ #define _RALINK_GSW_MT7620_H__ @@ -90,6 +92,7 @@ enum { struct mt7620_gsw { struct device *dev; + struct reset_control *rst_ephy; void __iomem *base; int irq; bool ephy_disable; diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c index 9c11e9cc89..c741c85f4a 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c @@ -61,8 +61,6 @@ #define NEXT_TX_DESP_IDX(X) (((X) + 1) & (ring->tx_ring_size - 1)) #define NEXT_RX_DESP_IDX(X) (((X) + 1) & (ring->rx_ring_size - 1)) -#define SYSC_REG_RSTCTRL 0x34 - static int fe_msg_level = -1; module_param_named(msg_level, fe_msg_level, int, 0); MODULE_PARM_DESC(msg_level, "Message level (-1=defaults,0=none,...,16=all)"); @@ -127,20 +125,6 @@ void fe_m32(struct fe_priv *eth, u32 clear, u32 set, unsigned reg) spin_unlock(ð->page_lock); } -void fe_reset(u32 reset_bits) -{ - u32 t; - - t = rt_sysc_r32(SYSC_REG_RSTCTRL); - t |= reset_bits; - rt_sysc_w32(t, SYSC_REG_RSTCTRL); - usleep_range(10, 20); - - t &= ~reset_bits; - rt_sysc_w32(t, SYSC_REG_RSTCTRL); - usleep_range(10, 20); -} - static void fe_reset_fe(struct fe_priv *priv) { if (!priv->resets) diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h index 619319d18e..7b291ff43e 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.h @@ -157,8 +157,6 @@ enum fe_work_flag { #define MT7620A_FE_GDMA1_MAC_ADRL (MT7620A_GDMA_OFFSET + 0x0C) #define MT7620A_FE_GDMA1_MAC_ADRH (MT7620A_GDMA_OFFSET + 0x10) -#define MT7620A_RESET_EPHY BIT(24) - #define RT5350_TX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x00) #define RT5350_TX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x04) #define RT5350_TX_CTX_IDX0 (RT5350_PDMA_OFFSET + 0x08) @@ -513,8 +511,6 @@ void fe_fwd_config(struct fe_priv *priv); void fe_reg_w32(u32 val, enum fe_reg reg); u32 fe_reg_r32(enum fe_reg reg); -void fe_reset(u32 reset_bits); - static inline void *priv_netdev(struct fe_priv *priv) { return (char *)priv - ALIGN(sizeof(struct net_device), NETDEV_ALIGN); From 46a2490e8f24a1ad47e53b0b4ee875fa3658f2c1 Mon Sep 17 00:00:00 2001 From: Mohammad Sayful Islam Date: Wed, 3 Jan 2024 07:54:16 +0000 Subject: [PATCH 049/222] ipq807x: add support for Linksys MX4200 V1 and V2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linksys MX4200 is a 802.11ax Tri-band router/AP. Specifications: * CPU: Qualcomm IPQ8174 Quad core Cortex-A53 1.4GHz * RAM: 512MB of DDR3 * Storage: 512Mb NAND * Ethernet: 4x1G RJ45 ports (QCA8075) * WLAN: * 2.4GHz: Qualcomm QCN5024 2x2 802.11b/g/n/ax 574 Mbps PHY rate * 5GHz: Qualcomm QCN5054 2x2@80MHz or 2x2@160MHz 802.11a/b/g/n/ac/ax 2402 PHY rate * 5GHz: Qualcomm QCN5054 4x4@80MHz or 2x2@160MHz 802.11a/b/g/n/ac/ax 2402 PHY rate * LED-s: * RGB system led * Buttons: 1x Soft reset 1x WPS * Power: 12V DC Jack Installation instructions: Open Linksys Web UI - http://192.168.1.1/ca or http://10.65.1.1/ca depending on your setup. Login with your admin password. The default password can be found on a sticker under the device. To enter into the support mode, click on the “CA” link and the bottom of the page. Open the “Connectivity” menu and upload the squash-factory image with the “Choose file” button. Click start. Ignore all the prompts and warnings by click “yes” in all the popups. The Wifi radios are turned off by default. To configure the router, you will need to connect your computer to the LAN port of the device. Then you would need to write openwrt to the other partition for it to work - First Check booted partition fw_printenv -n boot_part - Then install Openwrt to the other partition if booted in slot 1: mtd -r -e alt_kernel -n write openwrt-qualcommax-ipq807x-linksys_mx4200v(X)-squashfs-factory.bin alt_kernel - If in slot 2: mtd -r -e kernel -n write openwrt-qualcommax-ipq807x-linksys_mx4200v(X)-squashfs-factory.bin kernel Replace (X) with your model version either 1 or 2 Signed-off-by: Mohammad Sayful Islam Reviewed-by: Robert Marko --- .../uboot-envtools/files/qualcommax_ipq807x | 6 + package/firmware/ipq-wifi/Makefile | 4 +- package/system/mtd/src/Makefile | 1 + .../arm64/boot/dts/qcom/ipq8174-mx4200.dtsi | 440 ++++++++++++++++++ .../arm64/boot/dts/qcom/ipq8174-mx4200v1.dts | 19 + .../arm64/boot/dts/qcom/ipq8174-mx4200v2.dts | 17 + target/linux/qualcommax/image/ipq807x.mk | 25 + .../ipq807x/base-files/etc/board.d/02_network | 2 + .../etc/hotplug.d/firmware/11-ath11k-caldata | 2 + .../ipq807x/base-files/etc/init.d/bootcount | 4 + .../base-files/lib/upgrade/platform.sh | 15 + 11 files changed, 534 insertions(+), 1 deletion(-) create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200.dtsi create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts create mode 100644 target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v2.dts diff --git a/package/boot/uboot-envtools/files/qualcommax_ipq807x b/package/boot/uboot-envtools/files/qualcommax_ipq807x index 761d5dfcc9..bcedfd9adc 100644 --- a/package/boot/uboot-envtools/files/qualcommax_ipq807x +++ b/package/boot/uboot-envtools/files/qualcommax_ipq807x @@ -29,6 +29,12 @@ edimax,cax1800) [ -n "$idx" ] && \ ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x10000" "0x20000" ;; +linksys,mx4200v1|\ +linksys,mx4200v2) + idx="$(find_mtd_index u_env)" + [ -n "$idx" ] && \ + ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000" "2" + ;; redmi,ax6|\ xiaomi,ax3600|\ xiaomi,ax9000) diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile index ef1a456403..189b8e9ec9 100644 --- a/package/firmware/ipq-wifi/Makefile +++ b/package/firmware/ipq-wifi/Makefile @@ -34,6 +34,7 @@ ALLWIFIBOARDS:= \ dynalink_dl-wrx36 \ edgecore_eap102 \ edimax_cax1800 \ + linksys_mx4200 \ netgear_rax120v2 \ netgear_wax218 \ netgear_wax620 \ @@ -83,7 +84,7 @@ define ipq-wifi-install-one $(call ipq-wifi-install-one-to,$(1),$(2),QCA9984/hw1.0),\ $(if $(filter $(suffix $(1)),.QCA99X0 .qca99x0),\ $(call ipq-wifi-install-one-to,$(1),$(2),QCA99X0/hw2.0),\ - $(if $(filter $(suffix $(1)),.IPQ8074 .ipq8074),\ + $(if $(filter $(suffix $(1)),.IPQ8074 .ipq8074 .ipq8174),\ $(call ipq-wifi-install-ath11-one-to,$(1),$(2),IPQ8074/hw2.0),\ $(if $(filter $(suffix $(1)),.QCN9074 .qcn9074),\ $(call ipq-wifi-install-ath11-one-to,$(1),$(2),QCN9074/hw1.0),\ @@ -144,6 +145,7 @@ $(eval $(call generate-ipq-wifi-package,compex_wpq873,Compex WPQ-873)) $(eval $(call generate-ipq-wifi-package,dynalink_dl-wrx36,Dynalink DL-WRX36)) $(eval $(call generate-ipq-wifi-package,edgecore_eap102,Edgecore EAP102)) $(eval $(call generate-ipq-wifi-package,edimax_cax1800,Edimax CAX1800)) +$(eval $(call generate-ipq-wifi-package,linksys_mx4200,Linksys MX4200)) $(eval $(call generate-ipq-wifi-package,netgear_rax120v2,Netgear RAX120v2)) $(eval $(call generate-ipq-wifi-package,netgear_wax218,Netgear WAX218)) $(eval $(call generate-ipq-wifi-package,netgear_wax620,Netgear WAX620)) diff --git a/package/system/mtd/src/Makefile b/package/system/mtd/src/Makefile index e204ecb221..a1277a6739 100644 --- a/package/system/mtd/src/Makefile +++ b/package/system/mtd/src/Makefile @@ -20,6 +20,7 @@ obj.mvebu = linksys_bootcount.o obj.kirkwood = linksys_bootcount.o obj.ipq806x = linksys_bootcount.o obj.ipq40xx = linksys_bootcount.o +obj.qualcommax = linksys_bootcount.o ifdef FIS_SUPPORT obj += fis.o diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200.dtsi b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200.dtsi new file mode 100644 index 0000000000..ef67742c03 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200.dtsi @@ -0,0 +1,440 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2023, Mohammad Sayful Islam */ + +#include "ipq8074.dtsi" +#include "ipq8074-ac-cpu.dtsi" +#include "ipq8074-ess.dtsi" +#include +#include +#include + +/ { + + aliases { + serial0 = &blsp1_uart5; + serial1 = &blsp1_uart3; + /* + * Aliases as required by u-boot + * to patch MAC addresses + */ + ethernet1 = &dp2; + ethernet2 = &dp3; + ethernet3 = &dp4; + ethernet4 = &dp5; + led-boot = &led_system_blue; + led-running = &led_system_blue; + led-failsafe = &led_system_red; + led-upgrade = &led_system_green; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " root=/dev/ubiblock0_0"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + reset-button { + label = "reset"; + gpios = <&tlmm 52 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps-button { + label = "wps"; + gpios = <&tlmm 67 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; +}; + +&tlmm { + button_pins: button-state { + pins = "gpio52", "gpio67"; + function = "gpio"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio_pins: mdio-state { + mdc-pins { + pins = "gpio68"; + function = "mdc"; + drive-strength = <8>; + bias-pull-up; + }; + + mdio-pins { + pins = "gpio69"; + function = "mdio"; + drive-strength = <8>; + bias-pull-up; + }; + }; + + iot_pins: iot-state { + recovery-pins { + pins = "gpio22"; + function = "gpio"; + input; + }; + + reset-pins { + pins = "gpio21"; + function = "gpio"; + bias-pull-up; + }; + }; +}; + +&blsp1_uart3 { + status = "okay"; + + pinctrl-0 = <&hsuart_pins &iot_pins>; + pinctrl-names = "default"; + + /* Silicon Labs EFR32MG21 IoT */ +}; + +&blsp1_uart5 { + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&qpic_bam { + status = "okay"; +}; + +&qpic_nand { + status = "okay"; + + /* + * Bootloader will find the NAND DT node by the compatible and + * then "fixup" it by adding the partitions from the SMEM table + * using the legacy bindings thus making it impossible for us + * to change the partition table or utilize NVMEM for calibration. + * So add a dummy partitions node that bootloader will populate + * and set it as disabled so the kernel ignores it instead of + * printing warnings due to the broken way bootloader adds the + * partitions. + */ + partitions { + status = "disabled"; + }; + + nand@0 { + reg = <0>; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + nand-bus-width = <8>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:sbl1"; + reg = <0x0 0x100000>; + read-only; + }; + + partition@100000 { + label = "0:mibib"; + reg = <0x100000 0x100000>; + read-only; + }; + + partition@200000 { + label = "0:bootconfig"; + reg = <0x200000 0x80000>; + read-only; + }; + + partition@280000 { + label = "0:bootconfig1"; + reg = <0x280000 0x80000>; + read-only; + }; + + partition@300000 { + label = "0:qsee"; + reg = <0x300000 0x300000>; + read-only; + }; + + partition@600000 { + label = "0:qsee_1"; + reg = <0x600000 0x300000>; + read-only; + }; + + partition@900000 { + label = "0:devcfg"; + reg = <0x900000 0x80000>; + read-only; + }; + + partition@980000 { + label = "0:devcfg_1"; + reg = <0x980000 0x80000>; + read-only; + }; + + partition@a00000 { + label = "0:apdp"; + reg = <0xa00000 0x80000>; + read-only; + }; + + partition@a80000 { + label = "0:apdp_1"; + reg = <0xa80000 0x80000>; + read-only; + }; + + partition@b00000 { + label = "0:rpm"; + reg = <0xb00000 0x80000>; + read-only; + }; + + partition@b80000 { + label = "0:rpm_1"; + reg = <0xb80000 0x80000>; + read-only; + }; + + partition@c00000 { + label = "0:cdt"; + reg = <0xc00000 0x80000>; + read-only; + }; + + partition@c80000 { + label = "0:cdt_1"; + reg = <0xc80000 0x80000>; + read-only; + }; + + partition@d00000 { + label = "0:appsblenv"; + reg = <0xd00000 0x80000>; + }; + + partition@d80000 { + label = "0:appsbl"; + reg = <0xd80000 0x100000>; + read-only; + }; + + partition@e80000 { + label = "0:appsbl_1"; + reg = <0xe80000 0x100000>; + read-only; + }; + + partition@f80000 { + label = "0:art"; + reg = <0xf80000 0x80000>; + read-only; + }; + + partition@1000000 { + label = "u_env"; + reg = <0x1000000 0x40000>; + }; + + partition@1040000 { + label = "s_env"; + reg = <0x1040000 0x20000>; + }; + + partition@1060000 { + label = "devinfo"; + reg = <0x1060000 0x20000>; + read-only; + }; + + partition@1080000 { + label = "kernel"; + reg = <0x1080000 0x9600000>; + }; + + partition@1680000 { + label = "rootfs"; + reg = <0x1680000 0x9000000>; + }; + + partition@a680000 { + label = "alt_kernel"; + reg = <0xa680000 0x9600000>; + }; + + partition@ac80000 { + label = "alt_rootfs"; + reg = <0xac80000 0x9000000>; + }; + partition@13c80000 { + label = "sysdiag"; + reg = <0x13c80000 0x200000>; + read-only; + }; + partition@13e80000 { + label = "0:ethphyfw"; + reg = <0x13e80000 0x80000>; + read-only; + }; + partition@13f00000 { + label = "syscfg"; + reg = <0x13f00000 0xb800000>; + read-only; + }; + partition@1f700000 { + label = "0:wififw"; + reg = <0x1f700000 0x900000>; + read-only; + }; + }; + }; +}; + +&blsp1_i2c2 { + status = "okay"; + + led-controller@62 { + compatible = "nxp,pca9633"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x62>; + nxp,hw-blink; + + led_system_red: led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + led_system_green: led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + led_system_blue: led@2 { + reg = <2>; + color = ; + function = LED_FUNCTION_STATUS; + }; + }; +}; + +&mdio { + status = "okay"; + + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + reset-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>; + + qca8075_1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; + + qca8075_2: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <2>; + }; + + qca8075_3: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <3>; + }; + + qca8075_4: ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <4>; + }; +}; + +&switch { + status = "okay"; + + switch_lan_bmp = <(ESS_PORT3 | ESS_PORT4 | ESS_PORT5)>; /* lan port bitmap */ + switch_wan_bmp = ; /* wan port bitmap */ + switch_mac_mode = ; /* mac mode for uniphy instance0*/ + + qcom,port_phyinfo { + port@2 { + port_id = <2>; + phy_address = <1>; + }; + port@3 { + port_id = <3>; + phy_address = <2>; + }; + port@4 { + port_id = <4>; + phy_address = <3>; + }; + port@5 { + port_id = <5>; + phy_address = <4>; + }; + }; +}; + +&edma { + status = "okay"; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "wan"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan1"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan2"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "lan3"; +}; + +&ssphy_0 { + status = "okay"; +}; + +&qusb_phy_0 { + status = "okay"; +}; + +&usb_0 { + status = "okay"; +}; + diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts new file mode 100644 index 0000000000..4bc1b8cc28 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2023, Mohammad Sayful Islam */ + +/dts-v1/; + +#include "ipq8074-512m.dtsi" +#include "ipq8174-mx4200.dtsi" + +/ { + model = "Linksys MX4200v1"; + compatible = "linksys,mx4200v1", "qcom,ipq8074"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Linksys-MX4200v1"; + qcom,ath11k-fw-memory-mode = <1>; +}; diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v2.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v2.dts new file mode 100644 index 0000000000..44e1b72f16 --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v2.dts @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* Copyright (c) 2023, Mohammad Sayful Islam */ + +/dts-v1/; + +#include "ipq8174-mx4200.dtsi" + +/ { + model = "Linksys MX4200v2"; + compatible = "linksys,mx4200v2", "qcom,ipq8074"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Linksys-MX4200v2"; +}; diff --git a/target/linux/qualcommax/image/ipq807x.mk b/target/linux/qualcommax/image/ipq807x.mk index d8416d10fb..5beff11309 100644 --- a/target/linux/qualcommax/image/ipq807x.mk +++ b/target/linux/qualcommax/image/ipq807x.mk @@ -115,6 +115,31 @@ define Device/edimax_cax1800 endef TARGET_DEVICES += edimax_cax1800 +define Device/linksys_mx4200v1 + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Linksys + DEVICE_MODEL := MX4200 + DEVICE_VARIANT := v1 + BLOCKSIZE := 128k + PAGESIZE := 2048 + KERNEL_SIZE := 6144k + IMAGE_SIZE := 147456k + NAND_SIZE := 512m + KERNEL_IN_UBI := + SOC := ipq8174 + IMAGES += factory.bin + IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | linksys-image type=MX4200 + DEVICE_PACKAGES := kmod-leds-pca963x ipq-wifi-linksys_mx4200 kmod-bluetooth +endef +TARGET_DEVICES += linksys_mx4200v1 + +define Device/linksys_mx4200v2 + $(call Device/linksys_mx4200v1) + DEVICE_VARIANT := v2 +endef +TARGET_DEVICES += linksys_mx4200v2 + define Device/netgear_rax120v2 $(call Device/FitImage) $(call Device/UbiFit) diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network index 5da17db3fa..ff9069091f 100644 --- a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network +++ b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network @@ -18,6 +18,8 @@ ipq807x_setup_interfaces() ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" ;; compex,wpq873|\ + linksys,mx4200v1|\ + linksys,mx4200v2|\ redmi,ax6|\ xiaomi,ax3600) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata index ac1405739d..85d107079e 100644 --- a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata +++ b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata @@ -15,6 +15,8 @@ case "$FIRMWARE" in dynalink,dl-wrx36|\ edgecore,eap102|\ edimax,cax1800|\ + linksys,mx4200v1|\ + linksys,mx4200v2|\ netgear,rax120v2|\ netgear,wax218|\ netgear,wax620|\ diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount index 84f826b3b8..f5f6c909e9 100755 --- a/target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount +++ b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/bootcount @@ -10,5 +10,9 @@ boot() { # Unset changed flag after sysupgrade complete fw_setenv changed ;; + linksys,mx4200v1|\ + linksys,mx4200v2) + mtd resetbc s_env || true + ;; esac } diff --git a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh index 67fd0f5402..78842e1c4d 100644 --- a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh +++ b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh @@ -73,6 +73,21 @@ platform_do_upgrade() { fw_setenv upgrade_available 1 nand_do_upgrade "$1" ;; + linksys,mx4200v1|\ + linksys,mx4200v2) + boot_part="$(fw_printenv -n boot_part)" + if [ "$boot_part" -eq "1" ]; then + fw_setenv boot_part 2 + CI_KERNPART="alt_kernel" + CI_UBIPART="alt_rootfs" + else + fw_setenv boot_part 1 + CI_UBIPART="rootfs" + fi + fw_setenv boot_part_ready 3 + fw_setenv auto_recovery yes + nand_do_upgrade "$1" + ;; prpl,haze|\ qnap,301w) kernelname="0:HLOS" From 29f6da43403c5131d0035de0bfc4107eee17953b Mon Sep 17 00:00:00 2001 From: Tony Ambardar Date: Mon, 4 Dec 2023 03:09:28 -0800 Subject: [PATCH 050/222] kernel: include built-in module list Add modules.builtin to the kernel package for improved handling of loadable and builtin modules. As with other distros, this allows 'modprobe ' to consistently return success for both loaded/built-in modules, a useful feature for presence-testing. Given OpenWrt's few built-in modules, this change and related kmodloader support add ~1 KB to the compressed image size. Using sch_fq_codel (builtin) and sch_cake (loadable) for example: root@OpenWrt:/# modprobe sch_fq_codel && echo SUCCESS || echo FAIL SUCCESS root@OpenWrt:/# modprobe sch_cake && echo SUCCESS || echo FAIL SUCCESS root@OpenWrt:/# rmmod sch_fq_codel module is builtin Signed-off-by: Tony Ambardar --- package/kernel/linux/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package/kernel/linux/Makefile b/package/kernel/linux/Makefile index c88b5c1b31..b198882979 100644 --- a/package/kernel/linux/Makefile +++ b/package/kernel/linux/Makefile @@ -58,7 +58,9 @@ define Package/kernel endef define Package/kernel/install - # nothing to do + $(INSTALL_DIR) $(1)/$(MODULES_SUBDIR) + $(INSTALL_DATA) $(LINUX_DIR)/modules.builtin $(1)/$(MODULES_SUBDIR) + $(SED) 's,.*/,,' $(1)/$(MODULES_SUBDIR)/modules.builtin endef define Package/kernel/extra_provides From e1d8e576147d813398c6797ca866f9d8a41a350e Mon Sep 17 00:00:00 2001 From: Tony Ambardar Date: Tue, 5 Dec 2023 01:09:46 -0800 Subject: [PATCH 051/222] kernel: include modinfo for built-in modules Add modules.builtin.modinfo to the kernel package, to support presence testing using module aliases and printing module details with 'modinfo'. With related kmodloader changes this adds ~2 KB to compressed image sizes. root@OpenWrt:/# modinfo unix name: unix filename: (builtin) alias: net-pf-1 license: GPL root@OpenWrt:/# modprobe net-pf-1 && echo SUCCESS || echo FAIL SUCCESS Signed-off-by: Tony Ambardar --- package/kernel/linux/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package/kernel/linux/Makefile b/package/kernel/linux/Makefile index b198882979..6592b01678 100644 --- a/package/kernel/linux/Makefile +++ b/package/kernel/linux/Makefile @@ -61,6 +61,9 @@ define Package/kernel/install $(INSTALL_DIR) $(1)/$(MODULES_SUBDIR) $(INSTALL_DATA) $(LINUX_DIR)/modules.builtin $(1)/$(MODULES_SUBDIR) $(SED) 's,.*/,,' $(1)/$(MODULES_SUBDIR)/modules.builtin + strings $(LINUX_DIR)/modules.builtin.modinfo | \ + grep -E -v "\.(file$(if CONFIG_MODULE_STRIPPED,|parmtype))=" | \ + tr '\n' '\0' > $(1)/$(MODULES_SUBDIR)/modules.builtin.modinfo endef define Package/kernel/extra_provides From 7dbcc1215a56cc1da68c81bf92d7efa174c5e051 Mon Sep 17 00:00:00 2001 From: Dim Fish Date: Mon, 27 Nov 2023 12:01:34 +0300 Subject: [PATCH 052/222] mediatek: filogic: add support for Xiaomi AX3000T **SoC**: MediaTek MT7981B 2x A53 **Flash**: ESMT F50L1G41LB 128MB **RAM**: NT52B128M16JR-FL 256MB **Ethernet**: 4x 10/100/1000 Mbps **Switch**: MediaTek MT7531AE **WiFi**: MediaTek MT7976C **Buttons**: Reset, Mesh **Power**: DC 12V 1A 1. Get ssh access. Supported stock firmware **1.0.47** ``` curl -X POST "http://192.168.31.1/cgi-bin/luci/;stok=*******/api/misystem/arn_switch" -d "open=1&model=1&level=%0Anvram%20set%20ssh_en%3D1%0A" curl -X POST "http://192.168.31.1/cgi-bin/luci/;stok=*******/api/misystem/arn_switch" -d "open=1&model=1&level=%0Anvram%20commit%0A" curl -X POST "http://192.168.31.1/cgi-bin/luci/;stok=*******/api/misystem/arn_switch" -d "open=1&model=1&level=%0Ased%20-i%20's%2Fchannel%3D.*%2Fchannel%3D%22debug%22%2Fg'%20%2Fetc%2Finit.d%2Fdropbear%0A" curl -X POST "http://192.168.31.1/cgi-bin/luci/;stok=*******/api/misystem/arn_switch" -d "open=1&model=1&level=%0A%2Fetc%2Finit.d%2Fdropbear%20start%0A" curl -X POST "http://192.168.31.1/cgi-bin/luci/;stok=********/api/misystem/arn_switch" -d "open=1&model=1&level=%0Apasswd%20-d%20root%0A ``` 2. Backup stock partitions ``` nanddump -f /tmp/BL2.bin /dev/mtd1 nanddump -f /tmp/Nvram.bin /dev/mtd2 nanddump -f /tmp/Bdata.bin /dev/mtd3 nanddump -f /tmp/Factory.bin /dev/mtd4 nanddump -f /tmp/FIP.bin /dev/mtd5 nanddump -f /tmp/ubi.bin /dev/mtd8 nanddump -f /tmp/KF.bin /dev/mtd12 ``` Then transfer them to your computer in a safe place. 3. Get firmware information `cat /proc/cmdline` 4. Copy openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-initramfs-factory.ubi to **/tmp** and flash If **firmware=0** ``` ubiformat /dev/mtd9 -y -f /tmp/openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-initramfs-factory.ubi nvram set boot_wait=on nvram set uart_en=1 nvram set flag_boot_rootfs=1 nvram set flag_last_success=1 nvram set flag_boot_success=1 nvram set flag_try_sys1_failed=0 nvram set flag_try_sys2_failed=0 nvram commit reboot ``` If **firmware=1** ``` ubiformat /dev/mtd8 -y -f /tmp/openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-initramfs-factory.ubi nvram set boot_wait=on nvram set uart_en=1 nvram set flag_boot_rootfs=0 nvram set flag_last_success=0 nvram set flag_boot_success=1 nvram set flag_try_sys1_failed=0 nvram set flag_try_sys2_failed=0 nvram commit reboot ``` Then reboot your router, it should boot to the OpenWrt initramfs system now. 5. Flash openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-squashfs-sysupgrade.bin `sysupgrade -n /tmp/openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-squashfs-sysupgrade.bin` 1. Flash openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-initramfs-recovery.itb `ubiformat /dev/mtd8 -y -f /tmp/openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-initramfs-recovery.itb` `reboot` 2. Install kmod-mtd-rw `opkg update && opkg install kmod-mtd-rw` `insmod /lib/modules/$(uname -r)/mtd-rw.ko i_want_a_brick=1` 3. Format ubi and create new ubootenv volume ``` ubidetach -p /dev/mtd8; ubiformat /dev/mtd8 -y; ubiattach -p /dev/mtd8 ubimkvol /dev/ubi0 -n 0 -N ubootenv -s 128KiB ubimkvol /dev/ubi0 -n 1 -N ubootenv2 -s 128KiB ``` 4. *(Optional **-10Mb** free space) Add recovery boot feature.* ``` ubimkvol /dev/ubi0 -n 2 -N recovery -s 10MiB ubiupdatevol /dev/ubi0_2 /tmp/openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-initramfs-recovery.itb ``` 5. Flash Openwrt U-Boot ``` mtd write /tmp/openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-preloader.bin BL2 mtd write /tmp/openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-bl31-uboot.fip FIP ``` 6. Flash openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-squashfs-sysupgrade.itb `sysupgrade -n /tmp/openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-squashfs-sysupgrade.itb` 1. Force flash openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-initramfs-recovery.itb `sysupgrade -F -n /tmp/openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-initramfs-recovery.itb` 2. Format ubi and Nvram ``` ubidetach -p /dev/mtd8; ubiformat /dev/mtd8 -y; ubiattach -p /dev/mtd8 mtd erase Nvram ``` 3. Install kmod-mtd-rw `opkg update && opkg install kmod-mtd-rw` `insmod /lib/modules/$(uname -r)/mtd-rw.ko i_want_a_brick=1` 4. Flash stock images from backup ``` mtd write /tmp/BL2.bin BL2 mtd write /tmp/FIP.bin FIP mtd write /tmp/ubi.bin ubi ``` Then reboot your router, waiting it finished rollback in minutes. `ubiformat /dev/mtd7 -y -f /tmp/ubi.bin` Then reboot your router, waiting it finished rollback in minutes. Signed-off-by: Dim Fish --- .../uboot-envtools/files/mediatek_filogic | 2 + package/boot/uboot-mediatek/Makefile | 13 + .../440-add-xiaomi_mi-router-ax3000t.patch | 414 ++++++++++++++++++ ...981b-xiaomi-mi-router-ax3000t-ubootmod.dts | 16 + .../dts/mt7981b-xiaomi-mi-router-ax3000t.dts | 34 ++ .../dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi | 29 ++ .../dts/mt7981b-xiaomi-mi-router-common.dtsi | 245 +++++++++++ .../dts/mt7981b-xiaomi-mi-router-wr30u.dtsi | 257 +---------- .../filogic/base-files/etc/board.d/01_leds | 2 +- .../filogic/base-files/etc/board.d/02_network | 4 + .../base-files/lib/upgrade/platform.sh | 4 + target/linux/mediatek/image/filogic.mk | 45 ++ 12 files changed, 821 insertions(+), 244 deletions(-) create mode 100644 package/boot/uboot-mediatek/patches/440-add-xiaomi_mi-router-ax3000t.patch create mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t-ubootmod.dts create mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dts create mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi create mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-common.dtsi diff --git a/package/boot/uboot-envtools/files/mediatek_filogic b/package/boot/uboot-envtools/files/mediatek_filogic index b4957c212b..1e7b42b634 100644 --- a/package/boot/uboot-envtools/files/mediatek_filogic +++ b/package/boot/uboot-envtools/files/mediatek_filogic @@ -69,6 +69,7 @@ qihoo,360t7|\ tplink,tl-xdr4288|\ tplink,tl-xdr6086|\ tplink,tl-xdr6088|\ +xiaomi,mi-router-ax3000t-ubootmod|\ xiaomi,mi-router-wr30u-ubootmod|\ xiaomi,redmi-router-ax6000-ubootmod) . /lib/upgrade/nand.sh @@ -94,6 +95,7 @@ routerich,ax3000) ubnt,unifi-6-plus) ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x80000" "0x10000" ;; +xiaomi,mi-router-ax3000t|\ xiaomi,mi-router-wr30u-112m-nmbm|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,redmi-router-ax6000-stock) diff --git a/package/boot/uboot-mediatek/Makefile b/package/boot/uboot-mediatek/Makefile index a9e6d35f00..37fb68be22 100644 --- a/package/boot/uboot-mediatek/Makefile +++ b/package/boot/uboot-mediatek/Makefile @@ -322,6 +322,18 @@ define U-Boot/mt7981_qihoo_360t7 DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ddr3 endef +define U-Boot/mt7981_xiaomi_mi-router-ax3000t + NAME:=Xiaomi Router AX3000T + BUILD_SUBTARGET:=filogic + BUILD_DEVICES:=xiaomi_mi-router-ax3000t-ubootmod + UBOOT_CONFIG:=mt7981_xiaomi_mi-router-ax3000t + UBOOT_IMAGE:=u-boot.fip + BL2_BOOTDEV:=spim-nand + BL2_SOC:=mt7981 + BL2_DDRTYPE:=ddr3 + DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ddr3 +endef + define U-Boot/mt7981_xiaomi_mi-router-wr30u NAME:=Xiaomi Router WR30U BUILD_SUBTARGET:=filogic @@ -556,6 +568,7 @@ UBOOT_TARGETS := \ mt7981_rfb-sd \ mt7981_rfb-snfi \ mt7981_qihoo_360t7 \ + mt7981_xiaomi_mi-router-ax3000t \ mt7981_xiaomi_mi-router-wr30u \ mt7986_bananapi_bpi-r3-emmc \ mt7986_bananapi_bpi-r3-sdmmc \ diff --git a/package/boot/uboot-mediatek/patches/440-add-xiaomi_mi-router-ax3000t.patch b/package/boot/uboot-mediatek/patches/440-add-xiaomi_mi-router-ax3000t.patch new file mode 100644 index 0000000000..9b50166a94 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/440-add-xiaomi_mi-router-ax3000t.patch @@ -0,0 +1,414 @@ +--- /dev/null ++++ b/configs/mt7981_xiaomi_mi-router-ax3000t_defconfig +@@ -0,0 +1,163 @@ ++CONFIG_ARM=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_TARGET_MT7981=y ++CONFIG_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_SYS_HAS_NONCACHED_MEMORY=y ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DEFAULT_DEVICE_TREE="mt7981_xiaomi_mi-router-ax3000t" ++CONFIG_DEFAULT_ENV_FILE="xiaomi_mi-router-ax3000t_env" ++CONFIG_DEFAULT_FDT_FILE="mediatek/mt7981_xiaomi_mi-router-ax3000t.dtb" ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_DEBUG_UART=y ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_SMBIOS_PRODUCT_NAME="" ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_BOOTDELAY=30 ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_CFB_CONSOLE_ANSI=y ++CONFIG_BOARD_LATE_INIT=y ++CONFIG_BUTTON=y ++CONFIG_BUTTON_GPIO=y ++CONFIG_GPIO_HOG=y ++CONFIG_CMD_ENV_FLAGS=y ++CONFIG_FIT=y ++CONFIG_FIT_ENABLE_SHA256_SUPPORT=y ++CONFIG_LED=y ++CONFIG_LED_BLINK=y ++CONFIG_LED_GPIO=y ++CONFIG_LOGLEVEL=7 ++CONFIG_LOG=y ++CONFIG_SYS_PROMPT="MT7981> " ++CONFIG_CMD_BOOTMENU=y ++CONFIG_CMD_BOOTP=y ++CONFIG_CMD_BUTTON=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_CPU=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_ECHO=y ++CONFIG_CMD_ENV_READMEM=y ++CONFIG_CMD_ERASEENV=y ++# CONFIG_CMD_EXT4 is not set ++# CONFIG_CMD_FAT is not set ++CONFIG_CMD_FDT=y ++# CONFIG_CMD_FS_GENERIC is not set ++# CONFIG_CMD_FS_UUID is not set ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_ITEST=y ++CONFIG_CMD_LED=y ++CONFIG_CMD_LICENSE=y ++CONFIG_CMD_LINK_LOCAL=y ++# CONFIG_CMD_MBR is not set ++CONFIG_CMD_MTD=y ++# CONFIG_CMD_PCI is not set ++CONFIG_CMD_PSTORE=y ++CONFIG_CMD_PSTORE_MEM_ADDR=0x42ff0000 ++CONFIG_CMD_SF_TEST=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_PXE=y ++# CONFIG_CMD_PWM is not set ++CONFIG_CMD_SMC=y ++CONFIG_CMD_TFTPBOOT=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_UBI=y ++CONFIG_CMD_UBI_RENAME=y ++CONFIG_CMD_UBIFS=y ++CONFIG_CMD_ASKENV=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_SETEXPR=y ++CONFIG_CMD_SLEEP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_SOURCE=y ++CONFIG_CMD_STRINGS=y ++# CONFIG_CMD_USB is not set ++# CONFIG_CMD_FLASH is not set ++CONFIG_CMD_UUID=y ++CONFIG_DISPLAY_CPUINFO=y ++CONFIG_DM_MTD=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++# CONFIG_DM_USB is not set ++# CONFIG_DM_PWM is not set ++# CONFIG_PWM_MTK is not set ++CONFIG_HUSH_PARSER=y ++CONFIG_SYS_REDUNDAND_ENVIRONMENT=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_VERSION_VARIABLE=y ++CONFIG_PARTITION_UUIDS=y ++CONFIG_NETCONSOLE=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_DM_GPIO=y ++# CONFIG_DM_SCSI is not set ++# CONFIG_AHCI is not set ++CONFIG_PHY=y ++# CONFIG_PHY_MTK_TPHY is not set ++CONFIG_PHY_FIXED=y ++CONFIG_MTK_AHCI=y ++CONFIG_DM_ETH=y ++CONFIG_MEDIATEK_ETH=y ++# CONFIG_PCI is not set ++# CONFIG_MMC is not set ++# CONFIG_DM_MMC is not set ++CONFIG_MTD=y ++CONFIG_MTD_UBI_FASTMAP=y ++# CONFIG_DM_PCI is not set ++# CONFIG_PCIE_MEDIATEK is not set ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7981=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_PRE_CONSOLE_BUFFER=y ++CONFIG_PRE_CON_BUF_ADDR=0x4007EF00 ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_RAM=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_MTK_SPI_NAND=y ++CONFIG_MTK_SPI_NAND_MTD=y ++CONFIG_SYSRESET_WATCHDOG=y ++CONFIG_WDT_MTK=y ++CONFIG_LZO=y ++CONFIG_ZSTD=y ++CONFIG_HEXDUMP=y ++CONFIG_RANDOM_UUID=y ++CONFIG_REGEX=y ++# CONFIG_USB is not set ++# CONFIG_USB_HOST is not set ++# CONFIG_USB_XHCI_HCD is not set ++# CONFIG_USB_XHCI_MTK is not set ++# CONFIG_USB_STORAGE is not set ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_UBI=y ++CONFIG_ENV_UBI_PART="ubi" ++CONFIG_ENV_SIZE=0x1f000 ++CONFIG_ENV_SIZE_REDUND=0x1f000 ++CONFIG_ENV_UBI_VOLUME="ubootenv" ++CONFIG_ENV_UBI_VOLUME_REDUND="ubootenv2" ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_USE_DEFAULT_ENV_FILE=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_MTK_SPIM=y ++CONFIG_CMD_NAND=y ++CONFIG_CMD_NAND_TRIMFFS=y ++CONFIG_LMB_MAX_REGIONS=64 ++CONFIG_USE_IPADDR=y ++CONFIG_IPADDR="192.168.1.1" ++CONFIG_USE_SERVERIP=y ++CONFIG_SERVERIP="192.168.1.254" +--- /dev/null ++++ b/arch/arm/dts/mt7981_xiaomi_mi-router-ax3000t.dts +@@ -0,0 +1,187 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Sam Shih ++ */ ++ ++/dts-v1/; ++#include "mt7981.dtsi" ++#include ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "Xiaomi Router AX3000T"; ++ compatible = "mediatek,mt7981", "mediatek,mt7981-rfb"; ++ ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x10000000>; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ reset { ++ label = "reset"; ++ gpios = <&gpio 1 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ }; ++ ++ mesh { ++ label = "mesh"; ++ gpios = <&gpio 0 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ linux,input-type = ; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_status_blue { ++ label = "blue:status"; ++ gpios = <&gpio 9 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led_status_yellow { ++ label = "yellow:status"; ++ gpios = <&gpio 10 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&uart0 { ++ mediatek,force-highspeed; ++ status = "okay"; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "2500base-x"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 39 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <2500>; ++ full-duplex; ++ }; ++}; ++ ++&pinctrl { ++ spic_pins: spi1-pins-func-1 { ++ mux { ++ function = "spi"; ++ groups = "spi1_1"; ++ }; ++ }; ++ ++ uart1_pins: spi1-pins-func-3 { ++ mux { ++ function = "uart"; ++ groups = "uart1_2"; ++ }; ++ }; ++ ++ spi_flash_pins: spi0-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ ++ conf-pu { ++ pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++}; ++ ++&spi0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ status = "okay"; ++ must_tx; ++ enhance_timing; ++ dma_ext; ++ ipm_design; ++ support_quad; ++ tick_dly = <2>; ++ sample_sel = <0>; ++ ++ spi_nand@0 { ++ compatible = "spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <52000000>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x00 0x100000>; ++ }; ++ ++ partition@100000 { ++ label = "Nvram"; ++ reg = <0x100000 0x40000>; ++ }; ++ ++ partition@140000 { ++ label = "Bdata"; ++ reg = <0x140000 0x40000>; ++ }; ++ ++ partition@180000 { ++ label = "factory"; ++ reg = <0x180000 0x200000>; ++ }; ++ ++ partition@380000 { ++ label = "fip"; ++ reg = <0x380000 0x200000>; ++ }; ++ ++ partition@580000 { ++ label = "crash"; ++ reg = <0x580000 0x40000>; ++ }; ++ ++ partition@5c0000 { ++ label = "crash_log"; ++ reg = <0x5c0000 0x40000>; ++ }; ++ ++ partition@600000 { ++ label = "ubi"; ++ reg = <0x600000 0x7000000>; ++ }; ++ ++ partition@7600000 { ++ label = "KF"; ++ reg = <0x7600000 0x40000>; ++ }; ++ }; ++ }; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; +--- /dev/null ++++ b/xiaomi_mi-router-ax3000t_env +@@ -0,0 +1,55 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x46000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootargs=console=ttyS0,115200n8 console_msg_format=syslog ++bootcmd=if pstore check ; then run boot_recovery ; else run boot_ubi ; fi ++bootconf=config-1 ++bootdelay=0 ++bootfile=openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-initramfs-recovery.itb ++bootfile_bl2=openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-preloader.bin ++bootfile_fip=openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-bl31-uboot.fip ++bootfile_upg=openwrt-mediatek-filogic-xiaomi_mi-router-ax3000t-ubootmod-squashfs-sysupgrade.itb ++bootled_pwr=yellow:status ++bootled_rec=blue:status ++bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60 ++bootmenu_default=0 ++bootmenu_delay=0 ++bootmenu_title= ( ( ( OpenWrt ) ) ) ++bootmenu_0=Initialize environment.=run _firstboot ++bootmenu_0d=Run default boot command.=run boot_default ++bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return ++bootmenu_2=Boot production system from NAND.=run boot_production ; run bootmenu_confirm_return ++bootmenu_3=Boot recovery system from NAND.=run boot_recovery ; run bootmenu_confirm_return ++bootmenu_4=Load production system via TFTP then write to NAND.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_5=Load recovery system via TFTP then write to NAND.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_recovery ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_6=Load BL31+U-Boot FIP via TFTP then write to NAND.=run boot_tftp_write_fip ; run bootmenu_confirm_return ++bootmenu_7=Load BL2 preloader via TFTP then write to NAND.=run boot_tftp_write_bl2 ; run bootmenu_confirm_return ++bootmenu_8=Reboot.=reset ++bootmenu_9=Reset all settings to factory defaults.=run reset_factory ; reset ++boot_first=if button reset ; then led $bootled_rec on ; run boot_tftp_recovery ; setenv flag_recover 1 ; run boot_default ; fi ; bootmenu ++boot_default=if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_forever ++boot_production=led $bootled_pwr on ; run ubi_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off ++boot_recovery=led $bootled_rec on ; run ubi_read_recovery && bootm $loadaddr#$bootconf ; led $bootled_rec off ++boot_ubi=run boot_production ; run boot_recovery ; run boot_tftp_forever ++boot_tftp_forever=led $bootled_rec on ; while true ; do run boot_tftp_recovery ; sleep 1 ; done ++boot_tftp_recovery=tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run ubi_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_production=tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run ubi_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp=tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run mtd_write_fip && run reset_factory ++boot_tftp_write_bl2=tftpboot $loadaddr $bootfile_bl2 && run mtd_write_bl2 ++reset_factory=ubi part ubi ; mw $loadaddr 0x0 0x800 ; ubi write $loadaddr ubootenv 0x800 ; ubi write $loadaddr ubootenv2 0x800 ++mtd_write_fip=mtd erase fip && mtd write fip $loadaddr ++mtd_write_bl2=mtd erase bl2 && mtd write bl2 $loadaddr ++ubi_create_env=ubi check ubootenv || ubi create ubootenv 0x100000 dynamic 0 || run ubi_format ; ubi check ubootenv2 || ubi create ubootenv2 0x100000 dynamic 1 || run ubi_format ++ubi_format=ubi detach ; mtd erase ubi && ubi part ubi ; reset ++ubi_prepare_rootfs=if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi ++ubi_read_production=ubi read $loadaddr fit && iminfo $loadaddr && run ubi_prepare_rootfs ++ubi_read_recovery=ubi check recovery && ubi read $loadaddr recovery ++ubi_remove_rootfs=ubi check rootfs_data && ubi remove rootfs_data ++ubi_write_production=ubi check fit && ubi remove fit ; run ubi_remove_rootfs ; ubi create fit $filesize dynamic 2 && ubi write $loadaddr fit $filesize ++ubi_write_recovery=ubi check recovery && ubi remove recovery ; run ubi_remove_rootfs ; ubi create recovery $filesize dynamic 3 && ubi write $loadaddr recovery $filesize ++_init_env=setenv _init_env ; run ubi_create_env ; saveenv ; saveenv ++_firstboot=setenv _firstboot ; run _switch_to_menu ; run _init_env ; run boot_first ++_switch_to_menu=setenv _switch_to_menu ; setenv bootdelay 3 ; setenv bootmenu_delay 3 ; setenv bootmenu_0 $bootmenu_0d ; setenv bootmenu_0d ; run _bootmenu_update_title ++_bootmenu_update_title=setenv _bootmenu_update_title ; setenv bootmenu_title "$bootmenu_title $ver" diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t-ubootmod.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t-ubootmod.dts new file mode 100644 index 0000000000..809e625ce1 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t-ubootmod.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-ax3000t.dtsi" + +/ { + model = "Xiaomi Mi Router AX3000T (OpenWrt U-Boot layout)"; + compatible = "xiaomi,mi-router-ax3000t-ubootmod", "mediatek,mt7981"; +}; + +&partitions { + partition@600000 { + label = "ubi"; + reg = <0x600000 0x7000000>; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dts new file mode 100644 index 0000000000..cc0d44fdf5 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dts @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-ax3000t.dtsi" + +/ { + model = "Xiaomi Mi Router AX3000T"; + compatible = "xiaomi,mi-router-ax3000t", "mediatek,mt7981"; +}; + +&spi_nand { + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; +}; + +&partitions { + // ubi_kernel is the ubi partition in stock. + partition@600000 { + label = "ubi_kernel"; + reg = <0x600000 0x2200000>; + }; + + /* ubi is the result of squashing + * consecutive stock partitions: + * - ubi1 + * - overlay + * - data + */ + partition@2800000 { + label = "ubi"; + reg = <0x2800000 0x4e00000>; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi new file mode 100644 index 0000000000..7b6fde8465 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-ax3000t.dtsi @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include "mt7981b-xiaomi-mi-router-common.dtsi" + +&gmac0 { + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 (-2)>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + status = "okay"; + + nfc@57 { + compatible = "nt082c"; + reg = <0x57>; + }; +}; + +&pio { + i2c_pins: i2c-pins { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-common.dtsi b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-common.dtsi new file mode 100644 index 0000000000..d6872395a9 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-common.dtsi @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; +#include +#include + +#include "mt7981.dtsi" + +/ { + aliases { + serial0 = &uart0; + led-boot = &led_status_yellow; + led-failsafe = &led_status_yellow; + led-running = &led_status_blue; + led-upgrade = &led_status_yellow; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0 0x40000000 0 0x10000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-mesh { + label = "mesh"; + gpios = <&pio 0 GPIO_ACTIVE_LOW>; + linux,code = ; + linux,input-type = ; + }; + + button-reset { + label = "reset"; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds: leds { + compatible = "gpio-leds"; + + led_status_blue: led-status-blue { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + + led_status_yellow: led-status-yellow { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + }; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "wan"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + + partitions: partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00 0x100000>; + read-only; + }; + + partition@100000 { + label = "Nvram"; + reg = <0x100000 0x40000>; + }; + + partition@140000 { + label = "Bdata"; + reg = <0x140000 0x40000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x200000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@380000 { + label = "FIP"; + reg = <0x380000 0x200000>; + read-only; + }; + + partition@580000 { + label = "crash"; + reg = <0x580000 0x40000>; + read-only; + }; + + partition@5c0000 { + label = "crash_log"; + reg = <0x5c0000 0x40000>; + read-only; + }; + + partition@7600000 { + label = "KF"; + reg = <0x7600000 0x40000>; + read-only; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = ; + bias-pull-up = ; + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = ; + bias-pull-down = ; + }; + }; +}; + +&wifi { + status = "okay"; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi index 1e738a4474..87a2493a23 100644 --- a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi +++ b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u.dtsi @@ -1,252 +1,23 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT /dts-v1/; -#include -#include +#include "mt7981b-xiaomi-mi-router-common.dtsi" -#include "mt7981.dtsi" - -/ { - aliases { - serial0 = &uart0; - led-boot = &led_system_yellow; - led-failsafe = &led_system_yellow; - led-running = &led_system_blue; - led-upgrade = &led_system_yellow; - }; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - memory { - reg = <0 0x40000000 0 0x10000000>; - }; - - gpio-keys { - compatible = "gpio-keys"; - - reset { - label = "reset"; - gpios = <&pio 1 GPIO_ACTIVE_LOW>; - linux,code = ; - }; - - mesh { - label = "mesh"; - gpios = <&pio 0 GPIO_ACTIVE_LOW>; - linux,code = ; - linux,input-type = ; - }; - }; - - leds { - compatible = "gpio-leds"; - - led_system_blue: system_blue { - label = "blue:system"; - gpios = <&pio 9 GPIO_ACTIVE_LOW>; - }; - - led_system_yellow: system_yellow { - label = "yellow:system"; - gpios = <&pio 10 GPIO_ACTIVE_LOW>; - }; - - led_network_blue { - label = "blue:network"; - gpios = <&pio 11 GPIO_ACTIVE_LOW>; - }; - - led_network_yellow { - label = "yellow:network"; - gpios = <&pio 12 GPIO_ACTIVE_LOW>; - }; - }; +&gmac0 { + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_4 (-1)>; }; -ð { - status = "okay"; +&leds { + led-wan-blue { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 11 GPIO_ACTIVE_LOW>; + }; - gmac0: mac@0 { - compatible = "mediatek,eth-mac"; - reg = <0>; - phy-mode = "2500base-x"; - - nvmem-cells = <&macaddr_factory_4 (-1)>; - nvmem-cell-names = "mac-address"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; + led-wan-yellow { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; }; }; - -&mdio_bus { - switch: switch@1f { - compatible = "mediatek,mt7531"; - reg = <31>; - reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; - interrupt-controller; - #interrupt-cells = <1>; - interrupt-parent = <&pio>; - interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; - }; -}; - -&switch { - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - label = "wan"; - }; - - port@1 { - reg = <1>; - label = "lan2"; - }; - - port@2 { - reg = <2>; - label = "lan3"; - }; - - port@3 { - reg = <3>; - label = "lan4"; - }; - - port@6 { - reg = <6>; - ethernet = <&gmac0>; - phy-mode = "2500base-x"; - - fixed-link { - speed = <2500>; - full-duplex; - pause; - }; - }; - }; -}; - -&spi0 { - pinctrl-names = "default"; - pinctrl-0 = <&spi0_flash_pins>; - status = "okay"; - - spi_nand: flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "spi-nand"; - reg = <0>; - - spi-max-frequency = <52000000>; - spi-tx-bus-width = <4>; - spi-rx-bus-width = <4>; - - partitions: partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "BL2"; - reg = <0x00 0x100000>; - read-only; - }; - - partition@100000 { - label = "Nvram"; - reg = <0x100000 0x40000>; - }; - - partition@140000 { - label = "Bdata"; - reg = <0x140000 0x40000>; - }; - - factory: partition@180000 { - label = "Factory"; - reg = <0x180000 0x200000>; - read-only; - - nvmem-layout { - compatible = "fixed-layout"; - #address-cells = <1>; - #size-cells = <1>; - - macaddr_factory_4: macaddr@4 { - compatible = "mac-base"; - reg = <0x4 0x6>; - #nvmem-cell-cells = <1>; - }; - }; - }; - - partition@380000 { - label = "FIP"; - reg = <0x380000 0x200000>; - read-only; - }; - - partition@580000 { - label = "crash"; - reg = <0x580000 0x40000>; - read-only; - }; - - partition@5c0000 { - label = "crash_log"; - reg = <0x5c0000 0x40000>; - read-only; - }; - - partition@7600000 { - label = "KF"; - reg = <0x7600000 0x40000>; - read-only; - }; - }; - }; -}; - -&pio { - spi0_flash_pins: spi0-pins { - mux { - function = "spi"; - groups = "spi0", "spi0_wp_hold"; - }; - - conf-pu { - pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; - drive-strength = ; - bias-pull-up = ; - }; - - conf-pd { - pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; - drive-strength = ; - bias-pull-down = ; - }; - }; -}; - -&wifi { - status = "okay"; - - mediatek,mtd-eeprom = <&factory 0x0>; -}; - -&uart0 { - status = "okay"; -}; - -&watchdog { - status = "okay"; -}; diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds index b786558618..51654ae87f 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds @@ -36,7 +36,7 @@ routerich,ax3000) xiaomi,mi-router-wr30u-112m-nmbm|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,mi-router-wr30u-ubootmod) - ucidef_set_led_netdev "wan" "wan" "blue:network" "wan" + ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" "link tx rx" ;; xiaomi,redmi-router-ax6000-stock|\ xiaomi,redmi-router-ax6000-ubootmod) diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network index a36d998a40..dd3464b72c 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network @@ -72,6 +72,8 @@ mediatek_setup_interfaces() tplink,tl-xdr6086) ucidef_set_interfaces_lan_wan "lan1 lan2" eth1 ;; + xiaomi,mi-router-ax3000t|\ + xiaomi,mi-router-ax3000t-ubootmod|\ xiaomi,mi-router-wr30u-112m-nmbm|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,mi-router-wr30u-ubootmod|\ @@ -158,6 +160,8 @@ mediatek_setup_macs() wan_mac=$label_mac lan_mac=$(macaddr_add "$label_mac" 1) ;; + xiaomi,mi-router-ax3000t|\ + xiaomi,mi-router-ax3000t-ubootmod|\ xiaomi,mi-router-wr30u-112m-nmbm|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,mi-router-wr30u-ubootmod|\ diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index 9600f8745f..65ec5d8271 100755 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -49,6 +49,7 @@ xiaomi_initial_setup() local board=$(board_name) case "$board" in + xiaomi,mi-router-ax3000t|\ xiaomi,mi-router-wr30u-stock) fw_setenv mtdparts "nmbm0:1024k(bl2),256k(Nvram),256k(Bdata),2048k(factory),2048k(fip),256k(crash),256k(crash_log),34816k(ubi),34816k(ubi1),32768k(overlay),12288k(data),256k(KF)" ;; @@ -126,6 +127,7 @@ platform_do_upgrade() { tplink,tl-xdr4288|\ tplink,tl-xdr6086|\ tplink,tl-xdr6088|\ + xiaomi,mi-router-ax3000t-ubootmod|\ xiaomi,mi-router-wr30u-ubootmod|\ xiaomi,redmi-router-ax6000-ubootmod) CI_KERNPART="fit" @@ -140,6 +142,7 @@ platform_do_upgrade() { EMMC_ROOT_DEV="$(cmdline_get_var root)" emmc_do_upgrade "$1" ;; + xiaomi,mi-router-ax3000t|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,redmi-router-ax6000-stock) CI_KERN_UBIPART=ubi_kernel @@ -211,6 +214,7 @@ platform_pre_upgrade() { asus,tuf-ax6000) asus_initial_setup ;; + xiaomi,mi-router-ax3000t|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,redmi-router-ax6000-stock) xiaomi_initial_setup diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index 15951df1ec..c079fae0b0 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -728,6 +728,51 @@ define Device/ubnt_unifi-6-plus endef TARGET_DEVICES += ubnt_unifi-6-plus +define Device/xiaomi_mi-router-ax3000t + DEVICE_VENDOR := Xiaomi + DEVICE_MODEL := Mi Router AX3000T + DEVICE_DTS := mt7981b-xiaomi-mi-router-ax3000t + DEVICE_DTS_DIR := ../dts + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + ARTIFACTS := initramfs-factory.ubi + ARTIFACT/initramfs-factory.ubi := append-image-stage initramfs-kernel.bin | ubinize-kernel +endif + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += xiaomi_mi-router-ax3000t + +define Device/xiaomi_mi-router-ax3000t-ubootmod + DEVICE_VENDOR := Xiaomi + DEVICE_MODEL := Mi Router AX3000T (OpenWrt U-Boot layout) + DEVICE_DTS := mt7981b-xiaomi-mi-router-ax3000t-ubootmod + DEVICE_DTS_DIR := ../dts + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware + KERNEL_IN_UBI := 1 + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7981-bl2 spim-nand-ddr3 + ARTIFACT/bl31-uboot.fip := mt7981-bl31-uboot xiaomi_mi-router-ax3000t +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + ARTIFACTS += initramfs-factory.ubi + ARTIFACT/initramfs-factory.ubi := append-image-stage initramfs-recovery.itb | ubinize-kernel +endif +endef +TARGET_DEVICES += xiaomi_mi-router-ax3000t-ubootmod + define Device/xiaomi_mi-router-wr30u-112m-nmbm DEVICE_VENDOR := Xiaomi DEVICE_MODEL := Mi Router WR30U (112M UBI with NMBM-Enabled layout) From ebed3f65ea681f55b3ccfeb208664552970cb7fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samir=20Ibrad=C5=BEi=C4=87?= Date: Mon, 1 Jan 2024 16:23:09 +0900 Subject: [PATCH 053/222] qualcommax: Fix Buffalo WXR-5950AX12 wifi MAC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, WiFi interfaces on WXR-5950AX12 / WXR-6000AX12 devices come up with some MAC addresses inconsistent with vendor and Ethernet addresses. This adds a hotplug override in order to make it consistent with what is in u-boot env as well as OAM firmware where 1st radio MAC is set at Ethernet MAC + 8, and 2nd radio mac at Ethernet MAC + 16. fw_printenv | grep addr ethaddr=68:e1:dc:xx:xx:d8 ipaddr=192.168.11.1 wlan0addr=68:e1:dc:xx:xx:e0 wlan1addr=68:e1:dc:xx:xx:e8 wlan2addr=00:00:00:00:00:00 For OEM bootlog and MAC assagnment check https://openwrt.org/toh/buffalo/wxr-5950ax12#openwrt_uimage_tftp_bootlog Tested-by: Samir Ibradžić # Buffalo WXR-6000AX12P Signed-off-by: Samir Ibradžić --- .../base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index 3573942c54..f951d925ab 100644 --- a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -14,6 +14,10 @@ case "$board" in [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 1 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 2 > /sys${DEVPATH}/macaddress ;; + buffalo,wxr-5950ax12) + [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 8 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 16 > /sys${DEVPATH}/macaddress + ;; zte,mf269) [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 2 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 3 > /sys${DEVPATH}/macaddress From 184bd28064bc591bf907c42afc9e0b9c1b9858b4 Mon Sep 17 00:00:00 2001 From: Tony Ambardar Date: Sat, 6 Jan 2024 09:26:33 -0800 Subject: [PATCH 054/222] build: fix toplevel check target Partially revert changes to verbose logging that break the 'check' target dependencies and trigger many runtime warnings like: /home/kodidev/openwrt-project/include/toplevel.mk:213: *** mixed implicit and normal rules: deprecated syntax Fixes: e4a43cda0 ("build: allow var.% targets to bypass the prepare steps") Signed-off-by: Tony Ambardar --- include/toplevel.mk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/toplevel.mk b/include/toplevel.mk index 96f32139d9..f2dfde60cf 100644 --- a/include/toplevel.mk +++ b/include/toplevel.mk @@ -210,7 +210,9 @@ prereq:: prepare-tmpinfo .config @+$(NO_TRACE_MAKE) -r -s $@ check: .config FORCE -check val.% var.%: FORCE + @+$(NO_TRACE_MAKE) -r -s $@ QUIET= V=s + +val.% var.%: FORCE @+$(NO_TRACE_MAKE) -r -s $@ QUIET= V=s WARN_PARALLEL_ERROR = $(if $(BUILD_LOG),,$(and $(filter -j,$(MAKEFLAGS)),$(findstring s,$(OPENWRT_VERBOSE)))) From c0d7842bf2d0901697cc7d593f1db787252f549a Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Sat, 30 Dec 2023 19:52:18 +0800 Subject: [PATCH 055/222] ramips: add missing syscon compatible strings for MT7688 and RT3052 MT7688 devices use the "mt7628an.dtsi" as the template. And RT3052 devices use the "rt3050.dtsi" as template. Therefore, we need to add the corresponding system controller compatible strings to make them work properly. Fixes: 1f818b09f8ae ("ramips: add proper system clock and reset driver support for legacy SoCs") Fixes: #14305 Signed-off-by: Shiji Yang --- target/linux/ramips/dts/mt7628an.dtsi | 2 +- target/linux/ramips/dts/rt3050.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/ramips/dts/mt7628an.dtsi b/target/linux/ramips/dts/mt7628an.dtsi index 97f77f6b38..906ea03fe9 100644 --- a/target/linux/ramips/dts/mt7628an.dtsi +++ b/target/linux/ramips/dts/mt7628an.dtsi @@ -39,7 +39,7 @@ #size-cells = <1>; sysc: syscon@0 { - compatible = "ralink,mt7628-sysc", "syscon"; + compatible = "ralink,mt7628-sysc", "ralink,mt7688-sysc", "syscon"; reg = <0x0 0x100>; #clock-cells = <1>; #reset-cells = <1>; diff --git a/target/linux/ramips/dts/rt3050.dtsi b/target/linux/ramips/dts/rt3050.dtsi index d23303964f..30a3f898cd 100644 --- a/target/linux/ramips/dts/rt3050.dtsi +++ b/target/linux/ramips/dts/rt3050.dtsi @@ -40,7 +40,7 @@ #size-cells = <1>; sysc: syscon@0 { - compatible = "ralink,rt3050-sysc", "syscon"; + compatible = "ralink,rt3050-sysc", "ralink,rt3052-sysc", "syscon"; reg = <0x0 0x100>; #clock-cells = <1>; #reset-cells = <1>; From d13d513b9f14b29175c15a8945e2ad772665e821 Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Sat, 18 Nov 2023 16:53:20 +0100 Subject: [PATCH 056/222] ath79: mikrotik: add RB912UAG-5HPnD as alternative name Image for RB912UAG-2HPnD supports the 5GHz variant without modifications. Add it as alternative name, so it can be found easier. While at that, adjust board display name in device tree, to reflect that. Signed-off-by: Lech Perczak --- .../ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts | 2 +- target/linux/ath79/image/mikrotik.mk | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts index 121a5d0396..b550026f07 100644 --- a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts @@ -7,7 +7,7 @@ / { compatible = "mikrotik,routerboard-912uag-2hpnd", "qca,ar9342"; - model = "MikroTik RouterBOARD 912UAG-2HPnD"; + model = "MikroTik RouterBOARD 912UAG-(2,5)HPnD"; aliases { led-boot = &led_power; diff --git a/target/linux/ath79/image/mikrotik.mk b/target/linux/ath79/image/mikrotik.mk index d26420c7f5..fb98ccc122 100644 --- a/target/linux/ath79/image/mikrotik.mk +++ b/target/linux/ath79/image/mikrotik.mk @@ -32,6 +32,8 @@ define Device/mikrotik_routerboard-912uag-2hpnd $(Device/mikrotik_nand) SOC := ar9342 DEVICE_MODEL := RouterBOARD 912UAG-2HPnD + DEVICE_ALT0_VENDOR := Mikrotik + DEVICE_ALT0_MODEL := RouterBOARD 912UAG-5HPnD DEVICE_PACKAGES += kmod-usb-ehci kmod-usb2 SUPPORTED_DEVICES += rb-912uag-2hpnd endef From bcc44b1212b2369d04f68950f6422b8aff7ec09e Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Sat, 18 Nov 2023 16:53:45 +0100 Subject: [PATCH 057/222] ath79: support for MikroTik RouterBOARD 911G-(2,5)HPnD This is a stripped-down version of RB912UAG-(2,5)HPnD, without USB, miniPCIe and SIM sockets. This board has been supported in the ar71xx. Add support based on RB912UAG board, by splitting out the common part to .dtsi, and creating separate device tree for the stripped-down version. Links: * https://mikrotik.com/product/RB911G-2HPnD * https://mikrotik.com/product/RB911G-5HPnD * https://openwrt.org/toh/hwdata/mikrotik/mikrotik_rb911g-5hpnd Hardware: * SoC: Atheros AR9342, * RAM: DDR 64MB, * SPI NOR: 64KB, * NAND: 128MB, * Ethernet: x1 10/100/1000 port with passive POE in, * Wi-Fi: 802.11 a/b/g/n (depending on band variant) * LEDs: 5 general purpose LEDs (led1..led5), power LED, user LED, Ethernet phy LED, * Button, * Beeper. Flashing: * Use the RouterBOARD Reset button to enable TFTP netboot, boot kernel and initramfs and then perform sysupgrade. * From ar71xx OpenWrt firmware run: $ sysupgrade -F /tmp/ For more info see: https://openwrt.org/toh/mikrotik/common. Signed-off-by: Lech Perczak --- ...ar9342_mikrotik_routerboard-911g-xhpnd.dts | 11 + .../dts/ar9342_mikrotik_routerboard-911g.dtsi | 224 ++++++++++++++++++ ...9342_mikrotik_routerboard-912uag-2hpnd.dts | 218 +---------------- target/linux/ath79/image/mikrotik.mk | 10 + .../base-files/etc/board.d/02_network | 2 + .../etc/hotplug.d/firmware/10-ath9k-eeprom | 1 + .../base-files/lib/upgrade/platform.sh | 1 + 7 files changed, 250 insertions(+), 217 deletions(-) create mode 100644 target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g-xhpnd.dts create mode 100644 target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g.dtsi diff --git a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g-xhpnd.dts b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g-xhpnd.dts new file mode 100644 index 0000000000..5fa44b4412 --- /dev/null +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g-xhpnd.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "ar9342_mikrotik_routerboard-911g.dtsi" + +#include +#include + +/ { + compatible = "mikrotik,routerboard-911g-xhpnd", "qca,ar9342"; + model = "MikroTik RouterBOARD 911G-(2,5)HPnD"; +}; diff --git a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g.dtsi b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g.dtsi new file mode 100644 index 0000000000..86b4bc358b --- /dev/null +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-911g.dtsi @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "ar9344.dtsi" + +#include +#include + +/ { + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + gpio_key: gpio_key { + compatible = "mikrotik,gpio-rb91x-key"; + gpio-controller; + #gpio-cells = <2>; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; + }; + + gpio_latch: gpio_latch { + compatible = "gpio-latch"; + gpio-controller; + #gpio-cells = <2>; + gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, + <&gpio 1 GPIO_ACTIVE_HIGH>, + <&gpio 2 GPIO_ACTIVE_HIGH>, + <&gpio 3 GPIO_ACTIVE_HIGH>, + <0>, /* Not connected */ + <&gpio 13 GPIO_ACTIVE_HIGH>, + <&gpio 14 GPIO_ACTIVE_HIGH>, + <&gpio_key 0 GPIO_ACTIVE_HIGH>, + <&gpio 11 GPIO_ACTIVE_LOW>; /* Latch Enable */ + }; + + nand_gpio { + compatible = "mikrotik,rb91x-nand"; + + gpios = <&gpio_latch 3 GPIO_ACTIVE_HIGH>, /* Read */ + <&gpio 4 GPIO_ACTIVE_HIGH>, /* Ready (RDY) */ + <&gpio_latch 5 GPIO_ACTIVE_LOW>, /* Chip Enable (nCE) */ + <&gpio_latch 6 GPIO_ACTIVE_HIGH>, /* Command Latch Enable (CLE) */ + <&gpio_latch 7 GPIO_ACTIVE_HIGH>, /* Address Latch Enable (ALE) */ + <&gpio 12 GPIO_ACTIVE_LOW>, /* Read/Write Enable (nRW) */ + <&gpio_latch 8 GPIO_ACTIVE_LOW>, /* Latch Enable (nLE) */ + <&gpio_key 2 GPIO_ACTIVE_HIGH>; /* Key poll disable */ + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "booter"; + reg = <0x0 0x0040000>; + read-only; + }; + + partition@40000 { + label = "kernel"; + reg = <0x0040000 0x03c0000>; + }; + + partition@400000 { + label = "ubi"; + reg = <0x0400000 0x7c00000>; + }; + }; + }; + + keys { + compatible = "gpio-keys-polled"; + poll-interval = <20>; + + button-reset { + label = "reset"; + linux,code = ; + gpios = <&gpio_key 1 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "green:power"; + gpios = <&gpio_latch 1 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + user { + label = "green:user"; + gpios = <&gpio_latch 2 GPIO_ACTIVE_HIGH>; + }; + + led1 { + label = "green:led1"; + gpios = <&ssr 0 GPIO_ACTIVE_HIGH>; + }; + + led2 { + label = "green:led2"; + gpios = <&ssr 1 GPIO_ACTIVE_HIGH>; + }; + + led3 { + label = "green:led3"; + gpios = <&ssr 2 GPIO_ACTIVE_HIGH>; + }; + + led4 { + label = "green:led4"; + gpios = <&ssr 3 GPIO_ACTIVE_HIGH>; + }; + + led5 { + label = "green:led5"; + gpios = <&ssr 4 GPIO_ACTIVE_HIGH>; + }; + }; + + gpio-export { + compatible = "gpio-export"; + + beeper { + gpio-export,name = "beeper"; + gpio-export,output = <1>; /* Must be 1 to avoid EMI induced clicking noise */ + gpios = <&ssr 5 GPIO_ACTIVE_HIGH>; + }; + + usb_power { + gpio-export,name = "power-usb"; + gpio-export,output = <1>; + gpios = <&ssr 6 GPIO_ACTIVE_HIGH>; + }; + + pcie_power { + gpio-export,name = "power-pcie"; + gpio-export,output = <0>; + gpios = <&ssr 7 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&ref { + clock-frequency = <40000000>; +}; + +&spi { + status = "okay"; + + compatible = "qca,ar7100-spi"; + + cs-gpios = <0>, <&gpio_latch 0 GPIO_ACTIVE_LOW>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "mikrotik,routerboot-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "routerboot"; + reg = <0x0 0x0>; + read-only; + }; + + hard_config { + read-only; + }; + + bios { + size = <0x1000>; + read-only; + }; + + soft_config { + }; + }; + }; + + ssr: ssr@1 { + compatible = "fairchild,74hc595"; + gpio-controller; + #gpio-cells = <2>; + registers-number = <1>; + reg = <1>; + spi-max-frequency = <50000000>; + }; +}; + +&mdio0 { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; +}; + +ð0 { + status = "okay"; + + phy-mode = "rgmii-id"; + phy-handle = <&phy0>; + pll-data = <0x02000000 0x00000101 0x00001313>; + + gmac-config { + device = <&gmac>; + rgmii-gmac0 = <1>; + rxd-delay = <1>; + txd-delay = <1>; + }; +}; + +&wmac { + status = "okay"; + qca,no-eeprom; +}; diff --git a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts index b550026f07..81d7284b3d 100644 --- a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "ar9344.dtsi" +#include "ar9342_mikrotik_routerboard-911g.dtsi" #include #include @@ -8,222 +8,6 @@ / { compatible = "mikrotik,routerboard-912uag-2hpnd", "qca,ar9342"; model = "MikroTik RouterBOARD 912UAG-(2,5)HPnD"; - - aliases { - led-boot = &led_power; - led-failsafe = &led_power; - led-running = &led_power; - led-upgrade = &led_power; - }; - - gpio_key: gpio_key { - compatible = "mikrotik,gpio-rb91x-key"; - gpio-controller; - #gpio-cells = <2>; - gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; - }; - - gpio_latch: gpio_latch { - compatible = "gpio-latch"; - gpio-controller; - #gpio-cells = <2>; - gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, - <&gpio 1 GPIO_ACTIVE_HIGH>, - <&gpio 2 GPIO_ACTIVE_HIGH>, - <&gpio 3 GPIO_ACTIVE_HIGH>, - <0>, /* Not connected */ - <&gpio 13 GPIO_ACTIVE_HIGH>, - <&gpio 14 GPIO_ACTIVE_HIGH>, - <&gpio_key 0 GPIO_ACTIVE_HIGH>, - <&gpio 11 GPIO_ACTIVE_LOW>; /* Latch Enable */ - }; - - nand_gpio { - compatible = "mikrotik,rb91x-nand"; - - gpios = <&gpio_latch 3 GPIO_ACTIVE_HIGH>, /* Read */ - <&gpio 4 GPIO_ACTIVE_HIGH>, /* Ready (RDY) */ - <&gpio_latch 5 GPIO_ACTIVE_LOW>, /* Chip Enable (nCE) */ - <&gpio_latch 6 GPIO_ACTIVE_HIGH>, /* Command Latch Enable (CLE) */ - <&gpio_latch 7 GPIO_ACTIVE_HIGH>, /* Address Latch Enable (ALE) */ - <&gpio 12 GPIO_ACTIVE_LOW>, /* Read/Write Enable (nRW) */ - <&gpio_latch 8 GPIO_ACTIVE_LOW>, /* Latch Enable (nLE) */ - <&gpio_key 2 GPIO_ACTIVE_HIGH>; /* Key poll disable */ - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "booter"; - reg = <0x0 0x0040000>; - read-only; - }; - - partition@40000 { - label = "kernel"; - reg = <0x0040000 0x03c0000>; - }; - - partition@400000 { - label = "ubi"; - reg = <0x0400000 0x7c00000>; - }; - }; - }; - - keys { - compatible = "gpio-keys-polled"; - poll-interval = <20>; - - button-reset { - label = "reset"; - linux,code = ; - gpios = <&gpio_key 1 GPIO_ACTIVE_LOW>; - }; - }; - - leds { - compatible = "gpio-leds"; - - led_power: power { - label = "green:power"; - gpios = <&gpio_latch 1 GPIO_ACTIVE_HIGH>; - default-state = "on"; - }; - - user { - label = "green:user"; - gpios = <&gpio_latch 2 GPIO_ACTIVE_HIGH>; - }; - - led1 { - label = "green:led1"; - gpios = <&ssr 0 GPIO_ACTIVE_HIGH>; - }; - - led2 { - label = "green:led2"; - gpios = <&ssr 1 GPIO_ACTIVE_HIGH>; - }; - - led3 { - label = "green:led3"; - gpios = <&ssr 2 GPIO_ACTIVE_HIGH>; - }; - - led4 { - label = "green:led4"; - gpios = <&ssr 3 GPIO_ACTIVE_HIGH>; - }; - - led5 { - label = "green:led5"; - gpios = <&ssr 4 GPIO_ACTIVE_HIGH>; - }; - }; - - gpio-export { - compatible = "gpio-export"; - - beeper { - gpio-export,name = "beeper"; - gpio-export,output = <1>; /* Must be 1 to avoid EMI induced clicking noise */ - gpios = <&ssr 5 GPIO_ACTIVE_HIGH>; - }; - - usb_power { - gpio-export,name = "power-usb"; - gpio-export,output = <1>; - gpios = <&ssr 6 GPIO_ACTIVE_HIGH>; - }; - - pcie_power { - gpio-export,name = "power-pcie"; - gpio-export,output = <0>; - gpios = <&ssr 7 GPIO_ACTIVE_HIGH>; - }; - }; -}; - -&ref { - clock-frequency = <40000000>; -}; - -&spi { - status = "okay"; - - compatible = "qca,ar7100-spi"; - - cs-gpios = <0>, <&gpio_latch 0 GPIO_ACTIVE_LOW>; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <50000000>; - - partitions { - compatible = "mikrotik,routerboot-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "routerboot"; - reg = <0x0 0x0>; - read-only; - }; - - hard_config { - read-only; - }; - - bios { - size = <0x1000>; - read-only; - }; - - soft_config { - }; - }; - }; - - ssr: ssr@1 { - compatible = "fairchild,74hc595"; - gpio-controller; - #gpio-cells = <2>; - registers-number = <1>; - reg = <1>; - spi-max-frequency = <50000000>; - }; -}; - -&mdio0 { - status = "okay"; - - phy0: ethernet-phy@0 { - reg = <0>; - }; -}; - -ð0 { - status = "okay"; - - phy-mode = "rgmii-id"; - phy-handle = <&phy0>; - pll-data = <0x02000000 0x00000101 0x00001313>; - - gmac-config { - device = <&gmac>; - rgmii-gmac0 = <1>; - rxd-delay = <1>; - txd-delay = <1>; - }; -}; - -&wmac { - status = "okay"; - qca,no-eeprom; }; &pcie { diff --git a/target/linux/ath79/image/mikrotik.mk b/target/linux/ath79/image/mikrotik.mk index fb98ccc122..1bd1323f07 100644 --- a/target/linux/ath79/image/mikrotik.mk +++ b/target/linux/ath79/image/mikrotik.mk @@ -28,6 +28,16 @@ define Device/mikrotik_routerboard-911-lite endef TARGET_DEVICES += mikrotik_routerboard-911-lite +define Device/mikrotik_routerboard-911g-xhpnd + $(Device/mikrotik_nand) + SOC := ar9342 + DEVICE_MODEL := RouterBOARD 911G-2HPnD + DEVICE_ALT0_VENDOR := Mikrotik + DEVICE_ALT0_MODEL := RouterBOARD 911G-5HPnD + SUPPORTED_DEVICES += rb-912uag-2hpnd +endef +TARGET_DEVICES += mikrotik_routerboard-911g-xhpnd + define Device/mikrotik_routerboard-912uag-2hpnd $(Device/mikrotik_nand) SOC := ar9342 diff --git a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network index d45af6dbb3..f13eca243b 100644 --- a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network +++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network @@ -20,6 +20,7 @@ ath79_setup_interfaces() "0@eth0" "1:lan:4" "2:lan:1" "3:lan:3" "4:lan:2" ;; mikrotik,routerboard-911-lite|\ + mikrotik,routerboard-911g-xhpnd|\ mikrotik,routerboard-912uag-2hpnd|\ mikrotik,routerboard-lhg-2nd|\ mikrotik,routerboard-lhg-5nd|\ @@ -61,6 +62,7 @@ ath79_setup_macs() case "$board" in mikrotik,routerboard-911-lite|\ + mikrotik,routerboard-911g-xhpnd|\ mikrotik,routerboard-912uag-2hpnd|\ mikrotik,routerboard-lhg-2nd|\ mikrotik,routerboard-lhg-5nd|\ diff --git a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom index cc05ba080b..e7bf17d0ec 100644 --- a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom +++ b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom @@ -24,6 +24,7 @@ case "$FIRMWARE" in "ath9k-eeprom-ahb-18100000.wmac.bin") case $board in mikrotik,routerboard-911-lite|\ + mikrotik,routerboard-911g-xhpnd|\ mikrotik,routerboard-912uag-2hpnd|\ mikrotik,routerboard-lhg-2nd|\ mikrotik,routerboard-lhg-5nd|\ diff --git a/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh b/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh index e3887bfc50..db0509d290 100644 --- a/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh +++ b/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh @@ -30,6 +30,7 @@ platform_do_upgrade() { case "$board" in mikrotik,routerboard-493g|\ + mikrotik,routerboard-911g-xhpnd|\ mikrotik,routerboard-912uag-2hpnd|\ mikrotik,routerboard-921gs-5hpacd-15s|\ mikrotik,routerboard-922uags-5hpacd|\ From 95b6d76c5a343d13aaf33df44d2d8518a2ede1b6 Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Sat, 18 Nov 2023 16:54:18 +0100 Subject: [PATCH 058/222] ath79: mikrotik: add rssileds support for Routerboard 911G and RB912UAG LEDs 1 through 5 are used for RSSI monitoring on factory firmware. Reflect that by creating appropriate rssileds configuration. Signed-off-by: Lech Perczak --- target/linux/ath79/image/mikrotik.mk | 3 ++- .../linux/ath79/mikrotik/base-files/etc/board.d/01_leds | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/target/linux/ath79/image/mikrotik.mk b/target/linux/ath79/image/mikrotik.mk index 1bd1323f07..06a2417faa 100644 --- a/target/linux/ath79/image/mikrotik.mk +++ b/target/linux/ath79/image/mikrotik.mk @@ -34,6 +34,7 @@ define Device/mikrotik_routerboard-911g-xhpnd DEVICE_MODEL := RouterBOARD 911G-2HPnD DEVICE_ALT0_VENDOR := Mikrotik DEVICE_ALT0_MODEL := RouterBOARD 911G-5HPnD + DEVICE_PACKAGES += rssileds SUPPORTED_DEVICES += rb-912uag-2hpnd endef TARGET_DEVICES += mikrotik_routerboard-911g-xhpnd @@ -44,7 +45,7 @@ define Device/mikrotik_routerboard-912uag-2hpnd DEVICE_MODEL := RouterBOARD 912UAG-2HPnD DEVICE_ALT0_VENDOR := Mikrotik DEVICE_ALT0_MODEL := RouterBOARD 912UAG-5HPnD - DEVICE_PACKAGES += kmod-usb-ehci kmod-usb2 + DEVICE_PACKAGES += kmod-usb-ehci kmod-usb2 rssileds SUPPORTED_DEVICES += rb-912uag-2hpnd endef TARGET_DEVICES += mikrotik_routerboard-912uag-2hpnd diff --git a/target/linux/ath79/mikrotik/base-files/etc/board.d/01_leds b/target/linux/ath79/mikrotik/base-files/etc/board.d/01_leds index 66fa2ee6ac..16cb628445 100644 --- a/target/linux/ath79/mikrotik/base-files/etc/board.d/01_leds +++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/01_leds @@ -16,6 +16,15 @@ mikrotik,routerboard-lhg-5nd) ucidef_set_led_rssi "rssimediumhigh" "rssimediumhigh" "green:rssimediumhigh" "wlan0" "60" "100" ucidef_set_led_rssi "rssihigh" "rssihigh" "green:rssihigh" "wlan0" "80" "100" ;; +mikrotik,routerboard-911g-xhpnd|\ +mikrotik,routerboard-912uag-2hpnd) + ucidef_set_rssimon "wlan0" "200000" "1" + ucidef_set_led_rssi "rssilow" "rssilow" "green:led1" "wlan0" "1" "100" + ucidef_set_led_rssi "rssimediumlow" "rssimediumlow" "green:led2" "wlan0" "20" "100" + ucidef_set_led_rssi "rssimedium" "rssimedium" "green:led3" "wlan0" "40" "100" + ucidef_set_led_rssi "rssimediumhigh" "rssimediumhigh" "green:led4" "wlan0" "60" "100" + ucidef_set_led_rssi "rssihigh" "rssihigh" "green:led5" "wlan0" "80" "100" + ;; mikrotik,routerboard-750-r2|\ mikrotik,routerboard-951ui-2hnd|\ mikrotik,routerboard-951ui-2nd|\ From c2ab56a7549b75b9592ddcfc0cf1040281f7d28a Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Sat, 18 Nov 2023 16:54:59 +0100 Subject: [PATCH 059/222] ath79: support MikroTik RouterBOARD 911G-5HPacD The MikroTik RouterBOARD 911G-5HPacD is a stripped-down version of RB921GS-5HPacD, removing the SFP cage. This ports the board from ar71xx, and is based on support for RB921GS-5HPacD. Disable mdio1 and eth1 nodes in routerboard-92x.dtsi, then re-enable them in devices using that, so the newly-added device has the port disabled properly. See https://mikrotik.com/product/RB911G-5HPacD for more info. Specifications: - SoC: Qualcomm Atheros QCA9558 (720 MHz) - RAM: 128 MB - Storage: 128 MB NAND - Wireless: external QCA9892 802.11a/ac 2x2:2 - Ethernet: 1x 1000/100/10 Mbps, integrated, via AR8031 PHY, passive PoE in Working: - NAND storage detection - Ethernet - Wireless - 1x user LED (blinks during boot, sysupgrade) - Reset button - Sysupgrade Installation: - Boot initramfs image via TFTP and then flash sysupgrade image Signed-off-by: Lech Perczak --- ...a9558_mikrotik_routerboard-911g-5hpacd.dts | 29 +++++++++++++++++++ ..._mikrotik_routerboard-921gs-5hpacd-15s.dts | 8 +++++ ...58_mikrotik_routerboard-922uags-5hpacd.dts | 8 +++++ .../dts/qca9558_mikrotik_routerboard-92x.dtsi | 4 --- target/linux/ath79/image/mikrotik.mk | 9 ++++++ .../base-files/etc/board.d/02_network | 1 + .../etc/hotplug.d/firmware/11-ath10k-caldata | 1 + .../base-files/lib/upgrade/platform.sh | 1 + 8 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 target/linux/ath79/dts/qca9558_mikrotik_routerboard-911g-5hpacd.dts diff --git a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-911g-5hpacd.dts b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-911g-5hpacd.dts new file mode 100644 index 0000000000..22784075f6 --- /dev/null +++ b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-911g-5hpacd.dts @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qca9558_mikrotik_routerboard-92x.dtsi" + +/ { + compatible = "mikrotik,routerboard-911g-5hpacd", "qca,qca9558"; + model = "MikroTik RouterBOARD 911G-5HPacD"; + + ath10k-leds { + compatible = "gpio-leds"; + + wlan5g { + label = "green:wlan5g"; + gpios = <&ath10k 0 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + }; +}; + +&pcie1 { + status = "okay"; + + ath10k: wifi@0,0 { + compatible = "qcom,ath10k"; + reg = <0 0 0 0 0>; + #gpio-cells = <2>; + gpio-controller; + }; +}; diff --git a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-921gs-5hpacd-15s.dts b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-921gs-5hpacd-15s.dts index d1f307bd48..36283ec228 100644 --- a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-921gs-5hpacd-15s.dts +++ b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-921gs-5hpacd-15s.dts @@ -17,6 +17,14 @@ }; }; +&mdio1 { + status = "okay"; +}; + +ð1 { + status = "okay"; +}; + &pcie1 { status = "okay"; diff --git a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-922uags-5hpacd.dts b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-922uags-5hpacd.dts index 8ad834fe61..553dff0853 100644 --- a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-922uags-5hpacd.dts +++ b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-922uags-5hpacd.dts @@ -25,6 +25,14 @@ }; }; +&mdio1 { + status = "okay"; +}; + +ð1 { + status = "okay"; +}; + &pcie0 { status = "okay"; diff --git a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-92x.dtsi b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-92x.dtsi index 82b8c2ae56..bc85cad9b3 100644 --- a/target/linux/ath79/dts/qca9558_mikrotik_routerboard-92x.dtsi +++ b/target/linux/ath79/dts/qca9558_mikrotik_routerboard-92x.dtsi @@ -86,8 +86,6 @@ }; &mdio1 { - status = "okay"; - phy_sfp: ethernet-phy@0 { reg = <0>; phy-mode = "sgmii"; @@ -96,8 +94,6 @@ }; ð1 { - status = "okay"; - phy-handle = <&phy_sfp>; pll-data = <0x03000000 0x00000101 0x00001616>; qca955x-sgmii-fixup; diff --git a/target/linux/ath79/image/mikrotik.mk b/target/linux/ath79/image/mikrotik.mk index 06a2417faa..19cbf30933 100644 --- a/target/linux/ath79/image/mikrotik.mk +++ b/target/linux/ath79/image/mikrotik.mk @@ -50,6 +50,15 @@ define Device/mikrotik_routerboard-912uag-2hpnd endef TARGET_DEVICES += mikrotik_routerboard-912uag-2hpnd +define Device/mikrotik_routerboard-911g-5hpacd + $(Device/mikrotik_nand) + SOC := qca9558 + DEVICE_MODEL := RouterBOARD 911G-5HPacD + DEVICE_PACKAGES += kmod-ath10k-ct ath10k-firmware-qca988x-ct + SUPPORTED_DEVICES += rb-921gs-5hpacd-r2 +endef +TARGET_DEVICES += mikrotik_routerboard-911g-5hpacd + define Device/mikrotik_routerboard-921gs-5hpacd-15s $(Device/mikrotik_nand) SOC := qca9558 diff --git a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network index f13eca243b..4da5884045 100644 --- a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network +++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network @@ -62,6 +62,7 @@ ath79_setup_macs() case "$board" in mikrotik,routerboard-911-lite|\ + mikrotik,routerboard-911g-5hpacd|\ mikrotik,routerboard-911g-xhpnd|\ mikrotik,routerboard-912uag-2hpnd|\ mikrotik,routerboard-lhg-2nd|\ diff --git a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/11-ath10k-caldata index 5b918d966c..da331dc0ea 100644 --- a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +++ b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -11,6 +11,7 @@ board=$(board_name) case "$FIRMWARE" in "ath10k/cal-pci-0000:00:00.0.bin") case $board in + mikrotik,routerboard-911g-5hpacd|\ mikrotik,routerboard-921gs-5hpacd-15s|\ mikrotik,routerboard-951ui-2nd|\ mikrotik,routerboard-952ui-5ac2nd|\ diff --git a/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh b/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh index db0509d290..c4d401b8ae 100644 --- a/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh +++ b/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh @@ -30,6 +30,7 @@ platform_do_upgrade() { case "$board" in mikrotik,routerboard-493g|\ + mikrotik,routerboard-911g-5hpacd|\ mikrotik,routerboard-911g-xhpnd|\ mikrotik,routerboard-912uag-2hpnd|\ mikrotik,routerboard-921gs-5hpacd-15s|\ From 8226c8d306be0d617016f9c8e3f1659ef41e8ca6 Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sun, 3 Dec 2023 12:40:46 +0000 Subject: [PATCH 060/222] ramips: update leds & buttons dts description This commit: 1. Removes deprecated "label" property from the dts leds subnnodes; 2. Updates buttons and leds dts description according to kernel docs examples. Scope: devices well known to me. Run-tested: TP-Link ec330-g5u, WiFire S1500.nbn Signed-off-by: Mikhail Zhilkin --- .../linux/ramips/dts/mt7620a_sercomm_cpj.dtsi | 2 - .../ramips/dts/mt7621_arcadyan_wg4xx223.dtsi | 8 ++-- .../dts/mt7621_beeline_smartbox-flash.dts | 3 +- .../dts/mt7621_beeline_smartbox-giga.dts | 5 +-- .../dts/mt7621_beeline_smartbox-pro.dts | 3 +- .../mt7621_beeline_smartbox-turbo-plus.dts | 7 +--- .../linux/ramips/dts/mt7621_etisalat_s3.dts | 7 +--- .../dts/mt7621_sercomm_dxx_nand_256m.dtsi | 11 ++---- .../ramips/dts/mt7621_sercomm_s1500.dtsi | 39 ++++++------------- .../ramips/dts/mt7621_tplink_ec330-g5u-v1.dts | 27 ++++--------- .../ramips/dts/mt7621_wifire_s1500-nbn.dts | 1 - .../mt7621/base-files/etc/board.d/01_leds | 14 +++---- 12 files changed, 39 insertions(+), 88 deletions(-) diff --git a/target/linux/ramips/dts/mt7620a_sercomm_cpj.dtsi b/target/linux/ramips/dts/mt7620a_sercomm_cpj.dtsi index e903f9f729..8c565385e8 100644 --- a/target/linux/ramips/dts/mt7620a_sercomm_cpj.dtsi +++ b/target/linux/ramips/dts/mt7620a_sercomm_cpj.dtsi @@ -38,14 +38,12 @@ compatible = "gpio-leds"; status_green: led-0 { - label = "green:status"; gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; color = ; function = LED_FUNCTION_STATUS; }; status_amber: led-1 { - label = "amber:status"; gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; color = ; function = LED_FUNCTION_STATUS; diff --git a/target/linux/ramips/dts/mt7621_arcadyan_wg4xx223.dtsi b/target/linux/ramips/dts/mt7621_arcadyan_wg4xx223.dtsi index 7b3f316a8c..93570823b3 100644 --- a/target/linux/ramips/dts/mt7621_arcadyan_wg4xx223.dtsi +++ b/target/linux/ramips/dts/mt7621_arcadyan_wg4xx223.dtsi @@ -17,15 +17,13 @@ leds { compatible = "gpio-leds"; - led_status_green: led-1 { - label = "green:status"; + led_status_green: led-0 { color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 15 GPIO_ACTIVE_LOW>; }; - led_status_red: led-2 { - label = "red:status"; + led_status_red: led-1 { color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 16 GPIO_ACTIVE_LOW>; @@ -35,7 +33,7 @@ keys { compatible = "gpio-keys"; - reset { + button-0 { label = "reset"; gpios = <&gpio 3 GPIO_ACTIVE_LOW>; linux,code = ; diff --git a/target/linux/ramips/dts/mt7621_beeline_smartbox-flash.dts b/target/linux/ramips/dts/mt7621_beeline_smartbox-flash.dts index d373a801d2..36f2532161 100644 --- a/target/linux/ramips/dts/mt7621_beeline_smartbox-flash.dts +++ b/target/linux/ramips/dts/mt7621_beeline_smartbox-flash.dts @@ -7,8 +7,7 @@ model = "Beeline SmartBox Flash"; leds { - led-0 { - label = "blue:wan"; + led-2 { color = ; function = LED_FUNCTION_WAN; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; diff --git a/target/linux/ramips/dts/mt7621_beeline_smartbox-giga.dts b/target/linux/ramips/dts/mt7621_beeline_smartbox-giga.dts index f2a99a63a8..c1bf5c899b 100644 --- a/target/linux/ramips/dts/mt7621_beeline_smartbox-giga.dts +++ b/target/linux/ramips/dts/mt7621_beeline_smartbox-giga.dts @@ -23,21 +23,18 @@ compatible = "gpio-leds"; led_status_green: led-0 { - label = "green:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; }; led-1 { - label = "blue:wan"; color = ; function = LED_FUNCTION_WAN; gpios = <&gpio 14 GPIO_ACTIVE_HIGH>; }; led_status_red: led-2 { - label = "red:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; @@ -47,7 +44,7 @@ keys { compatible = "gpio-keys"; - reset { + button-0 { label = "reset"; gpios = <&gpio 4 GPIO_ACTIVE_LOW>; linux,code = ; diff --git a/target/linux/ramips/dts/mt7621_beeline_smartbox-pro.dts b/target/linux/ramips/dts/mt7621_beeline_smartbox-pro.dts index e2c0165e6b..912b191049 100644 --- a/target/linux/ramips/dts/mt7621_beeline_smartbox-pro.dts +++ b/target/linux/ramips/dts/mt7621_beeline_smartbox-pro.dts @@ -11,7 +11,7 @@ }; keys { - switch_bt { + switch-0 { label = "ROUT<->REP Switch_bt"; gpios = <&gpio 6 GPIO_ACTIVE_LOW>; linux,input-type = ; @@ -39,7 +39,6 @@ }; &led_wps { - label = "blue:wps"; color = ; }; diff --git a/target/linux/ramips/dts/mt7621_beeline_smartbox-turbo-plus.dts b/target/linux/ramips/dts/mt7621_beeline_smartbox-turbo-plus.dts index 00f4957c57..4af425a648 100644 --- a/target/linux/ramips/dts/mt7621_beeline_smartbox-turbo-plus.dts +++ b/target/linux/ramips/dts/mt7621_beeline_smartbox-turbo-plus.dts @@ -23,21 +23,18 @@ compatible = "gpio-leds"; led-0 { - label = "blue:wan"; color = ; function = LED_FUNCTION_WAN; gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; }; led_status_green: led-1 { - label = "green:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; led_status_red: led-2 { - label = "red:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; @@ -47,13 +44,13 @@ keys { compatible = "gpio-keys"; - wps { + button-0 { label = "wps"; gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; linux,code = ; }; - reset { + button-1 { label = "reset"; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; diff --git a/target/linux/ramips/dts/mt7621_etisalat_s3.dts b/target/linux/ramips/dts/mt7621_etisalat_s3.dts index 64e21bb704..2581e05a90 100644 --- a/target/linux/ramips/dts/mt7621_etisalat_s3.dts +++ b/target/linux/ramips/dts/mt7621_etisalat_s3.dts @@ -23,21 +23,18 @@ compatible = "gpio-leds"; led-0 { - label = "blue:wan"; color = ; function = LED_FUNCTION_WAN; gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; }; led_status_green: led-1 { - label = "green:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; led_status_red: led-2 { - label = "red:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; @@ -47,13 +44,13 @@ keys { compatible = "gpio-keys"; - wps { + button-0 { label = "wps"; gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; linux,code = ; }; - reset { + button-1 { label = "reset"; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; diff --git a/target/linux/ramips/dts/mt7621_sercomm_dxx_nand_256m.dtsi b/target/linux/ramips/dts/mt7621_sercomm_dxx_nand_256m.dtsi index 36d576108d..0416a5f980 100644 --- a/target/linux/ramips/dts/mt7621_sercomm_dxx_nand_256m.dtsi +++ b/target/linux/ramips/dts/mt7621_sercomm_dxx_nand_256m.dtsi @@ -19,22 +19,19 @@ leds { compatible = "gpio-leds"; - led-1 { - label = "blue:wan"; + led-0 { color = ; function = LED_FUNCTION_WAN; gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; }; - led_status_green: led-0 { - label = "green:status"; + led_status_green: led-1 { color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; led_status_red: led-2 { - label = "red:status"; color = ; function = LED_FUNCTION_STATUS; gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; @@ -44,13 +41,13 @@ keys { compatible = "gpio-keys"; - wps { + button-0 { label = "wps"; gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; linux,code = ; }; - reset { + button-1 { label = "reset"; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; diff --git a/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi b/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi index 09862b8067..8b2bb6b949 100644 --- a/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi +++ b/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi @@ -17,13 +17,13 @@ keys { compatible = "gpio-keys"; - reset { + button-0 { label = "reset"; gpios = <&gpio 7 GPIO_ACTIVE_LOW>; linux,code = ; }; - wps { + button-1 { label = "wps"; gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; @@ -34,33 +34,29 @@ compatible = "gpio-leds"; led-0 { - label = "amber:lan4"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <0>; + function-enumerator = <4>; linux,default-trigger = "mt7530-0:00:1Gbps"; gpios = <&gpio 3 GPIO_ACTIVE_LOW>; }; led-1 { - label = "green:lan4"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <1>; + function-enumerator = <4>; gpios = <&gpio 4 GPIO_ACTIVE_LOW>; }; led-2 { - label = "amber:lan3"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <2>; + function-enumerator = <3>; linux,default-trigger = "mt7530-0:01:1Gbps"; gpios = <&gpio 10 GPIO_ACTIVE_LOW>; }; led-3 { - label = "green:lan3"; color = ; function = LED_FUNCTION_LAN; function-enumerator = <3>; @@ -68,85 +64,72 @@ }; led-4 { - label = "amber:lan2"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <4>; + function-enumerator = <2>; linux,default-trigger = "mt7530-0:02:1Gbps"; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; led-5 { - label = "amber:lan1"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <5>; + function-enumerator = <1>; linux,default-trigger = "mt7530-0:03:1Gbps"; gpios = <&gpio 22 GPIO_ACTIVE_LOW>; }; led-6 { - label = "green:lan1"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <6>; + function-enumerator = <1>; gpios = <&gpio 23 GPIO_ACTIVE_LOW>; }; led-7 { - label = "amber:wan"; color = ; function = LED_FUNCTION_WAN; - function-enumerator = <0>; linux,default-trigger = "mt7530-0:04:1Gbps"; gpios = <&gpio 24 GPIO_ACTIVE_LOW>; }; led-8 { - label = "green:wan"; color = ; function = LED_FUNCTION_WAN; - function-enumerator = <1>; gpios = <&gpio 25 GPIO_ACTIVE_LOW>; }; led-9 { - label = "green:lan2"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <7>; + function-enumerator = <2>; gpios = <&gpio 26 GPIO_ACTIVE_LOW>; }; led-10 { - label = "white:wlan2g"; color = ; function = LED_FUNCTION_WLAN; - function-enumerator = <0>; + function-enumerator = <24>; linux,default-trigger = "phy1radio"; gpios = <&gpio 28 GPIO_ACTIVE_LOW>; }; led_wps: led-11 { function = LED_FUNCTION_WPS; - function-enumerator = <0>; gpios = <&gpio 29 GPIO_ACTIVE_LOW>; panic-indicator; }; led_status: led-12 { - label = "white:status"; color = ; function = LED_FUNCTION_STATUS; - function-enumerator = <0>; gpios = <&gpio 30 GPIO_ACTIVE_LOW>; }; led-13 { - label = "white:wlan5g"; color = ; function = LED_FUNCTION_WLAN; - function-enumerator = <1>; + function-enumerator = <50>; linux,default-trigger = "phy0radio"; gpios = <&gpio 32 GPIO_ACTIVE_LOW>; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_ec330-g5u-v1.dts b/target/linux/ramips/dts/mt7621_tplink_ec330-g5u-v1.dts index 84b3efe8df..a1b458edd5 100644 --- a/target/linux/ramips/dts/mt7621_tplink_ec330-g5u-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_ec330-g5u-v1.dts @@ -29,67 +29,54 @@ led-0 { color = ; function = LED_FUNCTION_USB; - function-enumerator = <0>; gpios = <&gpio 0 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>; linux,default-trigger = "usbport"; }; led-1 { - label = "blue:wps"; color = ; function = LED_FUNCTION_WPS; - function-enumerator = <0>; gpios = <&gpio 5 GPIO_ACTIVE_LOW>; }; led-2 { - label = "blue:ethernet"; color = ; function = LED_FUNCTION_LAN; - function-enumerator = <0>; gpios = <&gpio 9 GPIO_ACTIVE_LOW>; }; led-3 { - label = "amber:internet"; color = ; function = LED_FUNCTION_WAN; - function-enumerator = <0>; gpios = <&gpio 13 GPIO_ACTIVE_LOW>; }; led-4 { - label = "blue:internet"; color = ; function = LED_FUNCTION_WAN; - function-enumerator = <1>; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; led-5 { - label = "blue:wireless_5g"; color = ; function = LED_FUNCTION_WLAN; - function-enumerator = <0>; + function-enumerator = <50>; gpios = <&gpio 15 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy1tpt"; }; led-6 { - label = "blue:wireless_2g"; color = ; function = LED_FUNCTION_WLAN; - function-enumerator = <1>; + function-enumerator = <24>; gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy0tpt"; }; led_power: led-7 { - label = "blue:power"; color = ; - function = LED_FUNCTION_STATUS; - function-enumerator = <0>; + function = LED_FUNCTION_POWER; gpios = <&gpio 18 GPIO_ACTIVE_LOW>; }; }; @@ -97,28 +84,28 @@ keys { compatible = "gpio-keys"; - led { + button-0 { label = "led"; gpios = <&gpio 4 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; - wifi { + button-1 { label = "wifi on/off"; gpios = <&gpio 7 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; - reset { + button-2 { label = "reset"; gpios = <&gpio 8 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; - wps { + button-3 { label = "wps"; gpios = <&gpio 10 GPIO_ACTIVE_LOW>; debounce-interval = <60>; diff --git a/target/linux/ramips/dts/mt7621_wifire_s1500-nbn.dts b/target/linux/ramips/dts/mt7621_wifire_s1500-nbn.dts index 4ffe988153..a3cc6038c0 100644 --- a/target/linux/ramips/dts/mt7621_wifire_s1500-nbn.dts +++ b/target/linux/ramips/dts/mt7621_wifire_s1500-nbn.dts @@ -28,7 +28,6 @@ }; &led_wps { - label = "white:wps"; color = ; }; diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds index 51afb9cf41..1061de6f44 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds @@ -48,10 +48,10 @@ rostelecom,rt-sf-1) ;; beeline,smartbox-pro|\ wifire,s1500-nbn) - ucidef_set_led_netdev "lan1" "lan1" "green:lan1" "lan1" "link tx rx" - ucidef_set_led_netdev "lan2" "lan2" "green:lan2" "lan2" "link tx rx" - ucidef_set_led_netdev "lan3" "lan3" "green:lan3" "lan3" "link tx rx" - ucidef_set_led_netdev "lan4" "lan4" "green:lan4" "lan4" "link tx rx" + ucidef_set_led_netdev "lan1" "lan1" "green:lan-1" "lan1" "link tx rx" + ucidef_set_led_netdev "lan2" "lan2" "green:lan-2" "lan2" "link tx rx" + ucidef_set_led_netdev "lan3" "lan3" "green:lan-3" "lan3" "link tx rx" + ucidef_set_led_netdev "lan4" "lan4" "green:lan-4" "lan4" "link tx rx" ucidef_set_led_netdev "wan" "wan" "green:wan" "wan" "link tx rx" ;; belkin,rt1800) @@ -202,9 +202,9 @@ tplink,deco-m4r-v4) ucidef_set_led_netdev "lan" "LAN" "green:lan" "br-lan" ;; tplink,ec330-g5u-v1) - ucidef_set_led_netdev "lan" "Ethernet" "blue:ethernet" "br-lan" "link tx rx" - ucidef_set_led_netdev "wan" "Internet" "blue:internet" "wan" "link tx rx" - ucidef_set_led_netdev "wan-off" "Internet-off" "amber:internet" "wan" "link" + ucidef_set_led_netdev "lan" "Ethernet" "blue:lan" "br-lan" "link tx rx" + ucidef_set_led_netdev "wan" "Internet" "blue:wan" "wan" "link tx rx" + ucidef_set_led_netdev "wan-off" "Internet-off" "amber:wan" "wan" "link" ;; tplink,re350-v1) ucidef_set_led_netdev "wifi2g" "Wifi 2.4G" "blue:wifi2G" "wlan0" From 5457996a9ea93ea1761fe29fb5809911927a508e Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sun, 3 Dec 2023 12:42:47 +0000 Subject: [PATCH 061/222] ramips: sercomm s1500: enable wlan LEDs activity blinking This commit enables wireless LEDs activity blinking for Sercomm S1500 devices (Beeline Smartbox PRO, WiFire s1500.nbn). Run-tested: WiFire s1500.nbn Signed-off-by: Mikhail Zhilkin --- target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi b/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi index 8b2bb6b949..d03e0da548 100644 --- a/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi +++ b/target/linux/ramips/dts/mt7621_sercomm_s1500.dtsi @@ -110,7 +110,7 @@ color = ; function = LED_FUNCTION_WLAN; function-enumerator = <24>; - linux,default-trigger = "phy1radio"; + linux,default-trigger = "phy1tpt"; gpios = <&gpio 28 GPIO_ACTIVE_LOW>; }; @@ -130,7 +130,7 @@ color = ; function = LED_FUNCTION_WLAN; function-enumerator = <50>; - linux,default-trigger = "phy0radio"; + linux,default-trigger = "phy0tpt"; gpios = <&gpio 32 GPIO_ACTIVE_LOW>; }; }; From 96580500d2806136a98cf38657e7c6082dab7e1c Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sun, 3 Dec 2023 15:05:40 +0000 Subject: [PATCH 062/222] ramips: add alternative name to Etisalat (Sercomm) S3 This commit adds alternative name to Etisalat (Sercomm) S3 router. Signed-off-by: Mikhail Zhilkin --- target/linux/ramips/image/mt7621.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 2c25b1ab28..ab1b829ba0 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -1093,6 +1093,8 @@ define Device/etisalat_s3 SERCOMM_SWVER := 4009 DEVICE_VENDOR := Etisalat DEVICE_MODEL := S3 + DEVICE_ALT0_VENDOR := Sercomm + DEVICE_ALT0_MODEL := S3 DEVICE_PACKAGES := kmod-mt7603 kmod-mt7615-firmware kmod-usb3 endef TARGET_DEVICES += etisalat_s3 From 066b0fee76684a9fca44635d63bf2c699ef8e89c Mon Sep 17 00:00:00 2001 From: Chuanhong Guo Date: Sun, 7 Jan 2024 23:56:05 +0800 Subject: [PATCH 063/222] kernel: copy only *.ko for debug info Previous commits installed non-elf files into /lib/modules/$VER/. COLLECT_KERNEL_DEBUG tries to strip all files and these two files break the build. Fix it by copying only kernel modules for debug info collection. Fixes: e1d8e57614 ("kernel: include modinfo for built-in modules") Fixes: 29f6da4340 ("kernel: include built-in module list") Signed-off-by: Chuanhong Guo --- include/kernel-build.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/kernel-build.mk b/include/kernel-build.mk index 5b332258f8..b9513ec414 100644 --- a/include/kernel-build.mk +++ b/include/kernel-build.mk @@ -63,7 +63,7 @@ ifdef CONFIG_COLLECT_KERNEL_DEBUG mkdir -p $(KERNEL_BUILD_DIR)/debug/modules $(CP) $(LINUX_DIR)/vmlinux $(KERNEL_BUILD_DIR)/debug/ -$(CP) \ - $(STAGING_DIR_ROOT)/lib/modules/$(LINUX_VERSION)/* \ + $(STAGING_DIR_ROOT)/lib/modules/$(LINUX_VERSION)/*.ko \ $(KERNEL_BUILD_DIR)/debug/modules/ $(FIND) $(KERNEL_BUILD_DIR)/debug -type f | $(XARGS) $(KERNEL_CROSS)strip --only-keep-debug $(TAR) c -C $(KERNEL_BUILD_DIR) debug \ From 1278d47beaabaa963b2956e81936269b7fea4003 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Thu, 30 Nov 2023 07:32:52 +0100 Subject: [PATCH 064/222] mac80211: avoid crashing on invalid band info Frequent crashes have been observed on MT7916 based platforms. While the root of these crashes are currently unknown, they happen when decoding rate information of connected STAs in AP mode. The rate-information is associated with a band which is not available on the PHY. Check for this condition in order to avoid crashing the whole system. This patch should be removed once the roout cause has been found and fixed. Link: https://github.com/freifunk-gluon/gluon/issues/2980 Signed-off-by: David Bauer --- .../780-avoid-crashing-missing-band.patch | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch diff --git a/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch b/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch new file mode 100644 index 0000000000..2bc11efd00 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch @@ -0,0 +1,34 @@ +From: David Bauer +Date: Thu, 30 Nov 2023 07:32:52 +0100 +Subject: [PATCH] mac80211: avoid crashing on invalid band info + +Frequent crashes have been observed on MT7916 based platforms. While the +root of these crashes are currently unknown, they happen when decoding +rate information of connected STAs in AP mode. The rate-information is +associated with a band which is not available on the PHY. + +Check for this condition in order to avoid crashing the whole system. +This patch should be removed once the roout cause has been found and +fixed. + +Link: https://github.com/freifunk-gluon/gluon/issues/2980 + +Signed-off-by: David Bauer +--- + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -2422,6 +2422,13 @@ static void sta_stats_decode_rate(struct + + sband = local->hw.wiphy->bands[band]; + ++ if (!sband) { ++ wiphy_warn(local->hw.wiphy, ++ "Invalid band %d\n", ++ band); ++ break; ++ } ++ + if (WARN_ON_ONCE(!sband->bitrates)) + break; + From c9e58f85f6e5d96711291f079413d2f34c36fdc3 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Fri, 5 Jan 2024 17:02:01 +0100 Subject: [PATCH 065/222] ath79: move UniFi AC template into common This allows us to embrace alphabetical sorting for the UK-Ultra. Signed-off-by: David Bauer --- target/linux/ath79/image/common-ubnt.mk | 7 +++++++ target/linux/ath79/image/generic-ubnt.mk | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/target/linux/ath79/image/common-ubnt.mk b/target/linux/ath79/image/common-ubnt.mk index 76d6de000b..f44e06e110 100644 --- a/target/linux/ath79/image/common-ubnt.mk +++ b/target/linux/ath79/image/common-ubnt.mk @@ -121,6 +121,13 @@ define Device/ubnt-xw UBNT_VERSION := 6.0.4 endef +define Device/ubnt_unifiac + DEVICE_VENDOR := Ubiquiti + SOC := qca9563 + IMAGE_SIZE := 15488k + DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct +endef + define Device/ubnt-unifi-jffs2 $(Device/ubnt) KERNEL_SIZE := 3072k diff --git a/target/linux/ath79/image/generic-ubnt.mk b/target/linux/ath79/image/generic-ubnt.mk index fa4daa3aaa..92b764c389 100644 --- a/target/linux/ath79/image/generic-ubnt.mk +++ b/target/linux/ath79/image/generic-ubnt.mk @@ -244,13 +244,6 @@ define Device/ubnt_unifi-ap-lr endef TARGET_DEVICES += ubnt_unifi-ap-lr -define Device/ubnt_unifiac - DEVICE_VENDOR := Ubiquiti - SOC := qca9563 - IMAGE_SIZE := 15488k - DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct -endef - define Device/ubnt_unifiac-lite $(Device/ubnt_unifiac) DEVICE_MODEL := UniFi AC Lite From bf94e0a38389b2ce5d33be9c97d104d36dd5ebd6 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Fri, 5 Jan 2024 17:18:09 +0100 Subject: [PATCH 066/222] ath79: add support for UniFi UK-Ultra Hardware -------- CPU: Qualcomm Atheros QCA9563 RAM: 128M DDR2 FLASH: 16MB SPI-NOR WiFi: Qualcomm Atheros QCA9563 2x2:2 802.11n 2.4GHz Qualcomm Atheros QCA9880 2x2:2 802.11ac 5GHz Antennas -------- The device features internal antennas as well as external antenna connectors. By default, the internal antennas are used. Two GPIOs are exported by name, which can be used to control the antenna-path mux. Writing a logical 0 enables the external antenna connectors. Installation ------------ 1. Download the OpenWrt sysupgrade image to the device. You can use scp for this task. The default username and password are "ubnt" and the device is reachable at 192.168.1.20. $ scp -O openwrt-sysupgrade.bin ubnt@192.168.1.20:/tmp/firmware.bin 2. Connect to the device using SSH. $ ssh ubnt@192.168.1.20 3. Disable the write-protect $ echo "5edfacbf" > /proc/ubnthal/.uf 4. Verify kernel0 and kernel1 match mtd2 and mtd3 $ cat /proc/mtd 5. Write the sysupgrade image to kernel0 and kernel1 $ dd if=/tmp/firmware.bin of=/dev/mtdblock2 $ dd if=/tmp/firmware.bin of=/dev/mtdblock3 6. Write the bootselect flag to boot from kernel0 $ dd if=/dev/zero bs=1 count=1 of=/dev/mtd4 7. Reboot the device $ reboot Signed-off-by: David Bauer --- .../linux/ath79/dts/qca9563_ubnt_uk-ultra.dts | 35 +++++++++++++++++++ .../linux/ath79/dts/qca9563_ubnt_unifiac.dtsi | 2 +- .../generic/base-files/etc/board.d/01_leds | 7 ++++ .../generic/base-files/etc/board.d/02_network | 1 + .../base-files/etc/board.d/03_gpio_switches | 4 +++ .../etc/hotplug.d/firmware/11-ath10k-caldata | 1 + target/linux/ath79/image/generic-ubnt.mk | 7 ++++ 7 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 target/linux/ath79/dts/qca9563_ubnt_uk-ultra.dts diff --git a/target/linux/ath79/dts/qca9563_ubnt_uk-ultra.dts b/target/linux/ath79/dts/qca9563_ubnt_uk-ultra.dts new file mode 100644 index 0000000000..1ba635117e --- /dev/null +++ b/target/linux/ath79/dts/qca9563_ubnt_uk-ultra.dts @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qca9563_ubnt_unifiac-lite.dtsi" + +/ { + compatible = "ubnt,uk-ultra", "qca,qca9563"; + model = "Ubiquiti UniFi Swiss Army Knife Ultra"; +}; + +&leds { + led-rssi0 { + label = "white:rssi0"; + gpios = <&gpio 21 GPIO_ACTIVE_HIGH>; + }; + + led-rssi1 { + label = "white:rssi1"; + gpios = <&gpio 20 GPIO_ACTIVE_HIGH>; + }; + + led-rssi2 { + label = "white:rssi2"; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; + }; + + led-rssi3 { + label = "white:rssi3"; + gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; + }; +}; + +/** + * Antenna selection on GPIO5 and GPIO6 + * High = Internal ; Low = External + */ diff --git a/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi b/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi index da01251f3b..60d6fbc895 100644 --- a/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi +++ b/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi @@ -13,7 +13,7 @@ led-upgrade = &led_blue; }; - leds { + leds: leds { compatible = "gpio-leds"; led_white: led_white { diff --git a/target/linux/ath79/generic/base-files/etc/board.d/01_leds b/target/linux/ath79/generic/base-files/etc/board.d/01_leds index 615abe4b3b..ae6e3c4d30 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/01_leds +++ b/target/linux/ath79/generic/base-files/etc/board.d/01_leds @@ -516,6 +516,13 @@ ubnt,rocket-m) ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "green:link3" "wlan0" "51" "100" ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "green:link4" "wlan0" "76" "100" ;; +ubnt,uk-ultra) + ucidef_set_rssimon "wlan0" "200000" "1" + ucidef_set_led_rssi "rssilow" "RSSILOW" "white:rssi0" "wlan0" "1" "100" + ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "white:rssi1" "wlan0" "26" "100" + ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "white:rssi2" "wlan0" "51" "100" + ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "white:rssi3" "wlan0" "76" "100" + ;; wallys,dr531) ucidef_set_led_netdev "lan" "LAN" "green:lan" "eth0" ucidef_set_led_switch "wan" "WAN" "green:wan" "switch0" "0x2" diff --git a/target/linux/ath79/generic/base-files/etc/board.d/02_network b/target/linux/ath79/generic/base-files/etc/board.d/02_network index b74a7ff6b4..70bfd95f9e 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/02_network +++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network @@ -116,6 +116,7 @@ ath79_setup_interfaces() ubnt,powerbridge-m|\ ubnt,rocket-5ac-lite|\ ubnt,rocket-m|\ + ubnt,uk-ultra|\ ubnt,unifiac-lite|\ ubnt,unifiac-lr|\ ubnt,unifiac-mesh|\ diff --git a/target/linux/ath79/generic/base-files/etc/board.d/03_gpio_switches b/target/linux/ath79/generic/base-files/etc/board.d/03_gpio_switches index 899a8ba97e..279f518409 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/03_gpio_switches +++ b/target/linux/ath79/generic/base-files/etc/board.d/03_gpio_switches @@ -92,6 +92,10 @@ ubnt,nanostation-m) ubnt,nanostation-m-xw) ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "2" ;; +ubnt,uk-ultra) + ucidef_add_gpio_switch "ant0_internal" "ANT0 Internal" "5" "1" + ucidef_add_gpio_switch "ant1_internal" "ANT1 Internal" "6" "1" + ;; zbtlink,zbt-wd323) ucidef_add_gpio_switch "io0" "IO#0" "0" ucidef_add_gpio_switch "io1" "IO#1" "1" diff --git a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata index dd627ad2d6..1acbf35947 100644 --- a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +++ b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -37,6 +37,7 @@ case "$FIRMWARE" in sophos,ap100|\ sophos,ap100c|\ ubnt,bullet-ac|\ + ubnt,uk-ultra|\ ubnt,unifiac-lite|\ ubnt,unifiac-lr|\ ubnt,unifiac-mesh|\ diff --git a/target/linux/ath79/image/generic-ubnt.mk b/target/linux/ath79/image/generic-ubnt.mk index 92b764c389..68cef7d14b 100644 --- a/target/linux/ath79/image/generic-ubnt.mk +++ b/target/linux/ath79/image/generic-ubnt.mk @@ -229,6 +229,13 @@ define Device/ubnt_routerstation-pro endef TARGET_DEVICES += ubnt_routerstation-pro +define Device/ubnt_uk-ultra + $(Device/ubnt_unifiac) + DEVICE_MODEL := UniFi Swiss Army Knife Ultra + DEVICE_PACKAGES += rssileds -swconfig +endef +TARGET_DEVICES += ubnt_uk-ultra + define Device/ubnt_unifi-ap $(Device/ubnt-bz) DEVICE_MODEL := UniFi AP From 934873f4514b490307d2ba23cc48f5a056e75f66 Mon Sep 17 00:00:00 2001 From: Manuel Fombuena Date: Sun, 7 Jan 2024 01:04:36 +0000 Subject: [PATCH 067/222] ipq-wifi: bump version to 2024-01-06-71f45cff 673662f ipq8074: add Wallys DR8072V01 BDF 7e8b237 ipq40xx: add ZyXEL WSQ50 QCA4019 BDF 831c1bd ipq40xx: add ZyXEL WSQ50 QCA9984 BDF f9ff251 ipq40xx: add ASUS MAP-AC2200 QCA9888 BDF 71f45cf ipq8074: Update MX4200 BDF Signed-off-by: Manuel Fombuena Reviewed-by: Robert Marko --- package/firmware/ipq-wifi/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile index 189b8e9ec9..7b71c63d6f 100644 --- a/package/firmware/ipq-wifi/Makefile +++ b/package/firmware/ipq-wifi/Makefile @@ -6,9 +6,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git -PKG_SOURCE_DATE:=2023-11-10 -PKG_SOURCE_VERSION:=0c2e810e71ed0a59fb00246c7fa2c236ff67a0ee -PKG_MIRROR_HASH:=fc6016540bd2c67484952d0e4432d740f0e022d9b688e851bb6321def8d36844 +PKG_SOURCE_DATE:=2024-01-06 +PKG_SOURCE_VERSION:=71f45cff8944405b7cc2bf5c19df2bd8fe7f2421 +PKG_MIRROR_HASH:=799602d1519605bab3a952bc07d1a055617ab295e338121bf0e6cae2ebbb0dc9 PKG_FLAGS:=nonshared From 04ed95d1f92058ec26826791e309ec3ae09ee625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 5 Jan 2024 11:31:26 +0100 Subject: [PATCH 068/222] kernel: backport more NVMEM changes queued for v6.8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki --- ...factor-.add_cells-callback-arguments.patch | 94 +++++++++++++ ...mem-drop-nvmem_layout_get_match_data.patch | 72 ++++++++++ ...nvmem-core-add-nvmem_dev_size-helper.patch | 53 ++++++++ ...-use-nvmem_add_one_cell-nvmem-subsys.patch | 126 ++++++++++++++++++ ...-u-boot-env-use-nvmem-device-helpers.patch | 81 +++++++++++ ...vmem-u-boot-env-improve-coding-style.patch | 62 +++++++++ ...factor-.add_cells-callback-arguments.patch | 94 +++++++++++++ ...mem-drop-nvmem_layout_get_match_data.patch | 72 ++++++++++ ...nvmem-core-add-nvmem_dev_size-helper.patch | 53 ++++++++ ...-use-nvmem_add_one_cell-nvmem-subsys.patch | 126 ++++++++++++++++++ ...-u-boot-env-use-nvmem-device-helpers.patch | 81 +++++++++++ ...vmem-u-boot-env-improve-coding-style.patch | 62 +++++++++ ...env-align-endianness-of-crc32-values.patch | 6 +- ...env-align-endianness-of-crc32-values.patch | 6 +- 14 files changed, 982 insertions(+), 6 deletions(-) create mode 100644 target/linux/generic/backport-5.15/834-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch create mode 100644 target/linux/generic/backport-5.15/834-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch create mode 100644 target/linux/generic/backport-5.15/834-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch create mode 100644 target/linux/generic/backport-5.15/834-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch create mode 100644 target/linux/generic/backport-5.15/834-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch create mode 100644 target/linux/generic/backport-5.15/834-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch create mode 100644 target/linux/generic/backport-6.1/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch create mode 100644 target/linux/generic/backport-6.1/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch create mode 100644 target/linux/generic/backport-6.1/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch create mode 100644 target/linux/generic/backport-6.1/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch create mode 100644 target/linux/generic/backport-6.1/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch create mode 100644 target/linux/generic/backport-6.1/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch diff --git a/target/linux/generic/backport-5.15/834-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch b/target/linux/generic/backport-5.15/834-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch new file mode 100644 index 0000000000..1bf3ba35b6 --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch @@ -0,0 +1,94 @@ +From 401df0d4f4098ecc9c5278da2f50756d62e5b37d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:03 +0100 +Subject: [PATCH] nvmem: layouts: refactor .add_cells() callback arguments +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simply pass whole "struct nvmem_layout" instead of single variables. +There is nothing in "struct nvmem_layout" that we have to hide from +layout drivers. They also access it during .probe() and .remove(). + +Thanks to this change: + +1. API gets more consistent + All layouts drivers callbacks get the same argument + +2. Layouts get correct device + Before this change NVMEM core code was passing NVMEM device instead + of layout device. That resulted in: + * Confusing prints + * Calling devm_*() helpers on wrong device + * Helpers like of_device_get_match_data() dereferencing NULLs + +3. It gets possible to get match data + First of all nvmem_layout_get_match_data() requires passing "struct + nvmem_layout" which .add_cells() callback didn't have before this. It + doesn't matter much as it's rather useless now anyway (and will be + dropped). + What's more important however is that of_device_get_match_data() can + be used now thanks to owning a proper device pointer. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-1-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 2 +- + drivers/nvmem/layouts/onie-tlv.c | 4 +++- + drivers/nvmem/layouts/sl28vpd.c | 4 +++- + include/linux/nvmem-provider.h | 2 +- + 4 files changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -855,7 +855,7 @@ int nvmem_layout_register(struct nvmem_l + return -EINVAL; + + /* Populate the cells */ +- ret = layout->add_cells(&layout->nvmem->dev, layout->nvmem); ++ ret = layout->add_cells(layout); + if (ret) + return ret; + +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -182,8 +182,10 @@ static bool onie_tlv_crc_is_valid(struct + return true; + } + +-static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem) ++static int onie_tlv_parse_table(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + struct onie_tlv_hdr hdr; + size_t table_len, data_len, hdr_len; + u8 *table, *data; +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -80,8 +80,10 @@ static int sl28vpd_v1_check_crc(struct d + return 0; + } + +-static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem) ++static int sl28vpd_add_cells(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + const struct nvmem_cell_info *pinfo; + struct nvmem_cell_info info = {0}; + struct device_node *layout_np; +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -173,7 +173,7 @@ struct nvmem_cell_table { + struct nvmem_layout { + struct device dev; + struct nvmem_device *nvmem; +- int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); ++ int (*add_cells)(struct nvmem_layout *layout); + }; + + struct nvmem_layout_driver { diff --git a/target/linux/generic/backport-5.15/834-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch b/target/linux/generic/backport-5.15/834-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch new file mode 100644 index 0000000000..514b5f2de5 --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch @@ -0,0 +1,72 @@ +From 43f60e3fb62edc7bd8891de8779fb422f4ae23ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:04 +0100 +Subject: [PATCH] nvmem: drop nvmem_layout_get_match_data() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Thanks for layouts refactoring we now have "struct device" associated +with layout. Also its OF pointer points directly to the "nvmem-layout" +DT node. + +All it takes to get match data is a generic of_device_get_match_data(). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 ------------- + include/linux/nvmem-provider.h | 10 ---------- + 2 files changed, 23 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -877,19 +877,6 @@ void nvmem_layout_unregister(struct nvme + } + EXPORT_SYMBOL_GPL(nvmem_layout_unregister); + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- struct device_node __maybe_unused *layout_np; +- const struct of_device_id *match; +- +- layout_np = of_nvmem_layout_get_container(nvmem); +- match = of_match_node(layout->dev.driver->of_match_table, layout_np); +- +- return match ? match->data : NULL; +-} +-EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data); +- + /** + * nvmem_register() - Register a nvmem device for given nvmem_config. + * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -205,9 +205,6 @@ void nvmem_layout_driver_unregister(stru + module_driver(__nvmem_layout_driver, nvmem_layout_driver_register, \ + nvmem_layout_driver_unregister) + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout); +- + #else + + static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) +@@ -238,13 +235,6 @@ static inline int nvmem_layout_register( + + static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {} + +-static inline const void * +-nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- return NULL; +-} +- + #endif /* CONFIG_NVMEM */ + + #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) diff --git a/target/linux/generic/backport-5.15/834-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch b/target/linux/generic/backport-5.15/834-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch new file mode 100644 index 0000000000..aa0bbaa0c5 --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch @@ -0,0 +1,53 @@ +From 33cf42e68efc8ff529a7eee08a4f0ba8c8d0a207 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:17 +0100 +Subject: [PATCH] nvmem: core: add nvmem_dev_size() helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is required by layouts that need to read whole NVMEM content. It's +especially useful for NVMEM devices without hardcoded layout (like +U-Boot environment data block). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 +++++++++++++ + include/linux/nvmem-consumer.h | 1 + + 2 files changed, 14 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -2164,6 +2164,19 @@ const char *nvmem_dev_name(struct nvmem_ + } + EXPORT_SYMBOL_GPL(nvmem_dev_name); + ++/** ++ * nvmem_dev_size() - Get the size of a given nvmem device. ++ * ++ * @nvmem: nvmem device. ++ * ++ * Return: size of the nvmem device. ++ */ ++size_t nvmem_dev_size(struct nvmem_device *nvmem) ++{ ++ return nvmem->size; ++} ++EXPORT_SYMBOL_GPL(nvmem_dev_size); ++ + static int __init nvmem_init(void) + { + int ret; +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -81,6 +81,7 @@ int nvmem_device_cell_write(struct nvmem + struct nvmem_cell_info *info, void *buf); + + const char *nvmem_dev_name(struct nvmem_device *nvmem); ++size_t nvmem_dev_size(struct nvmem_device *nvmem); + + void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, + size_t nentries); diff --git a/target/linux/generic/backport-5.15/834-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch b/target/linux/generic/backport-5.15/834-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch new file mode 100644 index 0000000000..fc826f3f7e --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch @@ -0,0 +1,126 @@ +From 7c8979b42b1a9c5604f431ba804928e55919263c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:18 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem_add_one_cell() nvmem subsystem + helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simplify adding NVMEM cells. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-3-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 55 +++++++++++++++----------------------- + 1 file changed, 21 insertions(+), 34 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -23,13 +23,10 @@ enum u_boot_env_format { + + struct u_boot_env { + struct device *dev; ++ struct nvmem_device *nvmem; + enum u_boot_env_format format; + + struct mtd_info *mtd; +- +- /* Cells */ +- struct nvmem_cell_info *cells; +- int ncells; + }; + + struct u_boot_env_image_single { +@@ -94,43 +91,36 @@ static int u_boot_env_read_post_process_ + static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, + size_t data_offset, size_t data_len) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + char *data = buf + data_offset; + char *var, *value, *eq; +- int idx; +- +- priv->ncells = 0; +- for (var = data; var < data + data_len && *var; var += strlen(var) + 1) +- priv->ncells++; +- +- priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); +- if (!priv->cells) +- return -ENOMEM; + +- for (var = data, idx = 0; ++ for (var = data; + var < data + data_len && *var; +- var = value + strlen(value) + 1, idx++) { ++ var = value + strlen(value) + 1) { ++ struct nvmem_cell_info info = {}; ++ + eq = strchr(var, '='); + if (!eq) + break; + *eq = '\0'; + value = eq + 1; + +- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); +- if (!priv->cells[idx].name) ++ info.name = devm_kstrdup(dev, var, GFP_KERNEL); ++ if (!info.name) + return -ENOMEM; +- priv->cells[idx].offset = data_offset + value - data; +- priv->cells[idx].bytes = strlen(value); +- priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); ++ info.offset = data_offset + value - data; ++ info.bytes = strlen(value); ++ info.np = of_get_child_by_name(dev->of_node, info.name); + if (!strcmp(var, "ethaddr")) { +- priv->cells[idx].raw_len = strlen(value); +- priv->cells[idx].bytes = ETH_ALEN; +- priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr; ++ info.raw_len = strlen(value); ++ info.bytes = ETH_ALEN; ++ info.read_post_process = u_boot_env_read_post_process_ethaddr; + } +- } + +- if (WARN_ON(idx != priv->ncells)) +- priv->ncells = idx; ++ nvmem_add_one_cell(nvmem, &info); ++ } + + return 0; + } +@@ -209,7 +199,6 @@ static int u_boot_env_probe(struct platf + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct u_boot_env *priv; +- int err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -224,17 +213,15 @@ static int u_boot_env_probe(struct platf + return PTR_ERR(priv->mtd); + } + +- err = u_boot_env_parse(priv); +- if (err) +- return err; +- + config.dev = dev; +- config.cells = priv->cells; +- config.ncells = priv->ncells; + config.priv = priv; + config.size = priv->mtd->size; + +- return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); ++ priv->nvmem = devm_nvmem_register(dev, &config); ++ if (IS_ERR(priv->nvmem)) ++ return PTR_ERR(priv->nvmem); ++ ++ return u_boot_env_parse(priv); + } + + static const struct of_device_id u_boot_env_of_match_table[] = { diff --git a/target/linux/generic/backport-5.15/834-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch b/target/linux/generic/backport-5.15/834-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch new file mode 100644 index 0000000000..70abc7cf14 --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch @@ -0,0 +1,81 @@ +From a832556d23c5a11115f300011a5874d6107a0d62 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:19 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem device helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use nvmem_dev_size() and nvmem_device_read() to make this driver less +mtd dependent. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-4-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -127,27 +127,34 @@ static int u_boot_env_add_cells(struct u + + static int u_boot_env_parse(struct u_boot_env *priv) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; + size_t data_offset; + size_t data_len; ++ size_t dev_size; + uint32_t crc32; + uint32_t calc; +- size_t bytes; + uint8_t *buf; ++ int bytes; + int err; + +- buf = kcalloc(1, priv->mtd->size, GFP_KERNEL); ++ dev_size = nvmem_dev_size(nvmem); ++ ++ buf = kcalloc(1, dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; + } + +- err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf); +- if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) { +- dev_err(dev, "Failed to read from mtd: %d\n", err); ++ bytes = nvmem_device_read(nvmem, 0, dev_size, buf); ++ if (bytes < 0) { ++ err = bytes; ++ goto err_kfree; ++ } else if (bytes != dev_size) { ++ err = -EIO; + goto err_kfree; + } + +@@ -169,8 +176,8 @@ static int u_boot_env_parse(struct u_boo + break; + } + crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); +- crc32_data_len = priv->mtd->size - crc32_data_offset; +- data_len = priv->mtd->size - data_offset; ++ crc32_data_len = dev_size - crc32_data_offset; ++ data_len = dev_size - data_offset; + + calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + if (calc != crc32) { +@@ -179,7 +186,7 @@ static int u_boot_env_parse(struct u_boo + goto err_kfree; + } + +- buf[priv->mtd->size - 1] = '\0'; ++ buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); + if (err) + dev_err(dev, "Failed to add cells: %d\n", err); diff --git a/target/linux/generic/backport-5.15/834-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch b/target/linux/generic/backport-5.15/834-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch new file mode 100644 index 0000000000..273cfed874 --- /dev/null +++ b/target/linux/generic/backport-5.15/834-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch @@ -0,0 +1,62 @@ +From 6bafe07c930676d6430be471310958070816a595 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:20 +0100 +Subject: [PATCH] nvmem: u-boot-env: improve coding style +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +1. Prefer kzalloc() over kcalloc() + See memory-allocation.rst which says: "to be on the safe side it's + best to use routines that set memory to zero, like kzalloc()" +2. Drop dev_err() for u_boot_env_add_cells() fail + It can fail only on -ENOMEM. We don't want to print error then. +3. Add extra "crc32_addr" variable + It makes code reading header's crc32 easier to understand / review. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-5-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -132,6 +132,7 @@ static int u_boot_env_parse(struct u_boo + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; ++ __le32 *crc32_addr; + size_t data_offset; + size_t data_len; + size_t dev_size; +@@ -143,7 +144,7 @@ static int u_boot_env_parse(struct u_boo + + dev_size = nvmem_dev_size(nvmem); + +- buf = kcalloc(1, dev_size, GFP_KERNEL); ++ buf = kzalloc(dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; +@@ -175,7 +176,8 @@ static int u_boot_env_parse(struct u_boo + data_offset = offsetof(struct u_boot_env_image_broadcom, data); + break; + } +- crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); ++ crc32_addr = (__le32 *)(buf + crc32_offset); ++ crc32 = le32_to_cpu(*crc32_addr); + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; + +@@ -188,8 +190,6 @@ static int u_boot_env_parse(struct u_boo + + buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); +- if (err) +- dev_err(dev, "Failed to add cells: %d\n", err); + + err_kfree: + kfree(buf); diff --git a/target/linux/generic/backport-6.1/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch b/target/linux/generic/backport-6.1/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch new file mode 100644 index 0000000000..1bf3ba35b6 --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0008-nvmem-layouts-refactor-.add_cells-callback-arguments.patch @@ -0,0 +1,94 @@ +From 401df0d4f4098ecc9c5278da2f50756d62e5b37d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:03 +0100 +Subject: [PATCH] nvmem: layouts: refactor .add_cells() callback arguments +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simply pass whole "struct nvmem_layout" instead of single variables. +There is nothing in "struct nvmem_layout" that we have to hide from +layout drivers. They also access it during .probe() and .remove(). + +Thanks to this change: + +1. API gets more consistent + All layouts drivers callbacks get the same argument + +2. Layouts get correct device + Before this change NVMEM core code was passing NVMEM device instead + of layout device. That resulted in: + * Confusing prints + * Calling devm_*() helpers on wrong device + * Helpers like of_device_get_match_data() dereferencing NULLs + +3. It gets possible to get match data + First of all nvmem_layout_get_match_data() requires passing "struct + nvmem_layout" which .add_cells() callback didn't have before this. It + doesn't matter much as it's rather useless now anyway (and will be + dropped). + What's more important however is that of_device_get_match_data() can + be used now thanks to owning a proper device pointer. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-1-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 2 +- + drivers/nvmem/layouts/onie-tlv.c | 4 +++- + drivers/nvmem/layouts/sl28vpd.c | 4 +++- + include/linux/nvmem-provider.h | 2 +- + 4 files changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -855,7 +855,7 @@ int nvmem_layout_register(struct nvmem_l + return -EINVAL; + + /* Populate the cells */ +- ret = layout->add_cells(&layout->nvmem->dev, layout->nvmem); ++ ret = layout->add_cells(layout); + if (ret) + return ret; + +--- a/drivers/nvmem/layouts/onie-tlv.c ++++ b/drivers/nvmem/layouts/onie-tlv.c +@@ -182,8 +182,10 @@ static bool onie_tlv_crc_is_valid(struct + return true; + } + +-static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem) ++static int onie_tlv_parse_table(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + struct onie_tlv_hdr hdr; + size_t table_len, data_len, hdr_len; + u8 *table, *data; +--- a/drivers/nvmem/layouts/sl28vpd.c ++++ b/drivers/nvmem/layouts/sl28vpd.c +@@ -80,8 +80,10 @@ static int sl28vpd_v1_check_crc(struct d + return 0; + } + +-static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem) ++static int sl28vpd_add_cells(struct nvmem_layout *layout) + { ++ struct nvmem_device *nvmem = layout->nvmem; ++ struct device *dev = &layout->dev; + const struct nvmem_cell_info *pinfo; + struct nvmem_cell_info info = {0}; + struct device_node *layout_np; +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -173,7 +173,7 @@ struct nvmem_cell_table { + struct nvmem_layout { + struct device dev; + struct nvmem_device *nvmem; +- int (*add_cells)(struct device *dev, struct nvmem_device *nvmem); ++ int (*add_cells)(struct nvmem_layout *layout); + }; + + struct nvmem_layout_driver { diff --git a/target/linux/generic/backport-6.1/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch b/target/linux/generic/backport-6.1/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch new file mode 100644 index 0000000000..514b5f2de5 --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0009-nvmem-drop-nvmem_layout_get_match_data.patch @@ -0,0 +1,72 @@ +From 43f60e3fb62edc7bd8891de8779fb422f4ae23ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 19 Dec 2023 13:01:04 +0100 +Subject: [PATCH] nvmem: drop nvmem_layout_get_match_data() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Thanks for layouts refactoring we now have "struct device" associated +with layout. Also its OF pointer points directly to the "nvmem-layout" +DT node. + +All it takes to get match data is a generic of_device_get_match_data(). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Reviewed-by: Michael Walle +Link: https://lore.kernel.org/r/20231219120104.3422-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 ------------- + include/linux/nvmem-provider.h | 10 ---------- + 2 files changed, 23 deletions(-) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -877,19 +877,6 @@ void nvmem_layout_unregister(struct nvme + } + EXPORT_SYMBOL_GPL(nvmem_layout_unregister); + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- struct device_node __maybe_unused *layout_np; +- const struct of_device_id *match; +- +- layout_np = of_nvmem_layout_get_container(nvmem); +- match = of_match_node(layout->dev.driver->of_match_table, layout_np); +- +- return match ? match->data : NULL; +-} +-EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data); +- + /** + * nvmem_register() - Register a nvmem device for given nvmem_config. + * Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem +--- a/include/linux/nvmem-provider.h ++++ b/include/linux/nvmem-provider.h +@@ -205,9 +205,6 @@ void nvmem_layout_driver_unregister(stru + module_driver(__nvmem_layout_driver, nvmem_layout_driver_register, \ + nvmem_layout_driver_unregister) + +-const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout); +- + #else + + static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) +@@ -238,13 +235,6 @@ static inline int nvmem_layout_register( + + static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {} + +-static inline const void * +-nvmem_layout_get_match_data(struct nvmem_device *nvmem, +- struct nvmem_layout *layout) +-{ +- return NULL; +-} +- + #endif /* CONFIG_NVMEM */ + + #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) diff --git a/target/linux/generic/backport-6.1/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch b/target/linux/generic/backport-6.1/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch new file mode 100644 index 0000000000..aa0bbaa0c5 --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0010-nvmem-core-add-nvmem_dev_size-helper.patch @@ -0,0 +1,53 @@ +From 33cf42e68efc8ff529a7eee08a4f0ba8c8d0a207 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:17 +0100 +Subject: [PATCH] nvmem: core: add nvmem_dev_size() helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is required by layouts that need to read whole NVMEM content. It's +especially useful for NVMEM devices without hardcoded layout (like +U-Boot environment data block). + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-2-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/core.c | 13 +++++++++++++ + include/linux/nvmem-consumer.h | 1 + + 2 files changed, 14 insertions(+) + +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -2164,6 +2164,19 @@ const char *nvmem_dev_name(struct nvmem_ + } + EXPORT_SYMBOL_GPL(nvmem_dev_name); + ++/** ++ * nvmem_dev_size() - Get the size of a given nvmem device. ++ * ++ * @nvmem: nvmem device. ++ * ++ * Return: size of the nvmem device. ++ */ ++size_t nvmem_dev_size(struct nvmem_device *nvmem) ++{ ++ return nvmem->size; ++} ++EXPORT_SYMBOL_GPL(nvmem_dev_size); ++ + static int __init nvmem_init(void) + { + int ret; +--- a/include/linux/nvmem-consumer.h ++++ b/include/linux/nvmem-consumer.h +@@ -81,6 +81,7 @@ int nvmem_device_cell_write(struct nvmem + struct nvmem_cell_info *info, void *buf); + + const char *nvmem_dev_name(struct nvmem_device *nvmem); ++size_t nvmem_dev_size(struct nvmem_device *nvmem); + + void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, + size_t nentries); diff --git a/target/linux/generic/backport-6.1/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch b/target/linux/generic/backport-6.1/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch new file mode 100644 index 0000000000..fc826f3f7e --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0011-nvmem-u-boot-env-use-nvmem_add_one_cell-nvmem-subsys.patch @@ -0,0 +1,126 @@ +From 7c8979b42b1a9c5604f431ba804928e55919263c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:18 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem_add_one_cell() nvmem subsystem + helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Simplify adding NVMEM cells. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-3-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 55 +++++++++++++++----------------------- + 1 file changed, 21 insertions(+), 34 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -23,13 +23,10 @@ enum u_boot_env_format { + + struct u_boot_env { + struct device *dev; ++ struct nvmem_device *nvmem; + enum u_boot_env_format format; + + struct mtd_info *mtd; +- +- /* Cells */ +- struct nvmem_cell_info *cells; +- int ncells; + }; + + struct u_boot_env_image_single { +@@ -94,43 +91,36 @@ static int u_boot_env_read_post_process_ + static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf, + size_t data_offset, size_t data_len) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + char *data = buf + data_offset; + char *var, *value, *eq; +- int idx; +- +- priv->ncells = 0; +- for (var = data; var < data + data_len && *var; var += strlen(var) + 1) +- priv->ncells++; +- +- priv->cells = devm_kcalloc(dev, priv->ncells, sizeof(*priv->cells), GFP_KERNEL); +- if (!priv->cells) +- return -ENOMEM; + +- for (var = data, idx = 0; ++ for (var = data; + var < data + data_len && *var; +- var = value + strlen(value) + 1, idx++) { ++ var = value + strlen(value) + 1) { ++ struct nvmem_cell_info info = {}; ++ + eq = strchr(var, '='); + if (!eq) + break; + *eq = '\0'; + value = eq + 1; + +- priv->cells[idx].name = devm_kstrdup(dev, var, GFP_KERNEL); +- if (!priv->cells[idx].name) ++ info.name = devm_kstrdup(dev, var, GFP_KERNEL); ++ if (!info.name) + return -ENOMEM; +- priv->cells[idx].offset = data_offset + value - data; +- priv->cells[idx].bytes = strlen(value); +- priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name); ++ info.offset = data_offset + value - data; ++ info.bytes = strlen(value); ++ info.np = of_get_child_by_name(dev->of_node, info.name); + if (!strcmp(var, "ethaddr")) { +- priv->cells[idx].raw_len = strlen(value); +- priv->cells[idx].bytes = ETH_ALEN; +- priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr; ++ info.raw_len = strlen(value); ++ info.bytes = ETH_ALEN; ++ info.read_post_process = u_boot_env_read_post_process_ethaddr; + } +- } + +- if (WARN_ON(idx != priv->ncells)) +- priv->ncells = idx; ++ nvmem_add_one_cell(nvmem, &info); ++ } + + return 0; + } +@@ -209,7 +199,6 @@ static int u_boot_env_probe(struct platf + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct u_boot_env *priv; +- int err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -224,17 +213,15 @@ static int u_boot_env_probe(struct platf + return PTR_ERR(priv->mtd); + } + +- err = u_boot_env_parse(priv); +- if (err) +- return err; +- + config.dev = dev; +- config.cells = priv->cells; +- config.ncells = priv->ncells; + config.priv = priv; + config.size = priv->mtd->size; + +- return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); ++ priv->nvmem = devm_nvmem_register(dev, &config); ++ if (IS_ERR(priv->nvmem)) ++ return PTR_ERR(priv->nvmem); ++ ++ return u_boot_env_parse(priv); + } + + static const struct of_device_id u_boot_env_of_match_table[] = { diff --git a/target/linux/generic/backport-6.1/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch b/target/linux/generic/backport-6.1/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch new file mode 100644 index 0000000000..70abc7cf14 --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0012-nvmem-u-boot-env-use-nvmem-device-helpers.patch @@ -0,0 +1,81 @@ +From a832556d23c5a11115f300011a5874d6107a0d62 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:19 +0100 +Subject: [PATCH] nvmem: u-boot-env: use nvmem device helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use nvmem_dev_size() and nvmem_device_read() to make this driver less +mtd dependent. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-4-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -127,27 +127,34 @@ static int u_boot_env_add_cells(struct u + + static int u_boot_env_parse(struct u_boot_env *priv) + { ++ struct nvmem_device *nvmem = priv->nvmem; + struct device *dev = priv->dev; + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; + size_t data_offset; + size_t data_len; ++ size_t dev_size; + uint32_t crc32; + uint32_t calc; +- size_t bytes; + uint8_t *buf; ++ int bytes; + int err; + +- buf = kcalloc(1, priv->mtd->size, GFP_KERNEL); ++ dev_size = nvmem_dev_size(nvmem); ++ ++ buf = kcalloc(1, dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; + } + +- err = mtd_read(priv->mtd, 0, priv->mtd->size, &bytes, buf); +- if ((err && !mtd_is_bitflip(err)) || bytes != priv->mtd->size) { +- dev_err(dev, "Failed to read from mtd: %d\n", err); ++ bytes = nvmem_device_read(nvmem, 0, dev_size, buf); ++ if (bytes < 0) { ++ err = bytes; ++ goto err_kfree; ++ } else if (bytes != dev_size) { ++ err = -EIO; + goto err_kfree; + } + +@@ -169,8 +176,8 @@ static int u_boot_env_parse(struct u_boo + break; + } + crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); +- crc32_data_len = priv->mtd->size - crc32_data_offset; +- data_len = priv->mtd->size - data_offset; ++ crc32_data_len = dev_size - crc32_data_offset; ++ data_len = dev_size - data_offset; + + calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + if (calc != crc32) { +@@ -179,7 +186,7 @@ static int u_boot_env_parse(struct u_boo + goto err_kfree; + } + +- buf[priv->mtd->size - 1] = '\0'; ++ buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); + if (err) + dev_err(dev, "Failed to add cells: %d\n", err); diff --git a/target/linux/generic/backport-6.1/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch b/target/linux/generic/backport-6.1/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch new file mode 100644 index 0000000000..273cfed874 --- /dev/null +++ b/target/linux/generic/backport-6.1/819-v6.8-0013-nvmem-u-boot-env-improve-coding-style.patch @@ -0,0 +1,62 @@ +From 6bafe07c930676d6430be471310958070816a595 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 21 Dec 2023 18:34:20 +0100 +Subject: [PATCH] nvmem: u-boot-env: improve coding style +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +1. Prefer kzalloc() over kcalloc() + See memory-allocation.rst which says: "to be on the safe side it's + best to use routines that set memory to zero, like kzalloc()" +2. Drop dev_err() for u_boot_env_add_cells() fail + It can fail only on -ENOMEM. We don't want to print error then. +3. Add extra "crc32_addr" variable + It makes code reading header's crc32 easier to understand / review. + +Signed-off-by: Rafał Miłecki +Reviewed-by: Miquel Raynal +Link: https://lore.kernel.org/r/20231221173421.13737-5-zajec5@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/u-boot-env.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/nvmem/u-boot-env.c ++++ b/drivers/nvmem/u-boot-env.c +@@ -132,6 +132,7 @@ static int u_boot_env_parse(struct u_boo + size_t crc32_data_offset; + size_t crc32_data_len; + size_t crc32_offset; ++ __le32 *crc32_addr; + size_t data_offset; + size_t data_len; + size_t dev_size; +@@ -143,7 +144,7 @@ static int u_boot_env_parse(struct u_boo + + dev_size = nvmem_dev_size(nvmem); + +- buf = kcalloc(1, dev_size, GFP_KERNEL); ++ buf = kzalloc(dev_size, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_out; +@@ -175,7 +176,8 @@ static int u_boot_env_parse(struct u_boo + data_offset = offsetof(struct u_boot_env_image_broadcom, data); + break; + } +- crc32 = le32_to_cpu(*(__le32 *)(buf + crc32_offset)); ++ crc32_addr = (__le32 *)(buf + crc32_offset); ++ crc32 = le32_to_cpu(*crc32_addr); + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; + +@@ -188,8 +190,6 @@ static int u_boot_env_parse(struct u_boo + + buf[dev_size - 1] = '\0'; + err = u_boot_env_add_cells(priv, buf, data_offset, data_len); +- if (err) +- dev_err(dev, "Failed to add cells: %d\n", err); + + err_kfree: + kfree(buf); diff --git a/target/linux/generic/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch b/target/linux/generic/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch index 9b111050ee..d07447bcba 100644 --- a/target/linux/generic/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch +++ b/target/linux/generic/pending-5.15/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch @@ -36,9 +36,9 @@ Signed-off-by: Srinivas Kandagatla --- a/drivers/nvmem/u-boot-env.c +++ b/drivers/nvmem/u-boot-env.c -@@ -182,7 +182,7 @@ static int u_boot_env_parse(struct u_boo - crc32_data_len = priv->mtd->size - crc32_data_offset; - data_len = priv->mtd->size - data_offset; +@@ -181,7 +181,7 @@ static int u_boot_env_parse(struct u_boo + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; - calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L); diff --git a/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch b/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch index 9b111050ee..d07447bcba 100644 --- a/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch +++ b/target/linux/generic/pending-6.1/802-nvmem-u-boot-env-align-endianness-of-crc32-values.patch @@ -36,9 +36,9 @@ Signed-off-by: Srinivas Kandagatla --- a/drivers/nvmem/u-boot-env.c +++ b/drivers/nvmem/u-boot-env.c -@@ -182,7 +182,7 @@ static int u_boot_env_parse(struct u_boo - crc32_data_len = priv->mtd->size - crc32_data_offset; - data_len = priv->mtd->size - data_offset; +@@ -181,7 +181,7 @@ static int u_boot_env_parse(struct u_boo + crc32_data_len = dev_size - crc32_data_offset; + data_len = dev_size - data_offset; - calc = crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L; + calc = le32_to_cpu((__le32)crc32(~0, buf + crc32_data_offset, crc32_data_len) ^ ~0L); From 751791d545087ceee10c680ec8b5590b3554d082 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Sat, 6 Jan 2024 18:48:46 +0100 Subject: [PATCH 069/222] packages: store URL in Manifest The manifest should provide as much information as possible about the package, including the project URL. With this commit the URL is stored as it's own attribute instead of at the end of the description. Signed-off-by: Paul Spooren --- include/package-dumpinfo.mk | 4 ++-- include/package-ipkg.mk | 1 + scripts/metadata.pm | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/package-dumpinfo.mk b/include/package-dumpinfo.mk index 6baf10225d..fc25099ad3 100644 --- a/include/package-dumpinfo.mk +++ b/include/package-dumpinfo.mk @@ -37,14 +37,14 @@ $(if $(USERID),Require-User: $(USERID) $(if $(LICENSE),License: $(LICENSE) )$(if $(LICENSE_FILES),LicenseFiles: $(LICENSE_FILES) )$(if $(PKG_CPE_ID),CPE-ID: $(PKG_CPE_ID) +)$(if $(URL),URL: $(URL) )$(if $(ABI_VERSION),ABI-Version: $(ABI_VERSION) )Type: $(if $(Package/$(1)/targets),$(Package/$(1)/targets),$(if $(PKG_TARGETS),$(PKG_TARGETS),ipkg)) $(if $(KCONFIG),Kernel-Config: $(KCONFIG) )$(if $(BUILDONLY),Build-Only: $(BUILDONLY) )$(if $(HIDDEN),Hidden: $(HIDDEN) )Description: $(if $(Package/$(1)/description),$(Package/$(1)/description),$(TITLE)) -$(if $(URL),$(URL) -)$(MAINTAINER) +$(MAINTAINER) @@ $(if $(Package/$(1)/config),Config: $(Package/$(1)/config) diff --git a/include/package-ipkg.mk b/include/package-ipkg.mk index afa2b81eb9..5f5f7e1317 100644 --- a/include/package-ipkg.mk +++ b/include/package-ipkg.mk @@ -185,6 +185,7 @@ $$(call addfield,Depends,$$(Package/$(1)/DEPENDS) )$$(call addfield,Section,$(SECTION) )$$(call addfield,Require-User,$(USERID) )$$(call addfield,SourceDateEpoch,$(PKG_SOURCE_DATE_EPOCH) +)$$(call addfield,URL,$(URL) )$$(if $$(ABIV_$(1)),ABIVersion: $$(ABIV_$(1)) )$(if $(PKG_CPE_ID),CPE-ID: $(PKG_CPE_ID) )$(if $(filter hold,$(PKG_FLAGS)),Status: unknown hold not-installed diff --git a/scripts/metadata.pm b/scripts/metadata.pm index 587ce7207d..ecfe42c0bc 100644 --- a/scripts/metadata.pm +++ b/scripts/metadata.pm @@ -257,6 +257,7 @@ sub parse_package_metadata($) { /^License: \s*(.+)\s*$/ and $pkg->{license} = $1; /^LicenseFiles: \s*(.+)\s*$/ and $pkg->{licensefiles} = $1; /^CPE-ID: \s*(.+)\s*$/ and $pkg->{cpe_id} = $1; + /^URL: \s*(.+)\s*$/ and $pkg->{url} = $1; /^ABI-Version: \s*(.+)\s*$/ and $pkg->{abi_version} = $1; /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1; /^Provides: \s*(.+)\s*$/ and do { @@ -344,6 +345,7 @@ sub parse_package_manifest_metadata($) { /^Section:\s*(.+)\s*$/ and $pkg->{section} = $1; /^SourceDateEpoch: \s*(.+)\s*$/ and $pkg->{sourcedateepoch} = $1; /^CPE-ID:\s*(.+)\s*$/ and $pkg->{cpe_id} = $1; + /^URL:\s*(.+)\s*$/ and $pkg->{url} = $1; /^Architecture:\s*(.+)\s*$/ and $pkg->{architecture} = $1; /^Installed-Size:\s*(.+)\s*$/ and $pkg->{installedsize} = $1; /^Filename:\s*(.+)\s*$/ and $pkg->{filename} = $1; From e32edf712b7c43e25b4bec40fedfd948a0ed5bd6 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Sat, 6 Jan 2024 18:50:00 +0100 Subject: [PATCH 070/222] packages: add PKG_URL variable Using PKG_URL one may set the URL for all sub packages, which is usually shared anyway. Future packages should only use PKG_URL instead of adding it per sub-package. Signed-off-by: Paul Spooren --- include/package-defaults.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/package-defaults.mk b/include/package-defaults.mk index 2cff26b531..30b112c7d8 100644 --- a/include/package-defaults.mk +++ b/include/package-defaults.mk @@ -49,7 +49,7 @@ define Package/Default KCONFIG:= BUILDONLY:= HIDDEN:= - URL:= + URL:=$(PKG_URL) VARIANT:= DEFAULT_VARIANT:= USERID:= From 49e8f532989c342fff44c1c558f8182585673833 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Sat, 6 Jan 2024 18:10:29 +0100 Subject: [PATCH 071/222] scripts: fix installed-size calculation Previously the script would calculate the size of the compressed archive which isn't the size installed in the overlayfs. This commit uses zcat in combination with wc to calculate the umcompressed size. Signed-off-by: Paul Spooren --- scripts/ipkg-build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ipkg-build b/scripts/ipkg-build index 122cca2cb4..6abcc58832 100755 --- a/scripts/ipkg-build +++ b/scripts/ipkg-build @@ -181,7 +181,7 @@ for file_mode in $file_modes; do done $TAR -X "$tmp_dir"/tarX --format=gnu --numeric-owner --sort=name -cpf - --mtime="$TIMESTAMP" . | gzip -n - > "$tmp_dir"/data.tar.gz -installed_size=$(stat -c "%s" "$tmp_dir"/data.tar.gz) +installed_size=$(zcat < "$tmp_dir"/data.tar.gz | wc -c) sed -i -e "s/^Installed-Size: .*/Installed-Size: $installed_size/" \ "$pkg_dir"/$CONTROL/control From c7c2257f8289ba278a6baffb6fea945b4ad47344 Mon Sep 17 00:00:00 2001 From: Manuel Fombuena Date: Mon, 8 Jan 2024 01:49:58 +0000 Subject: [PATCH 072/222] ipq-wifi: fix PKG_MIRROR_HASH Incorrect PKG_MIRROR_HASH introduced on #14356 Fixes: 934873f4514b ("ipq-wifi: bump version to 2024-01-06-71f45cff") Signed-off-by: Manuel Fombuena --- package/firmware/ipq-wifi/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile index 7b71c63d6f..fe249807d4 100644 --- a/package/firmware/ipq-wifi/Makefile +++ b/package/firmware/ipq-wifi/Makefile @@ -8,7 +8,7 @@ PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git PKG_SOURCE_DATE:=2024-01-06 PKG_SOURCE_VERSION:=71f45cff8944405b7cc2bf5c19df2bd8fe7f2421 -PKG_MIRROR_HASH:=799602d1519605bab3a952bc07d1a055617ab295e338121bf0e6cae2ebbb0dc9 +PKG_MIRROR_HASH:=90c3c1659c54cdb4685d0a71633746c1000230e459801eb8ce12c805a994cc37 PKG_FLAGS:=nonshared From 5a82bb909bf16786b85508d2e974ddf0a14bb10c Mon Sep 17 00:00:00 2001 From: Hannu Nyman Date: Sat, 6 Jan 2024 19:59:13 +0200 Subject: [PATCH 073/222] mediatek: GL-MT6000: Add missing LED state definitions Adjust LED names and provide the OpenWrt status indicator aliases to actually use LEDs by the OpenWrt boot & sysupgrade processes. * Name both LEDs clearly by the color * Add the missing OpenWrt LED status indicator aliases and remove the now unnecessary default status from blue LED After this commit, the LEDs are used as: * bootloader, really early Linux boot: blue LED is on * preinit/failsafe: white LED blinks rapidly * late boot: white LED blinks slowly * boot completed, running normally: blue LED is on * sysupgrade: white LED blinks Signed-off-by: Hannu Nyman --- target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts b/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts index fded507039..9a7031df53 100644 --- a/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts +++ b/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts @@ -13,6 +13,10 @@ aliases { serial0 = &uart0; + led-boot = &led_white; + led-failsafe = &led_white; + led-running = &led_blue; + led-upgrade = &led_white; }; chosen { @@ -51,13 +55,12 @@ leds { compatible = "gpio-leds"; - led_run: led@0 { + led_blue: led@0 { label = "blue:run"; gpios = <&pio 38 GPIO_ACTIVE_LOW>; - default-state = "on"; }; - led@1 { + led_white: led@1 { label = "white:system"; gpios = <&pio 37 GPIO_ACTIVE_LOW>; }; From b4086f44cd8a739458a0fd12cfaf684515507614 Mon Sep 17 00:00:00 2001 From: "Leon M. Busch-George" Date: Fri, 13 Oct 2023 12:44:11 +0200 Subject: [PATCH 074/222] mediatek: add support for YunCore AX835 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardware specification: SoC: MediaTek MT7981B 2x A53 Flash: 16MB NOR RAM: 256MB Ethernet: 2x 10/100/1000 Mbps Switch: MediaTek MT7531AE WiFi: MediaTek MT7976C Button: Reset Power: DC 12V 1A, PoE 802.3af 48V Flash instructions: Option #1 - SSH I was able to SSH into the stock firmware of my device. 1. Attach the router to the network 2. Use scp (-O) to copy the sysupgrade image 3. Connect using SSH and run `sysupgrade -n` Option #2 - U-Boot One way to use the bootloader for flashing is using TFTP: 1. Connect to the router using an ethernet cable 2 Spin up a TFTP server serving the sysupgrade file 3. Open the case and attach a UART 4. Attach power to the router and interrupt the countdown by pressing any key 5. Select option #2 (Upgrade firmware) 6. Enter IP address information and image name 7. Wait patiently Co-Authored-By: Enrique Rodríguez Valencia Co-Authored-By: Hauke Mehrtens Signed-off-by: Leon M. Busch-George --- .../mediatek/dts/mt7981b-yuncore-ax835.dts | 259 ++++++++++++++++++ .../filogic/base-files/etc/board.d/02_network | 6 +- .../base-files/lib/upgrade/platform.sh | 3 +- target/linux/mediatek/image/filogic.mk | 19 ++ 4 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts diff --git a/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts b/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts new file mode 100644 index 0000000000..b3ca5bfa2c --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) + +/dts-v1/; + +#include "mt7981.dtsi" + +/ { + compatible = "yuncore,ax835", "mediatek,mt7981"; + model = "YunCore AX835"; + + aliases { + ethernet0 = &gmac0; + led-boot = &led_system; + led-failsafe = &led_system; + led-running = &led_system; + led-upgrade = &led_system; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; + + reg_led_vbus { + compatible = "regulator-fixed"; + regulator-name = "led_vbus"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + gpio = <&pio 5 GPIO_ACTIVE_HIGH>; + }; + + leds { + compatible = "gpio-leds"; + + led_system: led_system { + label = "red:system"; + gpios = <&pio 4 GPIO_ACTIVE_LOW>; + }; + + led_wifi24 { + label = "green:wifi2"; + gpios = <&pio 34 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led_wifi5 { + label = "blue:wifi5"; + gpios = <&pio 35 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + led_hwwatchdog { + // a gpio-wdt watchdog couldn't be made to work. + // the device rebooted after 5 minutes. + label = "hwwatchdog"; + gpios = <&pio 7 GPIO_ACTIVE_LOW>; + linux,default-trigger = "timer"; + led-pattern = <1000>, <1000>; + }; + + // there's another "syswatchdog" on gpio2 + }; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; + + spi2_flash_pins: spi2-pins { + mux { + function = "spi"; + groups = "spi2", "spi2_wp_hold"; + }; + + conf-pu { + pins = "SPI2_CS", "SPI2_HOLD", "SPI2_WP"; + drive-strength = <8>; + bias-pull-up = <103>; + }; + + conf-pd { + pins = "SPI2_CLK", "SPI2_MOSI", "SPI2_MISO"; + drive-strength = <8>; + bias-pull-down = <103>; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "disabled"; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_flash_pins>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + + compatible = "jedec,spi-nor"; + reg = <0>; + + spi-max-frequency = <52000000>; + spi-tx-buswidth = <4>; + spi-rx-buswidth = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@00000 { + label = "BL2"; + reg = <0x00000 0x40000>; + read-only; + }; + + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x10000>; + read-only; + }; + + factory: partition@50000 { + label = "Factory"; + reg = <0x50000 0x10000>; + read-only; + + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; + }; + + macaddr_factory_24: macaddr@24 { + reg = <0x24 0x6>; + }; + + macaddr_factory_2a: macaddr@2a { + reg = <0x2a 0x6>; + }; + }; + + partition@100000 { + label = "FIP"; + reg = <0x100000 0x80000>; + read-only; + }; + + partition@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x180000 0xe00000>; + }; + }; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + lan: port@3 { + reg = <3>; + label = "lan"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_2a 0>; + }; + + port@4 { + reg = <4>; + label = "wan"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_2a 0>; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + status = "okay"; + nvmem-cells = <&eeprom_factory 0>; + nvmem-cell-names = "eeprom"; +}; diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network index dd3464b72c..2a6a97919d 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network @@ -66,7 +66,8 @@ mediatek_setup_interfaces() ucidef_set_interface_lan "eth0" ;; smartrg,sdg-8622|\ - smartrg,sdg-8632) + smartrg,sdg-8632|\ + yuncore,ax835) ucidef_set_interfaces_lan_wan lan wan ;; tplink,tl-xdr6086) @@ -170,6 +171,9 @@ mediatek_setup_macs() wan_mac=$(mtd_get_mac_ascii Bdata ethaddr_wan) label_mac=$wan_mac ;; + yuncore,ax835) + label_mac=$(mtd_get_mac_binary "Factory" 0x4) + ;; esac [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index 65ec5d8271..517f4520e1 100755 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -111,7 +111,8 @@ platform_do_upgrade() { ;; esac ;; - cudy,wr3000-v1) + cudy,wr3000-v1|\ + yuncore,ax835) default_do_upgrade "$1" ;; glinet,gl-mt2500|\ diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index c079fae0b0..d0c9907635 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -880,6 +880,25 @@ endif endef TARGET_DEVICES += xiaomi_redmi-router-ax6000-ubootmod +define Device/yuncore_ax835 + DEVICE_VENDOR := YunCore + DEVICE_MODEL := AX835 + DEVICE_DTS := mt7981b-yuncore-ax835 + DEVICE_DTS_DIR := ../dts + DEVICE_DTS_LOADADDR := 0x47000000 + IMAGES := sysupgrade.bin + IMAGE_SIZE := 14336k + SUPPORTED_DEVICES += mediatek,mt7981-spim-nor-rfb + KERNEL := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | pad-rootfs | check-size | append-metadata + DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware +endef +TARGET_DEVICES += yuncore_ax835 + + define Device/zbtlink_zbt-z8102ax DEVICE_VENDOR := Zbtlink DEVICE_MODEL := ZBT-Z8102AX From 50416c18dd309fec75b6911221905cd0c0139b25 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 21 Dec 2023 21:20:17 +0100 Subject: [PATCH 075/222] mediatek: disable btif for mt7622 devices It breaks built-in SoC WLAN. Can be re-enabled after we've figured out the cause Signed-off-by: Felix Fietkau --- .../mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi | 4 --- .../mediatek/dts/mt7622-linksys-e8450.dtsi | 4 --- .../mediatek/dts/mt7622-netgear-wax206.dts | 4 --- .../106-dts-mt7622-disable_btif.patch | 26 +++++++++++++++++++ .../112-dts-fix-bpi64-lan-names.patch | 2 +- .../114-dts-bpi64-disable-rtc.patch | 2 +- .../115-dts-bpi64-add-snand-support.patch | 2 +- .../131-dts-mt7622-add-snand-support.patch | 2 +- ...dts-fix-wmac-support-for-mt7622-rfb1.patch | 4 +-- ...80-dts-mt7622-bpi-r64-add-mt7531-irq.patch | 2 +- .../331-mt7622-rfb1-enable-bmt.patch | 2 +- ...mt7622-bpi-r64-aliases-for-dtoverlay.patch | 2 +- .../910-dts-mt7622-bpi-r64-wifi-eeprom.patch | 2 +- 13 files changed, 36 insertions(+), 22 deletions(-) create mode 100644 target/linux/mediatek/patches-6.1/106-dts-mt7622-disable_btif.patch diff --git a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi index 6d87454370..10cee7bcef 100644 --- a/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi +++ b/target/linux/mediatek/dts/mt7622-dlink-eagle-pro-ai-ax3200-a1.dtsi @@ -54,10 +54,6 @@ status = "okay"; }; -&btif { - status = "okay"; -}; - ð { pinctrl-names = "default"; pinctrl-0 = <ð_pins>; diff --git a/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi b/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi index abac02a72d..be216d972c 100644 --- a/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi +++ b/target/linux/mediatek/dts/mt7622-linksys-e8450.dtsi @@ -110,10 +110,6 @@ }; }; -&btif { - status = "okay"; -}; - &cir { pinctrl-names = "default"; pinctrl-0 = <&irrx_pins>; diff --git a/target/linux/mediatek/dts/mt7622-netgear-wax206.dts b/target/linux/mediatek/dts/mt7622-netgear-wax206.dts index 737ac35f3d..ce1cd46d2d 100644 --- a/target/linux/mediatek/dts/mt7622-netgear-wax206.dts +++ b/target/linux/mediatek/dts/mt7622-netgear-wax206.dts @@ -114,10 +114,6 @@ status = "okay"; }; -&btif { - status = "okay"; -}; - &cir { pinctrl-names = "default"; pinctrl-0 = <&irrx_pins>; diff --git a/target/linux/mediatek/patches-6.1/106-dts-mt7622-disable_btif.patch b/target/linux/mediatek/patches-6.1/106-dts-mt7622-disable_btif.patch new file mode 100644 index 0000000000..fc6a8f35bc --- /dev/null +++ b/target/linux/mediatek/patches-6.1/106-dts-mt7622-disable_btif.patch @@ -0,0 +1,26 @@ +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -108,10 +108,6 @@ + status = "disabled"; + }; + +-&btif { +- status = "okay"; +-}; +- + &cir { + pinctrl-names = "default"; + pinctrl-0 = <&irrx_pins>; +--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +@@ -89,10 +89,6 @@ + status = "disabled"; + }; + +-&btif { +- status = "okay"; +-}; +- + &cir { + pinctrl-names = "default"; + pinctrl-0 = <&irrx_pins>; diff --git a/target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch b/target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch index 816683e626..b012a48d75 100644 --- a/target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch +++ b/target/linux/mediatek/patches-6.1/112-dts-fix-bpi64-lan-names.patch @@ -8,7 +8,7 @@ }; chosen { -@@ -164,22 +165,22 @@ +@@ -160,22 +161,22 @@ port@1 { reg = <1>; diff --git a/target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch b/target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch index 3d1b90217f..e30d9e5e12 100644 --- a/target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch +++ b/target/linux/mediatek/patches-6.1/114-dts-bpi64-disable-rtc.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -558,12 +558,16 @@ +@@ -554,12 +554,16 @@ status = "okay"; }; diff --git a/target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch b/target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch index b159a17c4a..93f87fe697 100644 --- a/target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch +++ b/target/linux/mediatek/patches-6.1/115-dts-bpi64-add-snand-support.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -255,14 +255,42 @@ +@@ -251,14 +251,42 @@ status = "disabled"; }; diff --git a/target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch b/target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch index 9cfe69ebb6..d6e0ab1d41 100644 --- a/target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch +++ b/target/linux/mediatek/patches-6.1/131-dts-mt7622-add-snand-support.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -538,6 +538,65 @@ +@@ -534,6 +534,65 @@ status = "disabled"; }; diff --git a/target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch b/target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch index b01ce97cf0..117d5abde6 100644 --- a/target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch +++ b/target/linux/mediatek/patches-6.1/140-dts-fix-wmac-support-for-mt7622-rfb1.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -579,7 +579,7 @@ +@@ -575,7 +575,7 @@ reg = <0x140000 0x0080000>; }; @@ -9,7 +9,7 @@ label = "Factory"; reg = <0x1c0000 0x0100000>; }; -@@ -640,5 +640,6 @@ +@@ -636,5 +636,6 @@ &wmac { pinctrl-names = "default"; pinctrl-0 = <&wmac_pins>; diff --git a/target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch b/target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch index 5a834ac34f..676c09f656 100644 --- a/target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch +++ b/target/linux/mediatek/patches-6.1/180-dts-mt7622-bpi-r64-add-mt7531-irq.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -156,6 +156,10 @@ +@@ -152,6 +152,10 @@ switch@0 { compatible = "mediatek,mt7531"; reg = <0>; diff --git a/target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch b/target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch index 662515f2c5..3e956701cd 100644 --- a/target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch +++ b/target/linux/mediatek/patches-6.1/331-mt7622-rfb1-enable-bmt.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts -@@ -552,6 +552,7 @@ +@@ -548,6 +548,7 @@ spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; nand-ecc-engine = <&snfi>; diff --git a/target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch b/target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch index 600b94d7bb..8e56be9ff4 100644 --- a/target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch +++ b/target/linux/mediatek/patches-6.1/900-dts-mt7622-bpi-r64-aliases-for-dtoverlay.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -314,7 +314,7 @@ +@@ -310,7 +310,7 @@ /* Attention: GPIO 90 is used to switch between PCIe@1,0 and * SATA functions. i.e. output-high: PCIe, output-low: SATA */ diff --git a/target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch b/target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch index a45d51dd9f..b6762e29ac 100644 --- a/target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch +++ b/target/linux/mediatek/patches-6.1/910-dts-mt7622-bpi-r64-wifi-eeprom.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts -@@ -641,5 +641,28 @@ +@@ -637,5 +637,28 @@ }; &wmac { From 32d2443476188f880395e52e0216c84dce9670f8 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 21 Dec 2023 17:29:45 +0100 Subject: [PATCH 076/222] libubox: work around recent macOS linker change rpath handling seems to be more restrictive now. To deal with this, link the libubox library from STAGING_DIR_HOST to STAGING_DIR_HOSTPKG, so that packages installed to STAGING_DIR_HOSTPKG can pick it up. This mainly affects ucode, but possibly other host builds as well Signed-off-by: Felix Fietkau --- package/libs/libubox/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/package/libs/libubox/Makefile b/package/libs/libubox/Makefile index 549e604679..1ea886e6ac 100644 --- a/package/libs/libubox/Makefile +++ b/package/libs/libubox/Makefile @@ -105,6 +105,14 @@ CMAKE_HOST_OPTIONS += \ -DCMAKE_MACOSX_RPATH=1 \ -DCMAKE_INSTALL_RPATH="${STAGING_DIR_HOST}/lib" \ +ifeq ($(HOST_OS),Darwin) + define Host/Install + $(Host/Install/Default) + $(INSTALL_DIR) $(STAGING_DIR_HOSTPKG)/lib + cd "$(STAGING_DIR_HOSTPKG)/lib" && ln -sf ../../host/lib/libubox.* . + endef +endif + $(eval $(call BuildPackage,libubox)) $(eval $(call BuildPackage,libblobmsg-json)) $(eval $(call BuildPackage,jshn)) From d864f68232e910f2c8ab06a66347fc08c257dfcc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 9 Jan 2024 11:05:45 +0100 Subject: [PATCH 077/222] hostapd: add missing NULL pointer check on radar notification Fixes a race condition that can lead to a hostapd crash Signed-off-by: Felix Fietkau --- package/network/services/hostapd/src/src/ap/ubus.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index 6ff2257c32..66eba99901 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -1907,6 +1907,9 @@ void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequen struct hostapd_data *hapd; int i; + if (!ctx) + return; + blob_buf_init(&b, 0); blobmsg_add_u16(&b, "frequency", frequency); blobmsg_add_u16(&b, "width", chan_width); From 80e4e2285fdf4a7b19c84532deafe2d1e690ed30 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 9 Jan 2024 14:36:42 +0100 Subject: [PATCH 078/222] mac80211: do not emit VHT160 capabilities if channel width is less than 160 MHz Fixes compatibility issues with VHT160 capable clients Signed-off-by: Felix Fietkau --- .../kernel/mac80211/files/lib/netifd/wireless/mac80211.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index b5378e556e..6ff627b038 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -327,6 +327,11 @@ mac80211_hostapd_setup_base() { [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc" vht_cap="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))" + [ "$vht_oper_chwidth" -lt 2 ] && { + vht160=0 + short_gi_160=0 + } + mac80211_add_capabilities vht_capab $vht_cap \ RXLDPC:0x10::$rxldpc \ SHORT-GI-80:0x20::$short_gi_80 \ From 38bec08e87b69212daf34eac7b26d643a92d9353 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 9 Jan 2024 15:15:08 +0100 Subject: [PATCH 079/222] mediatek: fix BPI-R3 wifi mac address Setting/clearing bits on the first byte of the mac address causes collisions when using multiple SSIDs on both PHYs. Change the allocation to alter the last byte instead. Signed-off-by: Felix Fietkau --- .../base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index 7f013732d3..d9e0335b67 100644 --- a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -37,9 +37,9 @@ case "$board" in [ "$PHYNBR" = "1" ] && echo "$addr" > /sys${DEVPATH}/macaddress ;; bananapi,bpi-r3) - addr=$(macaddr_add $(cat /sys/class/net/eth0/address) 2) - [ "$PHYNBR" = "0" ] && macaddr_unsetbit $addr 6 > /sys${DEVPATH}/macaddress - [ "$PHYNBR" = "1" ] && macaddr_setbit $addr 6 > /sys${DEVPATH}/macaddress + addr=$(cat /sys/class/net/eth0/address) + [ "$PHYNBR" = "0" ] && macaddr_add $addr 2 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $addr 3 > /sys${DEVPATH}/macaddress ;; cetron,ct3003) addr=$(mtd_get_mac_binary "art" 0) From 3e753c45cd19199ef61aad805b0e29ed261577bd Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Mon, 27 Nov 2023 17:08:04 +0100 Subject: [PATCH 080/222] rtl838x: Enable jumbo frames by default Increase DEFAULT_MTU and max-mtu size Increase truncate length on rx of jumbo frame Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- .../files-5.15/drivers/net/ethernet/rtl838x_eth.c | 15 +++++++++------ .../files-5.15/drivers/net/ethernet/rtl838x_eth.h | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c index 9dcb7a3b78..54e592aeaa 100644 --- a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c @@ -43,6 +43,9 @@ extern struct rtl83xx_soc_info soc_info; #define RX_EN 0x4 #define TX_EN_93XX 0x20 #define RX_EN_93XX 0x10 +#define RX_TRUNCATE_EN_93XX BIT(6) +#define RX_TRUNCATE_EN_83XX BIT(4) +#define TX_PAD_EN_838X BIT(5) #define TX_DO 0x2 #define WRAP 0x2 #define MAX_PORTS 57 @@ -727,8 +730,8 @@ static void rtl838x_hw_en_rxtx(struct rtl838x_eth_priv *priv) /* Disable Head of Line features for all RX rings */ sw_w32(0xffffffff, priv->r->dma_if_rx_ring_size(0)); - /* Truncate RX buffer to 0x640 (1600) bytes, pad TX */ - sw_w32(0x06400020, priv->r->dma_if_ctrl); + /* Truncate RX buffer to DEFAULT_MTU bytes, pad TX */ + sw_w32((DEFAULT_MTU << 16) | RX_TRUNCATE_EN_83XX | TX_PAD_EN_838X, priv->r->dma_if_ctrl); /* Enable RX done, RX overflow and TX done interrupts */ sw_w32(0xfffff, priv->r->dma_if_intr_msk); @@ -752,7 +755,7 @@ static void rtl838x_hw_en_rxtx(struct rtl838x_eth_priv *priv) static void rtl839x_hw_en_rxtx(struct rtl838x_eth_priv *priv) { /* Setup CPU-Port: RX Buffer */ - sw_w32(0x0000c808, priv->r->dma_if_ctrl); + sw_w32((DEFAULT_MTU << 5) | RX_TRUNCATE_EN_83XX, priv->r->dma_if_ctrl); /* Enable Notify, RX done, RX overflow and TX done interrupts */ sw_w32(0x007fffff, priv->r->dma_if_intr_msk); /* Notify IRQ! */ @@ -775,8 +778,8 @@ static void rtl839x_hw_en_rxtx(struct rtl838x_eth_priv *priv) static void rtl93xx_hw_en_rxtx(struct rtl838x_eth_priv *priv) { - /* Setup CPU-Port: RX Buffer truncated at 1600 Bytes */ - sw_w32(0x06400040, priv->r->dma_if_ctrl); + /* Setup CPU-Port: RX Buffer truncated at DEFAULT_MTU Bytes */ + sw_w32((DEFAULT_MTU << 16) | RX_TRUNCATE_EN_93XX, priv->r->dma_if_ctrl); for (int i = 0; i < priv->rxrings; i++) { int pos = (i % 3) * 10; @@ -2415,7 +2418,7 @@ static int __init rtl838x_eth_probe(struct platform_device *pdev) dev->ethtool_ops = &rtl838x_ethtool_ops; dev->min_mtu = ETH_ZLEN; - dev->max_mtu = 1536; + dev->max_mtu = DEFAULT_MTU; dev->features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM; dev->hw_features = NETIF_F_RXCSUM; diff --git a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h index 7a5ff678a4..47ed286aa4 100644 --- a/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h +++ b/target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.h @@ -216,6 +216,9 @@ /* Registers of the internal Serdes of the 8380 */ #define RTL838X_SDS4_FIB_REG0 (0xF800) +/* Default MTU with jumbo frames support */ +#define DEFAULT_MTU 9000 + inline int rtl838x_mac_port_ctrl(int p) { return RTL838X_MAC_PORT_CTRL + (p << 7); From e0c0137eed81e365156270d20a3ba73b14e142f1 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Mon, 27 Nov 2023 17:09:27 +0100 Subject: [PATCH 081/222] rtl83xx: dsa: disable VLAN filtering on CPU port Before driver code - enabled egress filter for cpu and non-cpu ports - enabled ingress filter for non-cpu ports This patch explicitly enables ingress and egress filtering for non-cpu ports and disables ingress and egress filtering for cpu port. Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- .../realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c index 9f608950c0..75f9ceb557 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c @@ -1357,10 +1357,15 @@ static int rtl83xx_vlan_filtering(struct dsa_switch *ds, int port, * 2: Trap packet to CPU port * The Egress filter used 1 bit per state (0: DISABLED, 1: ENABLED) */ - if (port != priv->cpu_port) + if (port != priv->cpu_port) { priv->r->set_vlan_igr_filter(port, IGR_DROP); + priv->r->set_vlan_egr_filter(port, EGR_ENABLE); + } + else { + priv->r->set_vlan_igr_filter(port, IGR_TRAP); + priv->r->set_vlan_egr_filter(port, EGR_DISABLE); + } - priv->r->set_vlan_egr_filter(port, EGR_ENABLE); } else { /* Disable ingress and egress filtering */ if (port != priv->cpu_port) From a376508216440178184fb3ab71faf87eea637109 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Mon, 27 Nov 2023 17:09:55 +0100 Subject: [PATCH 082/222] rtl83xx: dsa: Do nothing when vid 0 Following other dsa drivers, vid 0 is no-op Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c index 75f9ceb557..3b5af72dd6 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c @@ -1430,6 +1430,8 @@ static int rtl83xx_vlan_add(struct dsa_switch *ds, int port, pr_debug("%s port %d, vid %d, flags %x\n", __func__, port, vlan->vid, vlan->flags); + if(!vlan->vid) return 0; + if (vlan->vid > 4095) { dev_err(priv->dev, "VLAN out of range: %d", vlan->vid); return -ENOTSUPP; From 2cfb1ecf103558a23c19ac55721dd4bfb0f7d4c1 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Tue, 12 Dec 2023 15:48:56 +0100 Subject: [PATCH 083/222] rtl930x: Rework per port LED configuration Use led_setX to determine number of LEDs per port. Introduce macros to calculate register value and shift for particular LED in a particular set. Problem with previous implementation is that it uses is10G status to determine leds per port. However with usxgmii, driver sets 10g, 5g and 2.5g so even though there are only 2 leds per port it selects 4 leds per port This implementation relies on configured led_set node. Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- .../dts-5.15/rtl9302_zyxel_xgs1250-12.dts | 4 +- .../drivers/net/dsa/rtl83xx/common.c | 20 ++++-- .../drivers/net/dsa/rtl83xx/rtl838x.h | 1 + .../drivers/net/dsa/rtl83xx/rtl930x.c | 69 ++++++++++++------- 4 files changed, 65 insertions(+), 29 deletions(-) diff --git a/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts b/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts index 0fe8f1997e..98ac08b26a 100644 --- a/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts +++ b/target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts @@ -66,10 +66,10 @@ compatible = "realtek,rtl9300-leds"; active-low; - led_set0 = <0x0000 0xffff 0x0a20 0x0b80>; // LED set 0: 1000Mbps, 10/100Mbps + led_set0 = <0x0a20 0x0b80>; // LED set 0: 1000Mbps, 10/100Mbps led_set1 = <0x0a0b 0x0a28 0x0a82 0x0a0b>; // LED set 1: (10G, 5G, 2.5G) (2.5G, 1G) // (5G, 10/100) (10G, 5G, 2.5G) - led_set2 = <0x0000 0xffff 0x0a20 0x0a01>; // LED set 2: 1000MBit, 10GBit + led_set2 = <0x0a20 0x0a01>; // LED set 2: 1000MBit, 10GBit }; }; diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c index 0434312afc..221428cc77 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c @@ -271,7 +271,7 @@ int write_phy(u32 port, u32 page, u32 reg, u32 val) static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) { struct device *dev = priv->dev; - struct device_node *dn, *phy_node, *mii_np = dev->of_node; + struct device_node *dn, *phy_node, *led_node, *mii_np = dev->of_node; struct mii_bus *bus; int ret; u32 pn; @@ -325,9 +325,12 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) return -ENODEV; } + led_node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds"); + for_each_node_by_name(dn, "port") { phy_interface_t interface; u32 led_set; + char led_set_str[16] = {0}; if (!of_device_is_available(dn)) continue; @@ -355,9 +358,18 @@ static int __init rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv) if (interface == PHY_INTERFACE_MODE_10GBASER) priv->ports[pn].is10G = true; - if (of_property_read_u32(dn, "led-set", &led_set)) - led_set = 0; - priv->ports[pn].led_set = led_set; + priv->ports[pn].leds_on_this_port = 0; + if (led_node) { + if (of_property_read_u32(dn, "led-set", &led_set)) + led_set = 0; + priv->ports[pn].led_set = led_set; + sprintf(led_set_str, "led_set%d", led_set); + priv->ports[pn].leds_on_this_port = of_property_count_u32_elems(led_node, led_set_str); + if (priv->ports[pn].leds_on_this_port > 4) { + dev_err(priv->dev, "led_set %d for port %d configuration is invalid\n", led_set, pn); + return -ENODEV; + } + } /* Check for the integrated SerDes of the RTL8380M first */ if (of_property_read_bool(phy_node, "phy-is-integrated") diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h index 24d18d61fa..a642c74775 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h @@ -635,6 +635,7 @@ struct rtl838x_port { bool is2G5; int sds_num; int led_set; + int leds_on_this_port; const struct dsa_port *dp; }; diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c index c4f200bc0e..4a4a926bb2 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c @@ -24,6 +24,15 @@ #define RTL930X_LED_GLB_ACTIVE_LOW BIT(22) +#define RTL930X_LED_SETX_0_CTRL(x) (RTL930X_LED_SET0_0_CTRL - (x * 8)) +#define RTL930X_LED_SETX_1_CTRL(x) (RTL930X_LED_SETX_0_CTRL(x) - 4) + +/* get register for given set and led in the set */ +#define RTL930X_LED_SETX_LEDY(x,y) (RTL930X_LED_SETX_0_CTRL(x) - 4 * (y / 2)) + +/* get shift for given led in any set */ +#define RTL930X_LED_SET_LEDX_SHIFT(x) (16 * (x % 2)) + extern struct mutex smi_lock; extern struct rtl83xx_soc_info soc_info; @@ -2396,10 +2405,44 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) return; } + for (int set = 0; set < 4; set++) { + char set_name[16] = {0}; + u32 set_config[4]; + int leds_in_this_set = 0; + + /* Reset LED set configuration */ + sw_w32(0, RTL930X_LED_SETX_0_CTRL(set)); + sw_w32(0, RTL930X_LED_SETX_1_CTRL(set)); + + /** + * Each led set has 4 number of leds, and each LED is configured with 16 bits + * So each 32bit register holds configuration for 2 leds + * And therefore each set requires 2 registers for configuring 4 LEDs + * + */ + sprintf(set_name, "led_set%d", set); + leds_in_this_set = of_property_count_u32_elems(node, set_name); + + if (leds_in_this_set == 0 || leds_in_this_set > sizeof(set_config)) { + pr_err("%s led_set configuration invalid skipping over this set\n", __func__); + continue; + } + + if (of_property_read_u32_array(node, set_name, set_config, leds_in_this_set)) { + break; + } + + /* Write configuration as per number of LEDs */ + for (int i=0, led = leds_in_this_set-1; led >= 0; led--,i++) { + sw_w32_mask(0xffff << RTL930X_LED_SET_LEDX_SHIFT(led), + (0xffff & set_config[i]) << RTL930X_LED_SET_LEDX_SHIFT(led), + RTL930X_LED_SETX_LEDY(set, led)); + } + } + for (int i = 0; i < priv->cpu_port; i++) { int pos = (i << 1) % 32; u32 set; - u32 v; sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_FIB_SET_SEL_CTRL(i)); sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_COPR_SET_SEL_CTRL(i)); @@ -2407,12 +2450,8 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) if (!priv->ports[i].phy) continue; - v = 0x1; - if (priv->ports[i].is10G) - v = 0x3; - if (priv->ports[i].phy_is_integrated) - v = 0x1; - sw_w32_mask(0x3 << pos, v << pos, RTL930X_LED_PORT_NUM_CTRL(i)); + /* 0x0 = 1 led, 0x1 = 2 leds, 0x2 = 3 leds, 0x3 = 4 leds per port */ + sw_w32_mask(0x3 << pos, (priv->ports[i].leds_on_this_port -1) << pos, RTL930X_LED_PORT_NUM_CTRL(i)); pm |= BIT(i); @@ -2421,22 +2460,6 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) sw_w32_mask(0, set << pos, RTL930X_LED_PORT_FIB_SET_SEL_CTRL(i)); } - for (int i = 0; i < 4; i++) { - const __be32 *led_set; - char set_name[9]; - u32 setlen; - u32 v; - - sprintf(set_name, "led_set%d", i); - led_set = of_get_property(node, set_name, &setlen); - if (!led_set || setlen != 16) - break; - v = be32_to_cpup(led_set) << 16 | be32_to_cpup(led_set + 1); - sw_w32(v, RTL930X_LED_SET0_0_CTRL - 4 - i * 8); - v = be32_to_cpup(led_set + 2) << 16 | be32_to_cpup(led_set + 3); - sw_w32(v, RTL930X_LED_SET0_0_CTRL - i * 8); - } - /* Set LED mode to serial (0x1) */ sw_w32_mask(0x3, 0x1, RTL930X_LED_GLB_CTRL); From fe01435b6933756f4a916e4bccc409a88e3fcc56 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Wed, 13 Dec 2023 08:29:36 +0100 Subject: [PATCH 084/222] rtl83xx: dsa: Clear duplex bit correctly Without this, luci shows 10M full duplex when there is no link. So explicitly set half duplex and unknown speed. Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c index 3b5af72dd6..0e1d64ae69 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c @@ -870,6 +870,8 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port, if (state->duplex == DUPLEX_FULL) reg |= RTL930X_DUPLEX_MODE; + else + reg &= ~RTL930X_DUPLEX_MODE; /* Clear duplex bit otherwise */ if (priv->ports[port].phy_is_integrated) reg &= ~RTL930X_FORCE_EN; /* Clear MAC_FORCE_EN to allow SDS-MAC link */ From da495c477d9018d59b1f6deb128cc8372d16df16 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Wed, 3 Jan 2024 15:53:47 +0100 Subject: [PATCH 085/222] rtl93xx: dsa: Fix 802.1QinQ for trunk ports Fix incorrect register value being set for VLAN_PORT_FWD Before, the 0b1111 would be set for the register which means outgoing packets would receive an extra tag, corresponding to the PVID of the port. On untagged ports, this meant outgoing packets with a single tag. On tagged ports, this meant outgoing QinQ packets, where the inner tag was either the PVID of the untagged ingress port, or the already assigned original (single) tag. Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- .../realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c | 4 ++-- .../realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c index 4a4a926bb2..793d762489 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c @@ -258,9 +258,9 @@ static void rtl930x_vlan_fwd_on_inner(int port, bool is_set) { /* Always set all tag modes to fwd based on either inner or outer tag */ if (is_set) - sw_w32_mask(0, 0xf, RTL930X_VLAN_PORT_FWD + (port << 2)); - else sw_w32_mask(0xf, 0, RTL930X_VLAN_PORT_FWD + (port << 2)); + else + sw_w32_mask(0, 0xf, RTL930X_VLAN_PORT_FWD + (port << 2)); } static void rtl930x_vlan_profile_setup(int profile) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c index 3221109c18..0e82d79d4c 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c @@ -827,9 +827,9 @@ static void rtl931x_vlan_fwd_on_inner(int port, bool is_set) { /* Always set all tag modes to fwd based on either inner or outer tag */ if (is_set) - sw_w32_mask(0, 0xf, RTL931X_VLAN_PORT_FWD + (port << 2)); - else sw_w32_mask(0xf, 0, RTL931X_VLAN_PORT_FWD + (port << 2)); + else + sw_w32_mask(0, 0xf, RTL931X_VLAN_PORT_FWD + (port << 2)); } static void rtl931x_vlan_profile_setup(int profile) From e691e2b302d98d4239ffbfced0759384592ea995 Mon Sep 17 00:00:00 2001 From: Harshal Gohel Date: Wed, 3 Jan 2024 16:15:12 +0100 Subject: [PATCH 086/222] rtl83xx: dsa: reset PVID to 1 instead of 0 Before, PVID is reset for all ports and goes out of bounds. Also, PVID is later changed by dsa configuration by `ip link` and `bridge vlan` commands, this does not change the CPU port PVID and CPU PVID stays 0. It does not allow sending packets from OpenWrt to any connected devices unless default configuration is changed This change iterates up to and including cpu_port and sets default PVID to 1. For lan* ports PVID can be configured with `ip link` and `bridge vlan` commands Acked-by: Simon Wunderlich Signed-off-by: Harshal Gohel --- .../linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c index 0e1d64ae69..a5b8ccea1c 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c @@ -137,9 +137,9 @@ static void rtl83xx_vlan_setup(struct rtl838x_switch_priv *priv) priv->r->vlan_set_tagged(i, &info); /* reset PVIDs; defaults to 1 on reset */ - for (int i = 0; i <= priv->ds->num_ports; i++) { - priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_INNER, 0); - priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_OUTER, 0); + for (int i = 0; i <= priv->cpu_port; i++) { + priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_INNER, 1); + priv->r->vlan_port_pvid_set(i, PBVLAN_TYPE_OUTER, 1); priv->r->vlan_port_pvidmode_set(i, PBVLAN_TYPE_INNER, PBVLAN_MODE_UNTAG_AND_PRITAG); priv->r->vlan_port_pvidmode_set(i, PBVLAN_TYPE_OUTER, PBVLAN_MODE_UNTAG_AND_PRITAG); } From 1f11a4e28336c07aca61dd3b4fef01ef872a362d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 27 Dec 2023 16:20:45 +0100 Subject: [PATCH 087/222] uhttpd: handle reload after uhttpd-mod-ubus installation using postinst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use postinst script to reload service instead of uci-defaults hack. It's possible thanks to recent base-files change that executes postinst after uci-defaults. This fixes support for uhttpd customizations. It's possible (again) to adjust uhttpd config with custom uci-defaults before it gets started. Cc: Hauke Mehrtens Fixes: d25d281fd668 ("uhttpd: Reload config after uhttpd-mod-ubus was added") Ref: b799dd3c705d ("base-files: execute package's "postinst" after executing uci-defaults") Signed-off-by: Rafał Miłecki --- package/network/services/uhttpd/Makefile | 9 ++++++++- package/network/services/uhttpd/files/ubus.default | 6 ------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/package/network/services/uhttpd/Makefile b/package/network/services/uhttpd/Makefile index 02a02405fd..37117bf911 100644 --- a/package/network/services/uhttpd/Makefile +++ b/package/network/services/uhttpd/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=uhttpd -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/uhttpd.git @@ -107,6 +107,13 @@ define Package/uhttpd-mod-ubus/install $(INSTALL_DATA) ./files/ubus.default $(1)/etc/uci-defaults/00_uhttpd_ubus endef +define Package/uhttpd-mod-ubus/postinst +#!/bin/sh +if [ -z "$${IPKG_INSTROOT}" ]; then + /etc/init.d/uhttpd reload +fi +endef + define Package/uhttpd-mod-ucode/install $(INSTALL_DIR) $(1)/usr/lib $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_ucode.so $(1)/usr/lib/ diff --git a/package/network/services/uhttpd/files/ubus.default b/package/network/services/uhttpd/files/ubus.default index 474016c1c5..d0a218a0ad 100644 --- a/package/network/services/uhttpd/files/ubus.default +++ b/package/network/services/uhttpd/files/ubus.default @@ -1,17 +1,11 @@ #!/bin/sh -commit=0 - if [ -z "$(uci -q get uhttpd.main.ubus_prefix)" ]; then uci set uhttpd.main.ubus_prefix=/ubus - commit=1 fi [ "$(uci -q get uhttpd.main.ubus_socket)" = "/var/run/ubus.sock" ] && { uci set uhttpd.main.ubus_socket='/var/run/ubus/ubus.sock' - commit=1 } -[ "$commit" = 1 ] && uci commit uhttpd && /etc/init.d/uhttpd reload - exit 0 From 0709bd87ba8a8c4b11389c4dea764d35ceabab85 Mon Sep 17 00:00:00 2001 From: Tomasz Maciej Nowak Date: Wed, 10 Jan 2024 16:39:57 +0100 Subject: [PATCH 088/222] ramips: mt76x8: add support for TP-Link RE365 v1 TP-Link RE365 is a wireless range extender, hardware-wise resembles RE305 with slight changes regarding buttons and LEDs. Specification SoC: MediaTek MT7628AN RAM: 64 MiB DDR2 Flash: 8 MiB SPI NOR WiFi: 2.4 GHz 2T2R integrated 5 GHz 2T2R MediaTek MT7612EN conncted to PCIe lanes Ethernet: 1x 10/100 Mbps integrated LEDs: 6x GPIO controlled Buttons: 4x GPIO controlled UART: row of 4 holes marked on PCB as J1, starting count from white triangle 1. VCC (3.3V), 2. GND, 3. RX, 4. TX baud: 57600, parity: none, flow control: none Installation 1. Open web management interface. 2. Go to Settings > System Tools > Firmware upgrade. 3. Select "Browse" and select the OpenWrt image with factory.bin suffix. 4. After selecting "Upgrade" firmware writing process will start. 5. Wait till device reboots, power LED should stay solid when it's fully booted, then it's ready for configuration through LAN port. Additional information With how device manufacturer patrtitioned the flash memory, it's possible that with default packages set, initial factory.bin image won't be created. In such case, try to reduce packages amount or use older release for initial conversion to OpenWrt. Later You can use sysupgrade.bin image with full set of packages because OpenWrt uses unpartitioned flash memory space unused by vendor firmware. Reverting to vendor firmware involves converting firmware using tplink-safeloader with -z option (can be found in ImageBuilder or SDK) and forcibly applying converted firmware as sysupgrade. Known issues WARNING: after removing casing of the device one is exposed to high voltage and is in a risk of being electrocuted. Caution when interfacing whith bootloader, saving its environment either by issuing "saveenv" or selecting option "1: Load system code to SDRAM via TFTP." in boot menu, any of those will lead to overwriting part of kernel. This will lead to need of firmware recovery. The cause of this issue is bootloader having environment offset on flash at 0x40000, while kernel starts from 0x20000. Signed-off-by: Tomasz Maciej Nowak [Wrap long line in DTS] Signed-off-by: Sander Vanheule --- .../ramips/dts/mt7628an_tplink_re365-v1.dts | 214 ++++++++++++++++++ target/linux/ramips/image/mt76x8.mk | 12 + .../mt76x8/base-files/etc/board.d/01_leds | 3 + .../mt76x8/base-files/etc/board.d/02_network | 1 + 4 files changed, 230 insertions(+) create mode 100644 target/linux/ramips/dts/mt7628an_tplink_re365-v1.dts diff --git a/target/linux/ramips/dts/mt7628an_tplink_re365-v1.dts b/target/linux/ramips/dts/mt7628an_tplink_re365-v1.dts new file mode 100644 index 0000000000..17fa9c0b5a --- /dev/null +++ b/target/linux/ramips/dts/mt7628an_tplink_re365-v1.dts @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7628an.dtsi" + +#include +#include +#include + +/ { + model = "TP-Link RE365 v1"; + compatible = "tplink,re365-v1", "mediatek,mt7628an-soc"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + label-mac-device = ðernet; + }; + + keys { + compatible = "gpio-keys"; + + button-led { + label = "led"; + gpios = <&gpio 44 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + button-power { + label = "power"; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + button-reset { + label = "reset"; + gpios = <&gpio 37 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + button-wps { + label = "wps"; + gpios = <&gpio 38 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-lan { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + }; + + led_power: led-power { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio 39 GPIO_ACTIVE_LOW>; + panic-indicator; + }; + + led-rssi-bad { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio 43 GPIO_ACTIVE_HIGH>; + }; + + led-rssi-good { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio 42 GPIO_ACTIVE_HIGH>; + }; + + led-wlan2g { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <2>; + gpios = <&gpio 41 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led-wlan5g { + color = ; + function = LED_FUNCTION_WLAN; + function-enumerator = <5>; + gpios = <&gpio 40 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + }; + + virtual_flash { + compatible = "mtd-concat"; + devices = <&fwconcat0>, <&fwconcat1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + compatible = "tplink,firmware"; + label = "firmware"; + reg = <0x0 0x0>; + }; + }; + }; +}; + +ðernet { + nvmem-cells = <&macaddr_config_10008 0>; + nvmem-cell-names = "mac-address"; +}; + +&pcie { + status = "okay"; +}; + +&pcie0 { + mt76@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + ieee80211-freq-limit = <5000000 6000000>; + nvmem-cells = <&eeprom_radio_8000>, <&macaddr_config_10008 2>; + nvmem-cell-names = "eeprom", "mac-address"; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x20000>; + read-only; + }; + + fwconcat0: partition@20000 { + label = "fwconcat0"; + reg = <0x20000 0x5e0000>; + }; + + partition@600000 { + label = "config"; + reg = <0x600000 0x50000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_config_10008: macaddr@10008 { + compatible = "mac-base"; + reg = <0x10008 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + fwconcat1: partition@650000 { + label = "fwconcat1"; + reg = <0x650000 0x1a0000>; + }; + + partition@7f0000 { + label = "radio"; + reg = <0x7f0000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_radio_8000: eeprom@8000 { + reg = <0x8000 0x200>; + }; + }; + }; + }; + }; +}; + +&state_default { + gpio { + groups = "refclk", "wdt", "p0led_an", "p1led_an", "p2led_an", "p3led_an", + "p4led_an"; + function = "gpio"; + }; +}; + +&wmac { + status = "okay"; + + nvmem-cells = <&eeprom_radio_0>, <&macaddr_config_10008 1>; + nvmem-cell-names = "eeprom", "mac-address"; +}; diff --git a/target/linux/ramips/image/mt76x8.mk b/target/linux/ramips/image/mt76x8.mk index 8a6bccfba6..9a458d38f3 100644 --- a/target/linux/ramips/image/mt76x8.mk +++ b/target/linux/ramips/image/mt76x8.mk @@ -666,6 +666,18 @@ define Device/tplink_re305-v3 endef TARGET_DEVICES += tplink_re305-v3 +define Device/tplink_re365-v1 + $(Device/tplink-safeloader) + DEVICE_MODEL := RE365 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-mt76x2 + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | check-size | append-metadata + IMAGE_SIZE := 7680k + KERNEL_SIZE := 6016k + TPLINK_BOARD_ID := RE365 +endef +TARGET_DEVICES += tplink_re365-v1 + define Device/tplink_tl-mr3020-v3 $(Device/tplink-v2) IMAGE_SIZE := 7808k diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds index c4301737b2..5a0e0ab214 100644 --- a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds @@ -91,6 +91,9 @@ tplink,tl-mr3020-v3|\ tplink,tl-wa801nd-v5) ucidef_set_led_netdev "lan" "lan" "green:lan" "eth0" ;; +tplink,re365-v1) + ucidef_set_led_netdev "lan" "lan" "blue:lan" "eth0" + ;; tplink,tl-mr3420-v5|\ tplink,tl-wr840n-v4|\ tplink,tl-wr842n-v5) diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network index fe3ac9193f..63abb14d13 100644 --- a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network @@ -27,6 +27,7 @@ ramips_setup_interfaces() tplink,re220-v2|\ tplink,re305-v1|\ tplink,re305-v3|\ + tplink,re365-v1|\ tplink,tl-wr802n-v4|\ tplink,tl-wa801nd-v5|\ tplink,tl-wr902ac-v4|\ From 6b0db8592a3e4342c32111491948f32d5bc0087f Mon Sep 17 00:00:00 2001 From: Uwe Niethammer Date: Fri, 10 Nov 2023 02:06:15 +0100 Subject: [PATCH 089/222] uqmi: added timeouts in qmi.sh Modems which are using qmi do not reply on the 1st sync but they do on subsequent. Sometimes uqmi is hanging - even when using an early dummy access to unlock the modem. To always guarantee a proper initialisation, running or hanging uqmi processes must be stopped before. All uqmi calls have now a timeout option -t to avoid hanging. Signed-off-by: Uwe Niethammer --- .../utils/uqmi/files/lib/netifd/proto/qmi.sh | 86 +++++++++---------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh index f8e655455a..49fd87ff9d 100755 --- a/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh +++ b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh @@ -85,8 +85,8 @@ proto_qmi_setup() { echo "Waiting for SIM initialization" local uninitialized_timeout=0 # timeout 3s for first call to avoid hanging uqmi - uqmi -d "$device" --get-pin-status -t 3000 > /dev/null 2>&1 - while uqmi -s -d "$device" --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do + uqmi -d "$device" -t 3000 --get-pin-status > /dev/null 2>&1 + while uqmi -s -d "$device" -t 1000 --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do [ -e "$device" ] || return 1 if [ "$uninitialized_timeout" -lt "$timeout" -o "$timeout" = "0" ]; then let uninitialized_timeout++ @@ -102,7 +102,7 @@ proto_qmi_setup() { # Check if UIM application is stuck in illegal state local uim_state_timeout=0 while true; do - json_load "$(uqmi -s -d "$device" --uim-get-sim-state)" + json_load "$(uqmi -s -d "$device" -t 1000 --uim-get-sim-state)" json_get_var card_application_state card_application_state # SIM card is either completely absent or state is labeled as illegal @@ -111,9 +111,9 @@ proto_qmi_setup() { echo "SIM in illegal state - Power-cycling SIM" # Try to reset SIM application - uqmi -d "$device" --uim-power-off --uim-slot 1 + uqmi -d "$device" -t 1000 --uim-power-off --uim-slot 1 sleep 3 - uqmi -d "$device" --uim-power-on --uim-slot 1 + uqmi -d "$device" -t 1000 --uim-power-on --uim-slot 1 if [ "$uim_state_timeout" -lt "$timeout" ] || [ "$timeout" = "0" ]; then let uim_state_timeout++ @@ -130,10 +130,10 @@ proto_qmi_setup() { fi done - if uqmi -s -d "$device" --uim-get-sim-state | grep -q '"Not supported"\|"Invalid QMI command"' && - uqmi -s -d "$device" --get-pin-status | grep -q '"Not supported"\|"Invalid QMI command"' ; then + if uqmi -s -d "$device" -t 1000 --uim-get-sim-state | grep -q '"Not supported"\|"Invalid QMI command"' && + uqmi -s -d "$device" -t 1000 --get-pin-status | grep -q '"Not supported"\|"Invalid QMI command"' ; then [ -n "$pincode" ] && { - uqmi -s -d "$device" --verify-pin1 "$pincode" > /dev/null || uqmi -s -d "$device" --uim-verify-pin1 "$pincode" > /dev/null || { + uqmi -s -d "$device" -t 1000 --verify-pin1 "$pincode" > /dev/null || uqmi -s -d "$device" -t 1000 --uim-verify-pin1 "$pincode" > /dev/null || { echo "Unable to verify PIN" proto_notify_error "$interface" PIN_FAILED proto_block_restart "$interface" @@ -141,10 +141,10 @@ proto_qmi_setup() { } } else - json_load "$(uqmi -s -d "$device" --get-pin-status)" + json_load "$(uqmi -s -d "$device" -t 1000 --get-pin-status)" json_get_var pin1_status pin1_status if [ -z "$pin1_status" ]; then - json_load "$(uqmi -s -d "$device" --uim-get-sim-state)" + json_load "$(uqmi -s -d "$device" -t 1000 --uim-get-sim-state)" json_get_var pin1_status pin1_status fi json_get_var pin1_verify_tries pin1_verify_tries @@ -167,7 +167,7 @@ proto_qmi_setup() { return 1 } if [ -n "$pincode" ]; then - uqmi -s -d "$device" --verify-pin1 "$pincode" > /dev/null 2>&1 || uqmi -s -d "$device" --uim-verify-pin1 "$pincode" > /dev/null 2>&1 || { + uqmi -s -d "$device" -t 1000 --verify-pin1 "$pincode" > /dev/null 2>&1 || uqmi -s -d "$device" -t 1000 --uim-verify-pin1 "$pincode" > /dev/null 2>&1 || { echo "Unable to verify PIN" proto_notify_error "$interface" PIN_FAILED proto_block_restart "$interface" @@ -194,7 +194,7 @@ proto_qmi_setup() { fi if [ -n "$plmn" ]; then - json_load "$(uqmi -s -d "$device" --get-plmn)" + json_load "$(uqmi -s -d "$device" -t 1000 --get-plmn)" json_get_var plmn_mode mode json_get_vars mcc mnc || { mcc=0 @@ -218,16 +218,16 @@ proto_qmi_setup() { fi # Cleanup current state if any - uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 - uqmi -s -d "$device" --set-ip-family ipv6 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-ip-family ipv6 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1 # Go online - uqmi -s -d "$device" --set-device-operating-mode online > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-device-operating-mode online > /dev/null 2>&1 # Set IP format - uqmi -s -d "$device" --set-data-format 802.3 > /dev/null 2>&1 - uqmi -s -d "$device" --wda-set-data-format 802.3 > /dev/null 2>&1 - dataformat="$(uqmi -s -d "$device" --wda-get-data-format)" + uqmi -s -d "$device" -t 1000 --set-data-format 802.3 > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --wda-set-data-format 802.3 > /dev/null 2>&1 + dataformat="$(uqmi -s -d "$device" -t 1000 --wda-get-data-format)" if [ "$dataformat" = '"raw-ip"' ]; then @@ -240,13 +240,13 @@ proto_qmi_setup() { echo "Y" > /sys/class/net/$ifname/qmi/raw_ip fi - uqmi -s -d "$device" --sync > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --sync > /dev/null 2>&1 - uqmi -s -d "$device" --network-register > /dev/null 2>&1 + uqmi -s -d "$device" -t 20000 --network-register > /dev/null 2>&1 # PLMN selection must happen after the call to network-register if [ -n "$mcc" -a -n "$mnc" ]; then - uqmi -s -d "$device" --set-plmn --mcc "$mcc" --mnc "$mnc" > /dev/null 2>&1 || { + uqmi -s -d "$device" -t 1000 --set-plmn --mcc "$mcc" --mnc "$mnc" > /dev/null 2>&1 || { echo "Unable to set PLMN" proto_notify_error "$interface" PLMN_FAILED proto_block_restart "$interface" @@ -255,10 +255,10 @@ proto_qmi_setup() { fi [ -n "$modes" ] && { - uqmi -s -d "$device" --set-network-modes "$modes" > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-network-modes "$modes" > /dev/null 2>&1 sleep 3 # Scan network to not rely on registration-timeout after RAT change - uqmi -s -d "$device" --network-scan > /dev/null 2>&1 + uqmi -s -d "$device" -t 30000 --network-scan > /dev/null 2>&1 } echo "Waiting for network registration" @@ -266,7 +266,7 @@ proto_qmi_setup() { local registration_timeout=0 local registration_state="" while true; do - registration_state=$(uqmi -s -d "$device" --get-serving-system 2>/dev/null | jsonfilter -e "@.registration" 2>/dev/null) + registration_state=$(uqmi -s -d "$device" -t 1000 --get-serving-system 2>/dev/null | jsonfilter -e "@.registration" 2>/dev/null) [ "$registration_state" = "registered" ] && break @@ -274,7 +274,7 @@ proto_qmi_setup() { if [ "$registration_timeout" -lt "$timeout" ] || [ "$timeout" = "0" ]; then [ "$registration_state" = "searching" ] || { echo "Device stopped network registration. Restart network registration" - uqmi -s -d "$device" --network-register > /dev/null 2>&1 + uqmi -s -d "$device" -t 20000 --network-register > /dev/null 2>&1 } let registration_timeout++ sleep 1 @@ -302,7 +302,7 @@ proto_qmi_setup() { # establish a non-LTE data session. profile_pdptype="$pdptype" [ "$profile_pdptype" = "ip" ] && profile_pdptype="ipv4" - uqmi -s -d "$device" --modify-profile "3gpp,1" --apn "$apn" --pdp-type "$profile_pdptype" > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --modify-profile "3gpp,1" --apn "$apn" --pdp-type "$profile_pdptype" > /dev/null 2>&1 if [ "$pdptype" = "ip" ]; then [ -z "$autoconnect" ] && autoconnect=1 @@ -312,16 +312,16 @@ proto_qmi_setup() { fi [ "$pdptype" = "ip" -o "$pdptype" = "ipv4v6" ] && { - cid_4=$(uqmi -s -d "$device" --get-client-id wds) + cid_4=$(uqmi -s -d "$device" -t 1000 --get-client-id wds) if ! [ "$cid_4" -eq "$cid_4" ] 2> /dev/null; then echo "Unable to obtain client ID" proto_notify_error "$interface" NO_CID return 1 fi - uqmi -s -d "$device" --set-client-id wds,"$cid_4" --set-ip-family ipv4 > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --set-ip-family ipv4 > /dev/null 2>&1 - pdh_4=$(uqmi -s -d "$device" --set-client-id wds,"$cid_4" \ + pdh_4=$(uqmi -s -d "$device" -t 5000 --set-client-id wds,"$cid_4" \ --start-network \ ${apn:+--apn $apn} \ ${profile:+--profile $profile} \ @@ -333,35 +333,35 @@ proto_qmi_setup() { # pdh_4 is a numeric value on success if ! [ "$pdh_4" -eq "$pdh_4" ] 2> /dev/null; then echo "Unable to connect IPv4" - uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 fi # Check data connection state - connstat=$(uqmi -s -d "$device" --set-client-id wds,"$cid_4" --get-data-status) + connstat=$(uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --get-data-status) [ "$connstat" == '"connected"' ] || { echo "No data link!" - uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 } } [ "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] && { - cid_6=$(uqmi -s -d "$device" --get-client-id wds) + cid_6=$(uqmi -s -d "$device" -t 1000 --get-client-id wds) if ! [ "$cid_6" -eq "$cid_6" ] 2> /dev/null; then echo "Unable to obtain client ID" proto_notify_error "$interface" NO_CID return 1 fi - uqmi -s -d "$device" --set-client-id wds,"$cid_6" --set-ip-family ipv6 > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --set-ip-family ipv6 > /dev/null 2>&1 : "${v6apn:=${apn}}" : "${v6profile:=${profile}}" - pdh_6=$(uqmi -s -d "$device" --set-client-id wds,"$cid_6" \ + pdh_6=$(uqmi -s -d "$device" -t 5000 --set-client-id wds,"$cid_6" \ --start-network \ ${v6apn:+--apn $v6apn} \ ${v6profile:+--profile $v6profile} \ @@ -373,16 +373,16 @@ proto_qmi_setup() { # pdh_6 is a numeric value on success if ! [ "$pdh_6" -eq "$pdh_6" ] 2> /dev/null; then echo "Unable to connect IPv6" - uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 fi # Check data connection state - connstat=$(uqmi -s -d "$device" --set-client-id wds,"$cid_6" --set-ip-family ipv6 --get-data-status) + connstat=$(uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --set-ip-family ipv6 --get-data-status) [ "$connstat" == '"connected"' ] || { echo "No data link!" - uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1 proto_notify_error "$interface" CALL_FAILED return 1 } @@ -407,7 +407,7 @@ proto_qmi_setup() { [ -n "$pdh_6" ] && { if [ -z "$dhcpv6" -o "$dhcpv6" = 0 ]; then - json_load "$(uqmi -s -d $device --set-client-id wds,$cid_6 --get-current-settings)" + json_load "$(uqmi -s -d $device -t 1000 --set-client-id wds,$cid_6 --get-current-settings)" json_select ipv6 json_get_var ip_6 ip json_get_var gateway_6 gateway @@ -449,7 +449,7 @@ proto_qmi_setup() { [ -n "$pdh_4" ] && { if [ "$dhcp" = 0 ]; then - json_load "$(uqmi -s -d $device --set-client-id wds,$cid_4 --get-current-settings)" + json_load "$(uqmi -s -d $device -t 1000 --set-client-id wds,$cid_4 --get-current-settings)" json_select ipv4 json_get_var ip_4 ip json_get_var gateway_4 gateway @@ -492,16 +492,16 @@ qmi_wds_stop() { [ -n "$cid" ] || return - uqmi -s -d "$device" --set-client-id wds,"$cid" \ + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \ --stop-network 0xffffffff \ --autoconnect > /dev/null 2>&1 [ -n "$pdh" ] && { - uqmi -s -d "$device" --set-client-id wds,"$cid" \ + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \ --stop-network "$pdh" > /dev/null 2>&1 } - uqmi -s -d "$device" --set-client-id wds,"$cid" \ + uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \ --release-client-id wds > /dev/null 2>&1 } From 2fe8ecd880396b5ae25fe9583aaa1d71be0b8468 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Tue, 9 Jan 2024 20:52:56 +0100 Subject: [PATCH 090/222] ath79: read back reset register Read back the reset register in order to flush the cache. This fixes spurious reboot hangs on TP-Link TL-WDR3600 and TL-WDR4300 with Zentel DRAM chips. This issue was fixed in the past, but switching to the reset-driver specific implementation removed the cache barrier which was previously implicitly added by reading back the register in question. Link: https://github.com/freifunk-gluon/gluon/issues/2904 Link: https://github.com/openwrt/openwrt/issues/13043 Link: https://dev.archive.openwrt.org/ticket/17839 Link: f8a7bfe1cb2c ("MIPS: ath79: fix system restart") Signed-off-by: David Bauer --- ...reset-ath79-read-back-reset-register.patch | 33 +++++++++++++++++++ ...reset-ath79-read-back-reset-register.patch | 33 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch create mode 100644 target/linux/ath79/patches-6.1/100-reset-ath79-read-back-reset-register.patch diff --git a/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch b/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch new file mode 100644 index 0000000000..7aa501514d --- /dev/null +++ b/target/linux/ath79/patches-5.15/100-reset-ath79-read-back-reset-register.patch @@ -0,0 +1,33 @@ +From 661edfc3dab943a67c8821353b63cc23057f7ce9 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Tue, 9 Jan 2024 20:48:46 +0100 +Subject: [PATCH] reset: ath79: read back reset register + +Read back the reset register in order to flush the cache. This fixes +spurious reboot hangs on TP-Link TL-WDR3600 and TL-WDR4300 with Zentel +DRAM chips. + +This issue was fixed in the past, but switching to the reset-driver +specific implementation removed the old fix. + +Link: https://github.com/freifunk-gluon/gluon/issues/2904 +Link: https://github.com/openwrt/openwrt/issues/13043 +Link: https://dev.archive.openwrt.org/ticket/17839 +Link: f8a7bfe1cb2c ("MIPS: ath79: fix system restart") + +Signed-off-by: David Bauer +--- + drivers/reset/reset-ath79.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/reset/reset-ath79.c ++++ b/drivers/reset/reset-ath79.c +@@ -37,6 +37,8 @@ static int ath79_reset_update(struct res + else + val &= ~BIT(id); + writel(val, ath79_reset->base); ++ /* Flush cache */ ++ readl(ath79_reset->base); + spin_unlock_irqrestore(&ath79_reset->lock, flags); + + return 0; diff --git a/target/linux/ath79/patches-6.1/100-reset-ath79-read-back-reset-register.patch b/target/linux/ath79/patches-6.1/100-reset-ath79-read-back-reset-register.patch new file mode 100644 index 0000000000..7aa501514d --- /dev/null +++ b/target/linux/ath79/patches-6.1/100-reset-ath79-read-back-reset-register.patch @@ -0,0 +1,33 @@ +From 661edfc3dab943a67c8821353b63cc23057f7ce9 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Tue, 9 Jan 2024 20:48:46 +0100 +Subject: [PATCH] reset: ath79: read back reset register + +Read back the reset register in order to flush the cache. This fixes +spurious reboot hangs on TP-Link TL-WDR3600 and TL-WDR4300 with Zentel +DRAM chips. + +This issue was fixed in the past, but switching to the reset-driver +specific implementation removed the old fix. + +Link: https://github.com/freifunk-gluon/gluon/issues/2904 +Link: https://github.com/openwrt/openwrt/issues/13043 +Link: https://dev.archive.openwrt.org/ticket/17839 +Link: f8a7bfe1cb2c ("MIPS: ath79: fix system restart") + +Signed-off-by: David Bauer +--- + drivers/reset/reset-ath79.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/reset/reset-ath79.c ++++ b/drivers/reset/reset-ath79.c +@@ -37,6 +37,8 @@ static int ath79_reset_update(struct res + else + val &= ~BIT(id); + writel(val, ath79_reset->base); ++ /* Flush cache */ ++ readl(ath79_reset->base); + spin_unlock_irqrestore(&ath79_reset->lock, flags); + + return 0; From 3df9322771cc932e5b82438634337fcca6cc97bc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 11 Jan 2024 09:14:59 +0100 Subject: [PATCH 091/222] hostapd: make ubus calls to wpa_supplicant asynchronous MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a deadlock issue where depending on the setup order, hostapd and wpa_supplicant could end up waiting for each other Reported-by: Michael-cy Lee (李峻宇) Signed-off-by: Felix Fietkau --- .../network/services/hostapd/files/hostapd.uc | 131 ++++++++++++++---- 1 file changed, 105 insertions(+), 26 deletions(-) diff --git a/package/network/services/hostapd/files/hostapd.uc b/package/network/services/hostapd/files/hostapd.uc index b85f523b35..0c89cd71cc 100644 --- a/package/network/services/hostapd/files/hostapd.uc +++ b/package/network/services/hostapd/files/hostapd.uc @@ -2,9 +2,10 @@ let libubus = require("ubus"); import { open, readfile } from "fs"; import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac, phy_open } from "common"; -let ubus = libubus.connect(); +let ubus = libubus.connect(null, 60); hostapd.data.config = {}; +hostapd.data.pending_config = {}; hostapd.data.file_fields = { vlan_file: true, @@ -122,17 +123,111 @@ function iface_config_macaddr_list(config) return macaddr_list; } -function iface_update_supplicant_macaddr(phy, config) +function __iface_pending_next(pending, state, ret, data) { - let macaddr_list = []; - for (let i = 0; i < length(config.bss); i++) - push(macaddr_list, config.bss[i].bssid); - ubus.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list }); + let config = pending.config; + let phydev = pending.phydev; + let phy = pending.phy; + + if (pending.defer) + pending.defer.abort(); + delete pending.defer; + switch (state) { + case "init": + let macaddr_list = []; + for (let i = 0; i < length(config.bss); i++) + push(macaddr_list, config.bss[i].bssid); + pending.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list }); + return "create_bss"; + case "create_bss": + let bss = config.bss[0]; + let err = wdev_create(phy, bss.ifname, { mode: "ap" }); + if (err) { + hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`); + return null; + } + + pending.call("wpa_supplicant", "phy_status", { phy: phy }); + return "check_phy"; + case "check_phy": + let phy_status = data; + if (phy_status && phy_status.state == "COMPLETED") { + if (iface_add(phy, config, phy_status)) + return "done"; + + hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`); + } + pending.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true }); + return "wpas_stopped"; + case "wpas_stopped": + if (!iface_add(phy, config)) + hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`); + pending.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false }); + return null; + case "done": + default: + delete hostapd.data.pending_config[phy]; + break; + } +} + +function iface_pending_next(ret, data) +{ + let pending = true; + let cfg = this; + + while (pending) { + this.next_state = __iface_pending_next(cfg, this.next_state, ret, data); + if (!this.next_state) { + __iface_pending_next(cfg, "done"); + return; + } + pending = !this.defer; + } +} + +function iface_pending_abort() +{ + this.next_state = "done"; + this.next(); +} + +function iface_pending_ubus_call(obj, method, arg) +{ + let ubus = hostapd.data.ubus; + let pending = this; + this.defer = ubus.defer(obj, method, arg, (ret, data) => { delete pending.defer; pending.next(ret, data) }); +} + +const iface_pending_proto = { + next: iface_pending_next, + call: iface_pending_ubus_call, + abort: iface_pending_abort, +}; + +function iface_pending_init(phydev, config) +{ + let phy = phydev.name; + + let pending = proto({ + next_state: "init", + phydev: phydev, + phy: phy, + config: config, + next: iface_pending_next, + }, iface_pending_proto); + + hostapd.data.pending_config[phy] = pending; + pending.next(); } function iface_restart(phydev, config, old_config) { let phy = phydev.name; + let pending = hostapd.data.pending_config[phy]; + + if (pending) + pending.abort(); hostapd.remove_iface(phy); iface_remove(old_config); @@ -150,26 +245,7 @@ function iface_restart(phydev, config, old_config) bss.bssid = phydev.macaddr_next(); } - iface_update_supplicant_macaddr(phy, config); - - let bss = config.bss[0]; - let err = wdev_create(phy, bss.ifname, { mode: "ap" }); - if (err) - hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`); - - let ubus = hostapd.data.ubus; - let phy_status = ubus.call("wpa_supplicant", "phy_status", { phy: phy }); - if (phy_status && phy_status.state == "COMPLETED") { - if (iface_add(phy, config, phy_status)) - return; - - hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`); - } - - ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true }); - if (!iface_add(phy, config)) - hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`); - ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false }); + iface_pending_init(phydev, config); } function array_to_obj(arr, key, start) @@ -274,6 +350,9 @@ function iface_reload_config(phydev, config, old_config) if (is_equal(old_config.bss, config.bss)) return true; + if (hostapd.data.pending_config[phy]) + return false; + if (!old_config.bss || !old_config.bss[0]) return false; From 2d4552a96c7e5d44f9caaf1367e2be9d3775afae Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Wed, 10 Jan 2024 17:21:01 +0100 Subject: [PATCH 092/222] ci: no longer require real name This goes in accordance with the Linux Kernel: > using a known identity (sorry, no anonymous contributions.) https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?id=HEAD#n442 Signed-off-by: Paul Spooren --- .github/workflows/formal.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/formal.yml b/.github/workflows/formal.yml index 8083c5832c..1532591dfc 100644 --- a/.github/workflows/formal.yml +++ b/.github/workflows/formal.yml @@ -37,14 +37,6 @@ jobs: RET=1 fi - author="$(git show -s --format=%aN $commit)" - if echo $author | grep -q '\S\+\s\+\S\+'; then - success "Author name ($author) seems ok" - else - err "Author name ($author) need to be your real name 'firstname lastname'" - RET=1 - fi - subject="$(git show -s --format=%s $commit)" if echo "$subject" | grep -q -e '^[0-9A-Za-z,+/_\.-]\+: ' -e '^Revert '; then success "Commit subject line seems ok ($subject)" From d5a1de17ade34abfa276b074e82f40a6a7b908de Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 22 Oct 2023 18:00:08 +0200 Subject: [PATCH 093/222] mac80211.sh: fix deadlock on configuring multiple PHYs simultaneously When hitting a timing window where ubus configuration calls are hitting hostapd and wpa_supplicant simultaneously, they can deadlock waiting for each other. Fix this by using a lock around the ubus calls. Signed-off-by: Felix Fietkau --- .../files/lib/netifd/wireless/mac80211.sh | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 6ff627b038..6572999fbc 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -19,6 +19,10 @@ wdev_tool() { ucode /usr/share/hostap/wdev.uc "$@" } +ubus_call() { + flock /var/run/hostapd.lock ubus call "$@" +} + drv_mac80211_init_device_config() { hostapd_common_add_device_config @@ -903,7 +907,7 @@ wpa_supplicant_set_config() { ubus wait_for wpa_supplicant } - local supplicant_res="$(ubus call wpa_supplicant config_set "$data")" + local supplicant_res="$(ubus_call wpa_supplicant config_set "$data")" ret="$?" [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED @@ -913,12 +917,12 @@ wpa_supplicant_set_config() { hostapd_set_config() { [ -n "$hostapd_ctrl" ] || { - ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null + ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null return 0; } ubus wait_for hostapd - local hostapd_res="$(ubus call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")" + local hostapd_res="$(ubus_call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")" ret="$?" [ "$ret" != 0 -o -z "$hostapd_res" ] && { wireless_setup_failed HOSTAPD_START_FAILED @@ -933,7 +937,7 @@ wpa_supplicant_start() { [ -n "$wpa_supp_init" ] || return 0 - ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null + ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null } mac80211_setup_supplicant() { @@ -1041,8 +1045,8 @@ mac80211_reset_config() { local phy="$1" hostapd_conf_file="/var/run/hostapd-$phy.conf" - ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null - ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null + ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null + ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null wdev_tool "$phy" set_config '{}' } From b7f9742da82fa9b122e8d63e48a9a5c0dec298f2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 14 Nov 2023 13:00:27 +0100 Subject: [PATCH 094/222] mac80211: rework interface setup, fix race condition Only tell netifd about vifs when the setup is complete and hostapd + wpa_supplicant have been notified Signed-off-by: Felix Fietkau --- .../files/lib/netifd/wireless/mac80211.sh | 159 ++++++++---------- .../network/services/hostapd/files/hostapd.sh | 7 +- 2 files changed, 74 insertions(+), 92 deletions(-) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 6572999fbc..cc7e143030 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -635,71 +635,6 @@ mac80211_set_ifname() { eval "ifname=\"$phy-$prefix\${idx_$prefix:-0}\"; idx_$prefix=\$((\${idx_$prefix:-0 } + 1))" } -mac80211_prepare_vif() { - json_select config - - json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file - - [ -n "$ifname" ] || { - local prefix; - - case "$mode" in - ap|sta|mesh) prefix=$mode;; - adhoc) prefix=ibss;; - monitor) prefix=mon;; - esac - - mac80211_set_ifname "$phy" "$prefix" - } - - append active_ifnames "$ifname" - set_default wds 0 - set_default powersave 0 - json_add_string _ifname "$ifname" - - default_macaddr= - if [ -z "$macaddr" ]; then - macaddr="$(mac80211_generate_mac $phy)" - macidx="$(($macidx + 1))" - default_macaddr=1 - elif [ "$macaddr" = 'random' ]; then - macaddr="$(macaddr_random)" - fi - json_add_string _macaddr "$macaddr" - json_add_string _default_macaddr "$default_macaddr" - json_select .. - - - [ "$mode" == "ap" ] && { - [ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname" - [ -z "$vlan_file" ] && hostapd_set_vlan "$ifname" - } - - json_select config - - # It is far easier to delete and create the desired interface - case "$mode" in - ap) - # Hostapd will handle recreating the interface and - # subsequent virtual APs belonging to the same PHY - if [ -n "$hostapd_ctrl" ]; then - type=bss - else - type=interface - fi - - mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return - - [ -n "$hostapd_ctrl" ] || { - ap_ifname="${ifname}" - hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" - } - ;; - esac - - json_select .. -} - mac80211_prepare_iw_htmode() { case "$htmode" in VHT20|HT20|HE20) iw_htmode=HT20;; @@ -842,17 +777,6 @@ mac80211_setup_monitor() { json_set_namespace "$prev" } -mac80211_set_vif_txpower() { - local name="$1" - - json_select config - json_get_var ifname _ifname - json_get_vars vif_txpower - json_select .. - - [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" -} - wpa_supplicant_init_config() { json_set_namespace wpa_supp prev @@ -957,19 +881,41 @@ mac80211_setup_supplicant() { return 0 } -mac80211_setup_vif() { - local name="$1" - local failed - +mac80211_prepare_vif() { json_select config - json_get_var ifname _ifname - json_get_var macaddr _macaddr - json_get_var default_macaddr _default_macaddr - json_get_vars mode wds powersave - set_default powersave 0 + json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file + local config_wpa_psk_file="$wpa_psk_file" + local config_vlan_file="$vlan_file" + + [ -n "$ifname" ] || { + local prefix; + + case "$mode" in + ap|sta|mesh) prefix=$mode;; + adhoc) prefix=ibss;; + monitor) prefix=mon;; + esac + + mac80211_set_ifname "$phy" "$prefix" + } + + append active_ifnames "$ifname" + + default_macaddr= + if [ -z "$macaddr" ]; then + macaddr="$(mac80211_generate_mac $phy)" + macidx="$(($macidx + 1))" + default_macaddr=1 + elif [ "$macaddr" = 'random' ]; then + macaddr="$(macaddr_random)" + fi + + local failed= set_default wds 0 + set_default powersave 0 + # It is far easier to delete and create the desired interface case "$mode" in mesh) json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING @@ -995,10 +941,48 @@ mac80211_setup_vif() { monitor) mac80211_setup_monitor ;; + ap) + # Hostapd will handle recreating the interface and + # subsequent virtual APs belonging to the same PHY + if [ -n "$hostapd_ctrl" ]; then + type=bss + else + type=interface + fi + + mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return + + [ -n "$hostapd_ctrl" ] || { + ap_ifname="${ifname}" + hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" + } + ;; esac + [ -n "$failed" ] || { + json_add_string _ifname "$ifname" + json_add_string _macaddr "$macaddr" + json_add_string _default_macaddr "$default_macaddr" + } + json_select .. - [ -n "$failed" ] || wireless_add_vif "$name" "$ifname" + + [ "$mode" == "ap" ] && { + [ -z "$config_wpa_psk_file" ] && hostapd_set_psk "$ifname" + [ -z "$config_vlan_file" ] && hostapd_set_vlan "$ifname" + } +} + +mac80211_setup_vif() { + local name="$1" + + json_select config + json_get_var ifname _ifname + json_get_vars vif_txpower + json_select .. + + [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" + [ -n "$ifname" ] && wireless_add_vif "$name" "$ifname" } get_freq() { @@ -1144,7 +1128,6 @@ drv_mac80211_setup() { mac80211_prepare_iw_htmode active_ifnames= for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif - for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy" [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy" @@ -1155,7 +1138,7 @@ drv_mac80211_setup() { wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames json_set_namespace "$prev" - for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower + for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif wireless_set_up } diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index 271c1f7bec..c0c39a9399 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -398,6 +398,7 @@ hostapd_set_vlan() { rm -f /var/run/hostapd-${ifname}.vlan for_each_vlan hostapd_set_vlan_file ${ifname} + touch /var/run/hostapd-${ifname}.vlan } hostapd_set_psk_file() { @@ -416,6 +417,7 @@ hostapd_set_psk() { rm -f /var/run/hostapd-${ifname}.psk for_each_station hostapd_set_psk_file ${ifname} + touch /var/run/hostapd-${ifname}.psk } append_iw_roaming_consortium() { @@ -688,10 +690,7 @@ hostapd_set_bss_options() { return 1 fi [ -z "$wpa_psk_file" ] && set_default wpa_psk_file /var/run/hostapd-$ifname.psk - [ -n "$wpa_psk_file" ] && { - [ -e "$wpa_psk_file" ] || touch "$wpa_psk_file" - append bss_conf "wpa_psk_file=$wpa_psk_file" "$N" - } + [ -n "$wpa_psk_file" ] && append bss_conf "wpa_psk_file=$wpa_psk_file" "$N" [ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N" set_default dynamic_vlan 0 From 5b8f188c0f0a18eecc7a5f4078b96338c3c282f2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 13 Jan 2024 11:19:07 +0100 Subject: [PATCH 095/222] Revert "mac80211: rework interface setup, fix race condition" This reverts commit b7f9742da82fa9b122e8d63e48a9a5c0dec298f2. There are several reports of regressions with this commit. Will be added back once I've figured out and fixed the cause Signed-off-by: Felix Fietkau --- .../files/lib/netifd/wireless/mac80211.sh | 159 ++++++++++-------- .../network/services/hostapd/files/hostapd.sh | 7 +- 2 files changed, 92 insertions(+), 74 deletions(-) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index cc7e143030..6572999fbc 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -635,6 +635,71 @@ mac80211_set_ifname() { eval "ifname=\"$phy-$prefix\${idx_$prefix:-0}\"; idx_$prefix=\$((\${idx_$prefix:-0 } + 1))" } +mac80211_prepare_vif() { + json_select config + + json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file + + [ -n "$ifname" ] || { + local prefix; + + case "$mode" in + ap|sta|mesh) prefix=$mode;; + adhoc) prefix=ibss;; + monitor) prefix=mon;; + esac + + mac80211_set_ifname "$phy" "$prefix" + } + + append active_ifnames "$ifname" + set_default wds 0 + set_default powersave 0 + json_add_string _ifname "$ifname" + + default_macaddr= + if [ -z "$macaddr" ]; then + macaddr="$(mac80211_generate_mac $phy)" + macidx="$(($macidx + 1))" + default_macaddr=1 + elif [ "$macaddr" = 'random' ]; then + macaddr="$(macaddr_random)" + fi + json_add_string _macaddr "$macaddr" + json_add_string _default_macaddr "$default_macaddr" + json_select .. + + + [ "$mode" == "ap" ] && { + [ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname" + [ -z "$vlan_file" ] && hostapd_set_vlan "$ifname" + } + + json_select config + + # It is far easier to delete and create the desired interface + case "$mode" in + ap) + # Hostapd will handle recreating the interface and + # subsequent virtual APs belonging to the same PHY + if [ -n "$hostapd_ctrl" ]; then + type=bss + else + type=interface + fi + + mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return + + [ -n "$hostapd_ctrl" ] || { + ap_ifname="${ifname}" + hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" + } + ;; + esac + + json_select .. +} + mac80211_prepare_iw_htmode() { case "$htmode" in VHT20|HT20|HE20) iw_htmode=HT20;; @@ -777,6 +842,17 @@ mac80211_setup_monitor() { json_set_namespace "$prev" } +mac80211_set_vif_txpower() { + local name="$1" + + json_select config + json_get_var ifname _ifname + json_get_vars vif_txpower + json_select .. + + [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" +} + wpa_supplicant_init_config() { json_set_namespace wpa_supp prev @@ -881,41 +957,19 @@ mac80211_setup_supplicant() { return 0 } -mac80211_prepare_vif() { +mac80211_setup_vif() { + local name="$1" + local failed + json_select config + json_get_var ifname _ifname + json_get_var macaddr _macaddr + json_get_var default_macaddr _default_macaddr + json_get_vars mode wds powersave - json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file - local config_wpa_psk_file="$wpa_psk_file" - local config_vlan_file="$vlan_file" - - [ -n "$ifname" ] || { - local prefix; - - case "$mode" in - ap|sta|mesh) prefix=$mode;; - adhoc) prefix=ibss;; - monitor) prefix=mon;; - esac - - mac80211_set_ifname "$phy" "$prefix" - } - - append active_ifnames "$ifname" - - default_macaddr= - if [ -z "$macaddr" ]; then - macaddr="$(mac80211_generate_mac $phy)" - macidx="$(($macidx + 1))" - default_macaddr=1 - elif [ "$macaddr" = 'random' ]; then - macaddr="$(macaddr_random)" - fi - - local failed= - set_default wds 0 set_default powersave 0 + set_default wds 0 - # It is far easier to delete and create the desired interface case "$mode" in mesh) json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING @@ -941,48 +995,10 @@ mac80211_prepare_vif() { monitor) mac80211_setup_monitor ;; - ap) - # Hostapd will handle recreating the interface and - # subsequent virtual APs belonging to the same PHY - if [ -n "$hostapd_ctrl" ]; then - type=bss - else - type=interface - fi - - mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return - - [ -n "$hostapd_ctrl" ] || { - ap_ifname="${ifname}" - hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}" - } - ;; esac - [ -n "$failed" ] || { - json_add_string _ifname "$ifname" - json_add_string _macaddr "$macaddr" - json_add_string _default_macaddr "$default_macaddr" - } - json_select .. - - [ "$mode" == "ap" ] && { - [ -z "$config_wpa_psk_file" ] && hostapd_set_psk "$ifname" - [ -z "$config_vlan_file" ] && hostapd_set_vlan "$ifname" - } -} - -mac80211_setup_vif() { - local name="$1" - - json_select config - json_get_var ifname _ifname - json_get_vars vif_txpower - json_select .. - - [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00" - [ -n "$ifname" ] && wireless_add_vif "$name" "$ifname" + [ -n "$failed" ] || wireless_add_vif "$name" "$ifname" } get_freq() { @@ -1128,6 +1144,7 @@ drv_mac80211_setup() { mac80211_prepare_iw_htmode active_ifnames= for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif + for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy" [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy" @@ -1138,7 +1155,7 @@ drv_mac80211_setup() { wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames json_set_namespace "$prev" - for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif + for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower wireless_set_up } diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index c0c39a9399..271c1f7bec 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -398,7 +398,6 @@ hostapd_set_vlan() { rm -f /var/run/hostapd-${ifname}.vlan for_each_vlan hostapd_set_vlan_file ${ifname} - touch /var/run/hostapd-${ifname}.vlan } hostapd_set_psk_file() { @@ -417,7 +416,6 @@ hostapd_set_psk() { rm -f /var/run/hostapd-${ifname}.psk for_each_station hostapd_set_psk_file ${ifname} - touch /var/run/hostapd-${ifname}.psk } append_iw_roaming_consortium() { @@ -690,7 +688,10 @@ hostapd_set_bss_options() { return 1 fi [ -z "$wpa_psk_file" ] && set_default wpa_psk_file /var/run/hostapd-$ifname.psk - [ -n "$wpa_psk_file" ] && append bss_conf "wpa_psk_file=$wpa_psk_file" "$N" + [ -n "$wpa_psk_file" ] && { + [ -e "$wpa_psk_file" ] || touch "$wpa_psk_file" + append bss_conf "wpa_psk_file=$wpa_psk_file" "$N" + } [ "$eapol_version" -ge "1" -a "$eapol_version" -le "2" ] && append bss_conf "eapol_version=$eapol_version" "$N" set_default dynamic_vlan 0 From 12c8bba73123dce47c1f8d0eddebefb485341704 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 13 Jan 2024 15:22:27 +0100 Subject: [PATCH 096/222] hostapd: fix an exception in hostapd.uc on interface add failure Signed-off-by: Felix Fietkau --- package/network/services/hostapd/files/hostapd.uc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/hostapd/files/hostapd.uc b/package/network/services/hostapd/files/hostapd.uc index 0c89cd71cc..5bffdff83f 100644 --- a/package/network/services/hostapd/files/hostapd.uc +++ b/package/network/services/hostapd/files/hostapd.uc @@ -128,6 +128,7 @@ function __iface_pending_next(pending, state, ret, data) let config = pending.config; let phydev = pending.phydev; let phy = pending.phy; + let bss = config.bss[0]; if (pending.defer) pending.defer.abort(); @@ -140,7 +141,6 @@ function __iface_pending_next(pending, state, ret, data) pending.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list }); return "create_bss"; case "create_bss": - let bss = config.bss[0]; let err = wdev_create(phy, bss.ifname, { mode: "ap" }); if (err) { hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`); From 912e5731279b046a9ab62e248d31e457a80c3e09 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 13 Jan 2024 16:11:41 +0100 Subject: [PATCH 097/222] hostapd: add back missing function for updating wpa_supplicant macaddr list Make the call deferred instead of blocking to avoid deadlock issues Fixes: 3df9322771cc ("hostapd: make ubus calls to wpa_supplicant asynchronous") Signed-off-by: Felix Fietkau --- package/network/services/hostapd/files/hostapd.uc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/package/network/services/hostapd/files/hostapd.uc b/package/network/services/hostapd/files/hostapd.uc index 5bffdff83f..dfddf8185b 100644 --- a/package/network/services/hostapd/files/hostapd.uc +++ b/package/network/services/hostapd/files/hostapd.uc @@ -123,6 +123,14 @@ function iface_config_macaddr_list(config) return macaddr_list; } +function iface_update_supplicant_macaddr(phy, config) +{ + let macaddr_list = []; + for (let i = 0; i < length(config.bss); i++) + push(macaddr_list, config.bss[i].bssid); + ubus.defer("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list }); +} + function __iface_pending_next(pending, state, ret, data) { let config = pending.config; From 92e0baba42b61e8c9819ef95cd5bc734f7ebc103 Mon Sep 17 00:00:00 2001 From: Sander Vanheule Date: Sun, 7 Jan 2024 15:51:36 +0100 Subject: [PATCH 098/222] realtek: rtl838x: join Netgear GSxxx flash layouts Flash layouts for GS108Tv3, GS110TPPv1, GS308Tv1 and GS310TPv1 are almost identical, except for the uimage header magic. Move the flash layout to the common dtsi, and only place the magic value in the device dts files. Signed-off-by: Sander Vanheule --- .../dts-5.15/rtl8380_netgear_gigabit.dtsi | 56 +++++++++++++++++ .../dts-5.15/rtl8380_netgear_gigabit_1xx.dtsi | 60 ------------------- .../dts-5.15/rtl8380_netgear_gigabit_3xx.dtsi | 60 ------------------- .../dts-5.15/rtl8380_netgear_gs108t-v3.dts | 6 +- .../dts-5.15/rtl8380_netgear_gs110tpp-v1.dts | 6 +- .../dts-5.15/rtl8380_netgear_gs308t-v1.dts | 6 +- .../dts-5.15/rtl8380_netgear_gs310tp-v1.dts | 6 +- 7 files changed, 76 insertions(+), 124 deletions(-) delete mode 100644 target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_1xx.dtsi delete mode 100644 target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_3xx.dtsi diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit.dtsi b/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit.dtsi index 5e587f278d..aca1a14774 100644 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit.dtsi +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit.dtsi @@ -58,6 +58,62 @@ }; }; +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x00e0000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0x00e0000 0x0010000>; + }; + + partition@f0000 { + label = "u-boot-env2"; + reg = <0x00f0000 0x0010000>; + }; + + partition@100000 { + label = "jffs"; + reg = <0x0100000 0x0100000>; + read-only; + }; + + partition@200000 { + label = "jffs2"; + reg = <0x0200000 0x0100000>; + read-only; + }; + + firmware: partition@300000 { + label = "firmware"; + compatible = "openwrt,uimage", "denx,uimage"; + reg = <0x0300000 0x0e80000>; + }; + + partition@1180000 { + label = "runtime2"; + reg = <0x1180000 0x0e80000>; + read-only; + }; + }; + }; +}; + &switch0 { ports { #address-cells = <1>; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_1xx.dtsi b/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_1xx.dtsi deleted file mode 100644 index fd44543bb4..0000000000 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_1xx.dtsi +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "rtl8380_netgear_gigabit.dtsi" - -&spi0 { - status = "okay"; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <50000000>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "u-boot"; - reg = <0x0000000 0x00e0000>; - read-only; - }; - - partition@e0000 { - label = "u-boot-env"; - reg = <0x00e0000 0x0010000>; - }; - - partition@f0000 { - label = "u-boot-env2"; - reg = <0x00f0000 0x0010000>; - }; - - partition@100000 { - label = "jffs"; - reg = <0x0100000 0x0100000>; - read-only; - }; - - partition@200000 { - label = "jffs2"; - reg = <0x0200000 0x0100000>; - read-only; - }; - - partition@300000 { - label = "firmware"; - compatible = "openwrt,uimage", "denx,uimage"; - openwrt,ih-magic = <0x4e474520>; - reg = <0x0300000 0x0e80000>; - }; - - partition@1180000 { - label = "runtime2"; - reg = <0x1180000 0x0e80000>; - read-only; - }; - }; - }; -}; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_3xx.dtsi b/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_3xx.dtsi deleted file mode 100644 index 0ade665c98..0000000000 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit_3xx.dtsi +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "rtl8380_netgear_gigabit.dtsi" - -&spi0 { - status = "okay"; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <50000000>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "u-boot"; - reg = <0x0000000 0x00e0000>; - read-only; - }; - - partition@e0000 { - label = "u-boot-env"; - reg = <0x00e0000 0x0010000>; - }; - - partition@f0000 { - label = "u-boot-env2"; - reg = <0x00f0000 0x0010000>; - }; - - partition@100000 { - label = "jffs"; - reg = <0x0100000 0x0100000>; - read-only; - }; - - partition@200000 { - label = "jffs2"; - reg = <0x0200000 0x0100000>; - read-only; - }; - - partition@300000 { - label = "firmware"; - compatible = "openwrt,uimage", "denx,uimage"; - openwrt,ih-magic = <0x4e474335>; - reg = <0x0300000 0x0e80000>; - }; - - partition@1180000 { - label = "runtime2"; - reg = <0x1180000 0x0e80000>; - read-only; - }; - }; - }; -}; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs108t-v3.dts b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs108t-v3.dts index e149834d44..c1d72b880b 100644 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs108t-v3.dts +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs108t-v3.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "rtl8380_netgear_gigabit_1xx.dtsi" +#include "rtl8380_netgear_gigabit.dtsi" #include @@ -33,3 +33,7 @@ }; }; }; + +&firmware { + openwrt,ih-magic = <0x4e474520>; +}; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tpp-v1.dts b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tpp-v1.dts index b61af62ea5..599b2e3b51 100644 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tpp-v1.dts +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tpp-v1.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "rtl8380_netgear_gigabit_1xx.dtsi" +#include "rtl8380_netgear_gigabit.dtsi" #include / { @@ -40,6 +40,10 @@ }; }; +&firmware { + openwrt,ih-magic = <0x4e474520>; +}; + &uart1 { status = "okay"; }; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs308t-v1.dts b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs308t-v1.dts index cd69e80186..5cf3ca0c81 100644 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs308t-v1.dts +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs308t-v1.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "rtl8380_netgear_gigabit_3xx.dtsi" +#include "rtl8380_netgear_gigabit.dtsi" #include @@ -33,3 +33,7 @@ }; }; }; + +&firmware { + openwrt,ih-magic = <0x4e474335>; +}; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs310tp-v1.dts b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs310tp-v1.dts index dacd504ac4..a6f7181c11 100644 --- a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs310tp-v1.dts +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs310tp-v1.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include "rtl8380_netgear_gigabit_3xx.dtsi" +#include "rtl8380_netgear_gigabit.dtsi" / { compatible = "netgear,gs310tp-v1", "realtek,rtl838x-soc"; @@ -8,6 +8,10 @@ }; +&firmware { + openwrt,ih-magic = <0x4e474335>; +}; + &uart1 { status = "okay"; }; From 735efbfb7c1d2b29bb53d833a9ddd16cc29355e6 Mon Sep 17 00:00:00 2001 From: Jacob Potter Date: Sat, 23 Dec 2023 21:37:54 -0500 Subject: [PATCH 099/222] realtek: rtl838x: add Netgear GS110TUP v1 support The GS110TUP v1 is a managed switch similar to the GS110TPP v1, but with port 10 as SFP instead of RJ-45 and a total budget of 240 watts. Ports 1-4 support 60-watt 802.3bt PoE and ports 5-8 support 30-watt 802.3at. The flash layout of the two switches are identical, and the U-Boot configurations are the same except for having a different magic number, so installation can be done via the same U-Boot method. The following command will be needed to enable the port LEDs as per https://forum.openwrt.org/t/72510/51 : fw_setenv bootcmd "rtk network on; boota" Additionally, port 9 (1000base-T from a separate QSGMII PHY) does not function without this. Port 10 was not tested as no SFP module was available. Signed-off-by: Jacob Potter [rebase on merged flash layout] Signed-off-by: Sander Vanheule --- .../realtek/base-files/etc/board.d/02_network | 3 + .../dts-5.15/rtl8380_netgear_gs110tup-v1.dts | 61 +++++++++++++++++++ target/linux/realtek/image/rtl838x.mk | 26 ++++++++ 3 files changed, 90 insertions(+) create mode 100644 target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tup-v1.dts diff --git a/target/linux/realtek/base-files/etc/board.d/02_network b/target/linux/realtek/base-files/etc/board.d/02_network index 4a5fe7666c..fb9c28d794 100644 --- a/target/linux/realtek/base-files/etc/board.d/02_network +++ b/target/linux/realtek/base-files/etc/board.d/02_network @@ -91,6 +91,9 @@ hpe,1920-8g-poe-180w) netgear,gs110tpp-v1) ucidef_set_poe 130 "$lan_list" "lan9 lan10" ;; +netgear,gs110tup-v1) + ucidef_set_poe 240 "$lan_list" "lan9 lan10" + ;; netgear,gs310tp-v1) ucidef_set_poe 55 "$lan_list" "lan9 lan10" ;; diff --git a/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tup-v1.dts b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tup-v1.dts new file mode 100644 index 0000000000..76653fa210 --- /dev/null +++ b/target/linux/realtek/dts-5.15/rtl8380_netgear_gs110tup-v1.dts @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_netgear_gigabit.dtsi" +#include + +/ { + compatible = "netgear,gs110tup-v1", "realtek,rtl838x-soc"; + model = "Netgear GS110TUP v1"; + + aliases { + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_green; + led-upgrade = &led_status_blue; + }; + + leds { + compatible = "gpio-leds"; + + led_status_red: led-0 { + label = "red:status"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 31 GPIO_ACTIVE_LOW>; + }; + + led_status_green: led-1 { + label = "green:status"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 32 GPIO_ACTIVE_LOW>; + }; + + led_status_blue: led-2 { + label = "blue:status"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 34 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&firmware { + openwrt,ih-magic = <0x4e474720>; +}; + +&uart1 { + status = "okay"; +}; + +&mdio { + EXTERNAL_PHY(16) + EXTERNAL_PHY(24) +}; + +&switch0 { + ports { + SWITCH_PORT(16, 9, qsgmii) + SWITCH_SFP_PORT(24, 10, rgmii-id) + }; +}; diff --git a/target/linux/realtek/image/rtl838x.mk b/target/linux/realtek/image/rtl838x.mk index 9a9a310713..60249ff2fd 100644 --- a/target/linux/realtek/image/rtl838x.mk +++ b/target/linux/realtek/image/rtl838x.mk @@ -171,6 +171,24 @@ define Device/netgear_nge DEVICE_VENDOR := NETGEAR endef +# "NGG" refers to the uImage magic +define Device/netgear_ngg + KERNEL := \ + kernel-bin | \ + append-dtb | \ + lzma | \ + uImage lzma + KERNEL_INITRAMFS := \ + kernel-bin | \ + append-dtb | \ + lzma | \ + uImage lzma + SOC := rtl8380 + IMAGE_SIZE := 14848k + UIMAGE_MAGIC := 0x4e474720 + DEVICE_VENDOR := NETGEAR +endef + define Device/netgear_gs108t-v3 $(Device/netgear_nge) DEVICE_MODEL := GS108T @@ -186,6 +204,14 @@ define Device/netgear_gs110tpp-v1 endef TARGET_DEVICES += netgear_gs110tpp-v1 +define Device/netgear_gs110tup-v1 + $(Device/netgear_ngg) + DEVICE_MODEL := GS110TUP + DEVICE_VARIANT := v1 + DEVICE_PACKAGES += realtek-poe +endef +TARGET_DEVICES += netgear_gs110tup-v1 + define Device/netgear_gs308t-v1 $(Device/netgear_nge) DEVICE_MODEL := GS308T From 7c9010fd3ee75eeaa344e2ae124f480c0ca5ff78 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Sun, 17 Dec 2023 23:15:08 +0800 Subject: [PATCH 100/222] mediatek: mt7622: refresh kernel config Refresh kernel config with 'make kernel_oldconfig'. Signed-off-by: Chukun Pan --- target/linux/mediatek/mt7622/config-5.15 | 28 ++++++------------------ target/linux/mediatek/mt7622/config-6.1 | 4 ++-- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 index 18f972e949..7bca33c0ae 100644 --- a/target/linux/mediatek/mt7622/config-5.15 +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -8,7 +8,6 @@ CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y CONFIG_ARCH_MMAP_RND_BITS=18 CONFIG_ARCH_MMAP_RND_BITS_MAX=24 CONFIG_ARCH_MMAP_RND_BITS_MIN=18 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 CONFIG_ARCH_PROC_KCORE_TEXT=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -17,10 +16,8 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARCH_WANTS_NO_INSTR=y CONFIG_ARM64=y CONFIG_ARM64_4K_PAGES=y -# CONFIG_ARM64_CNP is not set CONFIG_ARM64_CRYPTO=y CONFIG_ARM64_ERRATUM_843419=y -CONFIG_ARM64_ERRATUM_845719=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PA_BITS=48 @@ -28,7 +25,6 @@ CONFIG_ARM64_PA_BITS_48=y CONFIG_ARM64_TAGGED_ADDR_ABI=y CONFIG_ARM64_VA_BITS=39 CONFIG_ARM64_VA_BITS_39=y -# CONFIG_ARMV8_DEPRECATED is not set CONFIG_ARM_AMBA=y CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y @@ -46,9 +42,9 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_SD=y CONFIG_BLK_MQ_PCI=y CONFIG_BLK_PM=y -CONFIG_BLOCK_COMPAT=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y @@ -74,19 +70,7 @@ CONFIG_COMMON_CLK_MT7622_HIFSYS=y # CONFIG_COMMON_CLK_MT7988 is not set # CONFIG_COMMON_CLK_MT8173 is not set # CONFIG_COMMON_CLK_MT8183 is not set -# CONFIG_COMMON_CLK_MT8183_AUDIOSYS is not set -# CONFIG_COMMON_CLK_MT8183_CAMSYS is not set -# CONFIG_COMMON_CLK_MT8183_IMGSYS is not set -# CONFIG_COMMON_CLK_MT8183_IPU_ADL is not set -# CONFIG_COMMON_CLK_MT8183_IPU_CONN is not set -# CONFIG_COMMON_CLK_MT8183_IPU_CORE0 is not set -# CONFIG_COMMON_CLK_MT8183_IPU_CORE1 is not set -# CONFIG_COMMON_CLK_MT8183_MFGCFG is not set -# CONFIG_COMMON_CLK_MT8183_MMSYS is not set -# CONFIG_COMMON_CLK_MT8183_VDECSYS is not set -# CONFIG_COMMON_CLK_MT8183_VENCSYS is not set # CONFIG_COMMON_CLK_MT8516 is not set -# CONFIG_COMMON_CLK_MT8516_AUDSYS is not set CONFIG_COMPAT_32BIT_TIME=y CONFIG_CONFIGFS_FS=y CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 @@ -144,7 +128,6 @@ CONFIG_DIMLIB=y CONFIG_DMADEVICES=y CONFIG_DMA_DIRECT_REMAP=y CONFIG_DMA_ENGINE=y -CONFIG_DMA_ENGINE_RAID=y CONFIG_DMA_OF=y CONFIG_DMA_REMAP=y CONFIG_DMA_VIRTUAL_CHANNELS=y @@ -254,8 +237,8 @@ CONFIG_MTD_SPLIT_FIRMWARE=y CONFIG_MTD_SPLIT_FIT_FW=y CONFIG_MTD_UBI=y CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_FASTMAP=y CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_FASTMAP=y CONFIG_MTD_UBI_WL_THRESHOLD=4096 # CONFIG_MTK_CMDQ is not set # CONFIG_MTK_CQDMA is not set @@ -288,6 +271,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=2 CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_NVMEM_MTK_EFUSE=y CONFIG_NVMEM_SYSFS=y CONFIG_OF=y @@ -301,8 +285,9 @@ CONFIG_OF_KOBJ=y CONFIG_OF_MDIO=y CONFIG_OF_OVERLAY=y CONFIG_OF_RESOLVE=y -CONFIG_OLD_SIGSUSPEND3=y CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_POOL_STATS=y CONFIG_PARTITION_PERCPU=y CONFIG_PCI=y CONFIG_PCIEAER=y @@ -319,6 +304,7 @@ CONFIG_PCI_DOMAINS=y CONFIG_PCI_DOMAINS_GENERIC=y CONFIG_PCI_MSI=y CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCS_MTK_LYNXI=y CONFIG_PERF_EVENTS=y CONFIG_PGTABLE_LEVELS=3 CONFIG_PHYLIB=y @@ -420,7 +406,6 @@ CONFIG_SWCONFIG=y CONFIG_SWIOTLB=y CONFIG_SWPHY=y CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYSVIPC_COMPAT=y CONFIG_THERMAL=y CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 @@ -435,6 +420,7 @@ CONFIG_THREAD_INFO_IN_TASK=y CONFIG_TICK_CPU_ACCOUNTING=y CONFIG_TIMER_OF=y CONFIG_TIMER_PROBE=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y CONFIG_TREE_RCU=y CONFIG_TREE_SRCU=y CONFIG_UBIFS_FS=y diff --git a/target/linux/mediatek/mt7622/config-6.1 b/target/linux/mediatek/mt7622/config-6.1 index 6272a3bac6..89260f78ee 100644 --- a/target/linux/mediatek/mt7622/config-6.1 +++ b/target/linux/mediatek/mt7622/config-6.1 @@ -4,7 +4,6 @@ CONFIG_AQUANTIA_PHY=y CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_ARCH_FORCE_MAX_ORDER=11 CONFIG_ARCH_KEEP_MEMBLOCK=y CONFIG_ARCH_MEDIATEK=y CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y @@ -104,6 +103,7 @@ CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_RMAP=y CONFIG_CPU_THERMAL=y CONFIG_CRC16=y +CONFIG_CRC_CCITT=y CONFIG_CRYPTO_AES_ARM64=y CONFIG_CRYPTO_AES_ARM64_CE=y CONFIG_CRYPTO_AES_ARM64_CE_BLK=y @@ -155,7 +155,6 @@ CONFIG_FIT_PARTITION=y CONFIG_FIXED_PHY=y CONFIG_FIX_EARLYCON_MEM=y CONFIG_FRAME_POINTER=y -CONFIG_FRAME_WARN=2048 CONFIG_FS_IOMAP=y CONFIG_FS_MBCACHE=y CONFIG_FWNODE_MDIO=y @@ -291,6 +290,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=2 CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_NVMEM_MTK_EFUSE=y CONFIG_NVMEM_SYSFS=y CONFIG_OF=y From 3a3a4d3bd32969f54712d7494d77b2fbc0e81ab7 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Mon, 18 Dec 2023 23:15:20 +0800 Subject: [PATCH 101/222] mediatek: filogic: refresh kernel config Refresh kernel config with 'make kernel_oldconfig'. Also disable the useless rtl8367s gsw driver. Signed-off-by: Chukun Pan --- target/linux/mediatek/filogic/config-5.15 | 3 ++- target/linux/mediatek/filogic/config-6.1 | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index 1499f79b9a..8ba0b0efe8 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -268,6 +268,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=4 CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_NVMEM_MTK_EFUSE=y CONFIG_NVMEM_SYSFS=y CONFIG_OF=y @@ -370,7 +371,7 @@ CONFIG_RPS=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_MT7622=y CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RTL8367S_GSW=y +# CONFIG_RTL8367S_GSW is not set CONFIG_RWSEM_SPIN_ON_OWNER=y CONFIG_SCHED_MC=y CONFIG_SCSI=y diff --git a/target/linux/mediatek/filogic/config-6.1 b/target/linux/mediatek/filogic/config-6.1 index 9473967d00..1687aadbc1 100644 --- a/target/linux/mediatek/filogic/config-6.1 +++ b/target/linux/mediatek/filogic/config-6.1 @@ -95,6 +95,7 @@ CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_RMAP=y CONFIG_CPU_THERMAL=y CONFIG_CRC16=y +CONFIG_CRC_CCITT=y CONFIG_CRYPTO_AES_ARM64=y CONFIG_CRYPTO_AES_ARM64_CE=y CONFIG_CRYPTO_AES_ARM64_CE_BLK=y @@ -286,6 +287,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=4 CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y CONFIG_NVMEM_MTK_EFUSE=y CONFIG_NVMEM_SYSFS=y CONFIG_OF=y From d55517796005cf63b753cf6e98a3a3a730bcec6e Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Tue, 19 Dec 2023 23:15:38 +0800 Subject: [PATCH 102/222] mediatek: Cetron CT3003: move mac address setup to dts It looks like we can put the mac address setting into the device tree. Compile test only. Signed-off-by: Chukun Pan --- target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts | 7 ++++++- .../mediatek/filogic/base-files/etc/board.d/02_network | 5 ----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts b/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts index 4949cdb3d7..281c96e275 100644 --- a/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts +++ b/target/linux/mediatek/dts/mt7981b-cetron-ct3003.dts @@ -12,6 +12,7 @@ aliases { serial0 = &uart0; + label-mac-device = &gmac0; led-boot = &led_status_red; led-failsafe = &led_status_red; led-running = &led_status_green; @@ -65,7 +66,7 @@ reg = <0>; phy-mode = "2500base-x"; - nvmem-cells = <&macaddr_art_0>; + nvmem-cells = <&macaddr_art_0 0>; nvmem-cell-names = "mac-address"; fixed-link { @@ -134,7 +135,9 @@ #size-cells = <1>; macaddr_art_0: macaddr@0 { + compatible = "mac-base"; reg = <0x0 0x6>; + #nvmem-cell-cells = <1>; }; }; }; @@ -192,6 +195,8 @@ port@3 { reg = <3>; label = "wan"; + nvmem-cells = <&macaddr_art_0 3>; + nvmem-cell-names = "mac-address"; }; port@6 { diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network index 2a6a97919d..b86c376d74 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network @@ -111,11 +111,6 @@ mediatek_setup_macs() bananapi,bpi-r3) wan_mac=$(macaddr_add $(cat /sys/class/net/eth0/address) 1) ;; - cetron,ct3003) - lan_mac=$(mtd_get_mac_binary "art" 0) - wan_mac=$(macaddr_add "$lan_mac" 3) - label_mac=$lan_mac - ;; cmcc,rax3000m) case "$(cmdline_get_var root)" in /dev/mmc*) From 99bc8a9770b238fa7c8d7ecbd9a1d34edd677d47 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Wed, 20 Dec 2023 23:15:31 +0800 Subject: [PATCH 103/222] mediatek: Cudy WR3000: simplify mac address setup The mac address of the network port under the switch is the same as the corresponding gmac by default, so there is no need to repeat the setting. Compile test only. Signed-off-by: Chukun Pan --- .../linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts b/target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts index e2fa8bf5d3..f4ba629525 100644 --- a/target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts +++ b/target/linux/mediatek/dts/mt7981b-cudy-wr3000-v1.dts @@ -10,7 +10,7 @@ aliases { ethernet0 = &gmac0; - label-mac-device = &lan1; + label-mac-device = &gmac0; led-boot = &led_status; led-failsafe = &led_status; led-running = &led_status; @@ -238,28 +238,19 @@ nvmem-cells = <&macaddr_bdinfo_de00 1>; }; - lan1: port@1 { + port@1 { reg = <1>; label = "lan1"; - - nvmem-cell-names = "mac-address"; - nvmem-cells = <&macaddr_bdinfo_de00 0>; }; port@2 { reg = <2>; label = "lan2"; - - nvmem-cell-names = "mac-address"; - nvmem-cells = <&macaddr_bdinfo_de00 0>; }; port@3 { reg = <3>; label = "lan3"; - - nvmem-cell-names = "mac-address"; - nvmem-cells = <&macaddr_bdinfo_de00 0>; }; port@6 { From cfee7fa36682be3476b5b27e8affad99c8753934 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Tue, 9 Jan 2024 23:15:27 +0800 Subject: [PATCH 104/222] mediatek: YunCore AX835: convert to nvmem-layout The nvmem-cells is deprecated. Also simplify mac address settings. Fixes: b4086f4 ("mediatek: add support for YunCore AX835") Signed-off-by: Chukun Pan --- .../mediatek/dts/mt7981b-yuncore-ax835.dts | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts b/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts index b3ca5bfa2c..37b381d984 100644 --- a/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts +++ b/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts @@ -84,6 +84,9 @@ reg = <0>; phy-mode = "2500base-x"; + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_2a>; + fixed-link { speed = <2500>; full-duplex; @@ -172,24 +175,26 @@ reg = <0x50000 0x10000>; read-only; - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; - eeprom_factory: eeprom@0 { - reg = <0x0 0x1000>; - }; + eeprom_factory: eeprom@0 { + reg = <0x0 0x1000>; + }; - macaddr_factory_4: macaddr@4 { - reg = <0x4 0x6>; - }; + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; + }; - macaddr_factory_24: macaddr@24 { - reg = <0x24 0x6>; - }; + macaddr_factory_24: macaddr@24 { + reg = <0x24 0x6>; + }; - macaddr_factory_2a: macaddr@2a { - reg = <0x2a 0x6>; + macaddr_factory_2a: macaddr@2a { + reg = <0x2a 0x6>; + }; }; }; @@ -213,20 +218,14 @@ #address-cells = <1>; #size-cells = <0>; - lan: port@3 { + port@3 { reg = <3>; label = "lan"; - - nvmem-cell-names = "mac-address"; - nvmem-cells = <&macaddr_factory_2a 0>; }; port@4 { reg = <4>; label = "wan"; - - nvmem-cell-names = "mac-address"; - nvmem-cells = <&macaddr_factory_2a 0>; }; port@6 { From 8632f6184b156aeab16c82a63b82204d0156c83b Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Thu, 21 Dec 2023 23:16:08 +0800 Subject: [PATCH 105/222] mediatek: fixes typo for spi properties Same as commit 3674689, correct 'buswidth' to 'bus-width'. Signed-off-by: Chukun Pan --- target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts | 4 ++-- target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts | 4 ++-- target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts | 4 ++-- target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts b/target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts index 520b8494ee..8f4dc23fb4 100644 --- a/target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts +++ b/target/linux/mediatek/dts/mt7981b-confiabits-mt7981.dts @@ -211,8 +211,8 @@ spi-cal-addrlen = <5>; spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; mediatek,nmbm; mediatek,bmt-max-ratio = <1>; mediatek,bmt-max-reserved-blocks = <64>; diff --git a/target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts b/target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts index 1dc4d380b8..dfe44843b9 100644 --- a/target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts +++ b/target/linux/mediatek/dts/mt7981b-routerich-ax3000.dts @@ -160,8 +160,8 @@ reg = <0>; spi-max-frequency = <52000000>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; spi-cal-enable; spi-cal-mode = "read-data"; diff --git a/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts b/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts index 37b381d984..4e6e834276 100644 --- a/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts +++ b/target/linux/mediatek/dts/mt7981b-yuncore-ax835.dts @@ -150,8 +150,8 @@ reg = <0>; spi-max-frequency = <52000000>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; partitions { compatible = "fixed-partitions"; diff --git a/target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts b/target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts index 15cd69aaae..e2acb63771 100644 --- a/target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts +++ b/target/linux/mediatek/dts/mt7986a-asus-rt-ax59u.dts @@ -213,8 +213,8 @@ reg = <0>; spi-max-frequency = <20000000>; - spi-tx-buswidth = <4>; - spi-rx-buswidth = <4>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; partitions: partitions { compatible = "fixed-partitions"; From 622340f6c10a492c03e6d0c0ee004da1c43270bc Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Sat, 23 Dec 2023 23:16:15 +0800 Subject: [PATCH 106/222] mediatek: TOTOLINK A8000RU: add missing usb3 package This device has a usb 3.0 port, so add it. Signed-off-by: Chukun Pan --- target/linux/mediatek/image/mt7622.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/mediatek/image/mt7622.mk b/target/linux/mediatek/image/mt7622.mk index e393b8433e..7df5eade82 100644 --- a/target/linux/mediatek/image/mt7622.mk +++ b/target/linux/mediatek/image/mt7622.mk @@ -352,7 +352,7 @@ define Device/totolink_a8000ru DEVICE_MODEL := A8000RU DEVICE_DTS := mt7622-totolink-a8000ru DEVICE_DTS_DIR := ../dts - DEVICE_PACKAGES := kmod-mt7615-firmware swconfig + DEVICE_PACKAGES := kmod-mt7615-firmware kmod-usb3 swconfig IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef TARGET_DEVICES += totolink_a8000ru From ba9c1b131432b6afbe96521eba949ba53df3ee95 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Mon, 15 Jan 2024 16:37:11 +0100 Subject: [PATCH 107/222] fstools: update to Git HEAD (2024-01-15) 97bacb70138a libfstools: query drivers by priority 41e619ed1352 block: recognize /dev/fit* block devices bc3b8cdd3de3 libfstools: add uImage.FIT fitblk driver 846302d09246 libfstools: partname: raise priority to 25 1a5695925ecf mount_root: add support for passing args to mount_root start 1858a492c300 mount_root: permit to pass mount options for rootfs mount Signed-off-by: Christian Marangi --- package/system/fstools/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/system/fstools/Makefile b/package/system/fstools/Makefile index 7e3779e61e..6198009ac0 100644 --- a/package/system/fstools/Makefile +++ b/package/system/fstools/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/fstools.git -PKG_MIRROR_HASH:=e9953b038a2c2ed2c4783b66d1c0d0cea0deab2f2bfa6712929243e3197c3bdd -PKG_SOURCE_DATE:=2023-05-28 -PKG_SOURCE_VERSION:=3a07943e1e60699ba952e605f0cf23c82de356cb +PKG_MIRROR_HASH:=02d0bc1f3a2d731756668108e3dcd305bf1be9f5b947b508ba42ea4f754cbc8b +PKG_SOURCE_DATE:=2024-01-15 +PKG_SOURCE_VERSION:=1858a492c300a0066a91f8096a858231c3cbd246 CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 From 0b23d3608c1f01f9dc4d042b0217ee0291c0fd70 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sat, 16 Sep 2023 17:16:04 +0200 Subject: [PATCH 108/222] base-files: add support for rootfs mount options from cmdline Add support for configuring rootfs mount options from cmdline. Rootfs mount options can be passed by declaring in the kernel cmdline as much options as needed prefixed with "rootfs_mount_options." An example usage is with rootfs with F2FS filesystem to enable compress_algorithm to reduce flash wear by compressing the files before writing to flash. Example usage: "... rootfs_mount_options.compress_algorithm=zstd ..." To pass multiple options: "... rootfs_mount_options.compress_algorithm=zstd rootfs_mount_options.noinline_data ..." Signed-off-by: Christian Marangi --- .../files/lib/preinit/80_mount_root | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/package/base-files/files/lib/preinit/80_mount_root b/package/base-files/files/lib/preinit/80_mount_root index c3816c2cbf..fa6abcde57 100644 --- a/package/base-files/files/lib/preinit/80_mount_root +++ b/package/base-files/files/lib/preinit/80_mount_root @@ -14,8 +14,27 @@ missing_lines() { IFS="$oIFS" } +# Rootfs mount options can be passed by declaring in the kernel +# cmdline as much options as needed prefixed with "rootfs_mount_options." +# +# Example: +# rootfs_mount_options.compress_algorithm=zstd rootfs_mount_options.noinline_data +# +compose_rootfs_mount_options() { + local mount_options + local cmdlinevar + + for cmdlinevar in $(cat /proc/cmdline); do + if [ "$cmdlinevar" != "${cmdlinevar#rootfs_mount_options\.}" ]; then + append mount_options "${cmdlinevar#rootfs_mount_options\.}" + fi + done + + echo $mount_options +} + do_mount_root() { - mount_root + mount_root start "$(compose_rootfs_mount_options)" boot_run_hook preinit_mount_root [ -f /sysupgrade.tgz -o -f /tmp/sysupgrade.tar ] && { echo "- config restore -" From 84ec8c41e7acc0bfc320d8562330ea14c704f93c Mon Sep 17 00:00:00 2001 From: a-gave Date: Thu, 11 Jan 2024 11:33:21 +0100 Subject: [PATCH 109/222] imagebuilder: copy from buildroot only target/linux/generic and target/linux/ to reduce the size This reduces the size of a single imagebuilder by about 40MB In example for the target ath79 it would be the sum of generic and directories, so about 16MB, instead of the whole size of the target directory, about 53MB: 11M target/linux/generic/ 3.9M target/linux/ath79/ Signed-off-by: a-gave --- target/imagebuilder/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/target/imagebuilder/Makefile b/target/imagebuilder/Makefile index 3bbadc7204..c3b6c9c10c 100644 --- a/target/imagebuilder/Makefile +++ b/target/imagebuilder/Makefile @@ -27,7 +27,7 @@ all: compile $(BIN_DIR)/$(IB_NAME).tar.xz: clean rm -rf $(PKG_BUILD_DIR) mkdir -p $(IB_KDIR) $(IB_LDIR) $(PKG_BUILD_DIR)/staging_dir/host/lib \ - $(PKG_BUILD_DIR)/target $(PKG_BUILD_DIR)/scripts $(IB_DTSDIR) + $(PKG_BUILD_DIR)/target/linux $(PKG_BUILD_DIR)/scripts $(IB_DTSDIR) -cp $(TOPDIR)/.config $(PKG_BUILD_DIR)/.config $(SED) 's/^CONFIG_BINARY_FOLDER=.*/# CONFIG_BINARY_FOLDER is not set/' $(PKG_BUILD_DIR)/.config $(SED) 's/^CONFIG_DOWNLOAD_FOLDER=.*/# CONFIG_DOWNLOAD_FOLDER is not set/' $(PKG_BUILD_DIR)/.config @@ -78,7 +78,9 @@ ifneq ($(CONFIG_SIGNATURE_CHECK),) $(CP) -L $(STAGING_DIR_ROOT)/usr/sbin/opkg-key $(PKG_BUILD_DIR)/scripts/ endif - $(CP) -L $(TOPDIR)/target/linux $(PKG_BUILD_DIR)/target/ + $(CP) -L $(TOPDIR)/target/linux/Makefile $(PKG_BUILD_DIR)/target/linux + $(CP) -L $(TOPDIR)/target/linux/generic $(PKG_BUILD_DIR)/target/linux + $(CP) -L $(TOPDIR)/target/linux/$(BOARD) $(PKG_BUILD_DIR)/target/linux if [ -d $(TOPDIR)/staging_dir/host/lib/grub ]; then \ $(CP) $(TOPDIR)/staging_dir/host/lib/grub/ $(PKG_BUILD_DIR)/staging_dir/host/lib; \ fi From 45f86a12787d6d0deadcaedd67fed8bbb541743b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Owoc?= Date: Sat, 6 Jan 2024 16:46:30 +0100 Subject: [PATCH 110/222] ipq807x: fix whitespace usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace with tab and remove unused whitespaces Signed-off-by: Paweł Owoc --- package/firmware/ipq-wifi/Makefile | 2 +- .../arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts | 4 ++-- target/linux/qualcommax/image/ipq807x.mk | 10 +++++----- .../ipq807x/base-files/etc/board.d/02_network | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile index fe249807d4..5806654ecf 100644 --- a/package/firmware/ipq-wifi/Makefile +++ b/package/firmware/ipq-wifi/Makefile @@ -34,7 +34,7 @@ ALLWIFIBOARDS:= \ dynalink_dl-wrx36 \ edgecore_eap102 \ edimax_cax1800 \ - linksys_mx4200 \ + linksys_mx4200 \ netgear_rax120v2 \ netgear_wax218 \ netgear_wax620 \ diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts index 4bc1b8cc28..7946e5c54d 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-mx4200v1.dts @@ -10,10 +10,10 @@ model = "Linksys MX4200v1"; compatible = "linksys,mx4200v1", "qcom,ipq8074"; }; - + &wifi { status = "okay"; - qcom,ath11k-calibration-variant = "Linksys-MX4200v1"; + qcom,ath11k-calibration-variant = "Linksys-MX4200v1"; qcom,ath11k-fw-memory-mode = <1>; }; diff --git a/target/linux/qualcommax/image/ipq807x.mk b/target/linux/qualcommax/image/ipq807x.mk index 5beff11309..f513d7f25c 100644 --- a/target/linux/qualcommax/image/ipq807x.mk +++ b/target/linux/qualcommax/image/ipq807x.mk @@ -119,24 +119,24 @@ define Device/linksys_mx4200v1 $(call Device/FitImage) $(call Device/UbiFit) DEVICE_VENDOR := Linksys - DEVICE_MODEL := MX4200 - DEVICE_VARIANT := v1 + DEVICE_MODEL := MX4200 + DEVICE_VARIANT := v1 BLOCKSIZE := 128k PAGESIZE := 2048 - KERNEL_SIZE := 6144k + KERNEL_SIZE := 6144k IMAGE_SIZE := 147456k NAND_SIZE := 512m KERNEL_IN_UBI := SOC := ipq8174 IMAGES += factory.bin - IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | linksys-image type=MX4200 + IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | linksys-image type=MX4200 DEVICE_PACKAGES := kmod-leds-pca963x ipq-wifi-linksys_mx4200 kmod-bluetooth endef TARGET_DEVICES += linksys_mx4200v1 define Device/linksys_mx4200v2 $(call Device/linksys_mx4200v1) - DEVICE_VARIANT := v2 + DEVICE_VARIANT := v2 endef TARGET_DEVICES += linksys_mx4200v2 diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network index ff9069091f..1e0719cf00 100644 --- a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network +++ b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network @@ -18,8 +18,8 @@ ipq807x_setup_interfaces() ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" ;; compex,wpq873|\ - linksys,mx4200v1|\ - linksys,mx4200v2|\ + linksys,mx4200v1|\ + linksys,mx4200v2|\ redmi,ax6|\ xiaomi,ax3600) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" From 7173a52f6aea971ae90610f10fd2f184dd29755c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Owoc?= Date: Sat, 6 Jan 2024 17:05:40 +0100 Subject: [PATCH 111/222] ipq807x: use devinfo MAC for Linksys MX4200 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some devices (MX42CF) have a wrong MAC address configuration. The correct one is located only on the devinfo partition. Signed-off-by: Paweł Owoc --- .../ipq807x/base-files/etc/board.d/02_network | 24 +++++++++++++++++++ .../etc/hotplug.d/ieee80211/11_fix_wifi_mac | 7 ++++++ 2 files changed, 31 insertions(+) diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network index 1e0719cf00..f38c4b6698 100644 --- a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network +++ b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network @@ -57,9 +57,33 @@ ipq807x_setup_interfaces() esac } +ipq807x_setup_macs() +{ + local board="$1" + local lan_mac="" + local wan_mac="" + local label_mac="" + + case "$board" in + linksys,mx4200v1|\ + linksys,mx4200v2) + label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) + for i in $(seq 3 5); do + [ "$(mtd_get_mac_ascii u_env eth${i}addr)" != "$label_mac" ] && lan_mac=$label_mac + done + [ "$(mtd_get_mac_ascii u_env eth2addr)" != "$label_mac" ] && wan_mac=$label_mac + ;; + esac + + [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac + [ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac + [ -n "$label_mac" ] && ucidef_set_label_macaddr $label_mac +} + board_config_update board=$(board_name) ipq807x_setup_interfaces $board +ipq807x_setup_macs $board board_config_flush exit 0 diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index f951d925ab..343e42d634 100644 --- a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -18,6 +18,13 @@ case "$board" in [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 8 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 16 > /sys${DEVPATH}/macaddress ;; + linksys,mx4200v1|\ + linksys,mx4200v2) + label_mac=$(mtd_get_mac_ascii devinfo hw_mac_addr) + [ "$PHYNBR" = "0" ] && macaddr_add $label_mac 2 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "1" ] && macaddr_add $label_mac 1 > /sys${DEVPATH}/macaddress + [ "$PHYNBR" = "2" ] && macaddr_add $label_mac 3 > /sys${DEVPATH}/macaddress + ;; zte,mf269) [ "$PHYNBR" = "0" ] && macaddr_add $(get_mac_label) 2 > /sys${DEVPATH}/macaddress [ "$PHYNBR" = "1" ] && macaddr_add $(get_mac_label) 3 > /sys${DEVPATH}/macaddress From b38d446ecde356c48a40c51bfc9cc66d745b1056 Mon Sep 17 00:00:00 2001 From: JinGen Lim Date: Wed, 3 Jan 2024 00:54:52 +0800 Subject: [PATCH 112/222] ipq806x: add support for Fortinet FAP-421E Hardware -------- SoC: Qualcomm IPQ8064 RAM: 235MB Flash: 128MB NAND (Micron MT29F1G08ABBDAH4) 32MB SPI-NOR (Spansion FL256SAIFRO) WLAN2: Qualcomm Atheros QCA9980 WLAN5: Qualcomm Atheros QCA9980 ETH: LAN1 - Atheros AR8035 LAN2 - Atheros AR8033 USB: USB-A, 2.0 LED: Power (yellow/amber) LAN1 (yellow/amber) LAN2 (yellow/amber) WLAN2G (yellow) WLAN5G (yellow) BTN: Reset Serial: RJ45 Port (9600 8n1) Cisco console cable, TTL voltage MAC Address: LAN1 (label) at APPSBL partition LAN2: label + 1 WLAN2: label + 8 WLAN5: label + 16 Installation ------------ Connect to the RJ45 console (TTL) Connect LAN1 to host, set host ip as 192.168.1.10 Start a tftp server to serve the initramfs image Open console connection (9600n8) Connect power through the DC jack `Hit any key to stop autoboot: 5`: press any key `Enter G,Q,or H:`: press `K` to access the hidden option `Enter password:`: `fap22b1!$` to access a limited u-boot console `(FAP) #`: `tftpboot your_initramfs_image_name.itb` `(FAP) #`: `bootm` Once OpenWrt has booted, install the firmware through sysupgrade Signed-off-by: JinGen Lim --- .../ipq806x/base-files/etc/board.d/01_leds | 9 + .../ipq806x/base-files/etc/board.d/02_network | 1 + .../base-files/etc/board.d/05_compat-version | 1 + .../base-files/lib/upgrade/platform.sh | 1 + .../arm/boot/dts/qcom-ipq8064-fap-421e.dts | 410 ++++++++++++++++++ target/linux/ipq806x/image/generic.mk | 12 + 6 files changed, 434 insertions(+) create mode 100644 target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-fap-421e.dts diff --git a/target/linux/ipq806x/base-files/etc/board.d/01_leds b/target/linux/ipq806x/base-files/etc/board.d/01_leds index 0b2ce2b7d5..4aab3c9b2c 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/01_leds +++ b/target/linux/ipq806x/base-files/etc/board.d/01_leds @@ -37,6 +37,15 @@ extreme,ap3935) ucidef_set_led_netdev "wan" "wan" "orange:lan1" "eth1" ucidef_set_led_netdev "lan" "lan" "orange:lan2" "eth0" ;; +fortinet,fap-421e) + ucidef_set_led_netdev "eth1-100" "ETH1-100" "amber:eth1" "eth0" "link_100" + ucidef_set_led_netdev "eth1-1000" "ETH1-1000" "yellow:eth1" "eth0" "link_1000" + ucidef_set_led_netdev "eth2-100" "ETH2-100" "amber:eth2" "eth1" "link_100" + ucidef_set_led_netdev "eth2-1000" "ETH2-1000" "yellow:eth2" "eth1" "link_1000" + ucidef_set_led_wlan "wlan2g" "2.4G" "yellow:2g" "phy1tpt" + ucidef_set_led_wlan "wlan5g" "5G" "yellow:5g" "phy0tpt" + ucidef_set_led_usbport "usb" "USB" "amber:power" "usb1-port1" "usb2-port1" + ;; meraki,mr52) ucidef_set_led_netdev "eth0" "eth0" "green:lan1" "eth0" ucidef_set_led_netdev "eth1" "eth1" "green:lan2" "eth1" diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network index 7fdda7cfec..8f24566b62 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -56,6 +56,7 @@ ipq806x_setup_interfaces() qcom,ipq8064-db149) ucidef_set_interface_lan "eth1 eth2 eth3 lan1 lan2 lan3 lan4" "wan" ;; + fortinet,fap-421e |\ ubnt,unifi-ac-hd) ucidef_set_interface_lan "eth0 eth1" ;; diff --git a/target/linux/ipq806x/base-files/etc/board.d/05_compat-version b/target/linux/ipq806x/base-files/etc/board.d/05_compat-version index 74135b0d62..caf65b96d2 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/05_compat-version +++ b/target/linux/ipq806x/base-files/etc/board.d/05_compat-version @@ -14,6 +14,7 @@ case "$(board_name)" in asrock,g10 |\ buffalo,wxr-2533dhp |\ compex,wpq864 |\ + fortinet,fap-421e |\ nec,wg2600hp |\ nec,wg2600hp3 |\ netgear,d7800 |\ diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index 7877ecae6b..b3a615a511 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -13,6 +13,7 @@ platform_do_upgrade() { arris,tr4400-v2 |\ askey,rt4230w-rev6 |\ compex,wpq864|\ + fortinet,fap-421e|\ netgear,d7800 |\ netgear,r7500 |\ netgear,r7500v2 |\ diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-fap-421e.dts b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-fap-421e.dts new file mode 100644 index 0000000000..d80e7ecf62 --- /dev/null +++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-fap-421e.dts @@ -0,0 +1,410 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq8064-smb208.dtsi" +#include + +/ { + model = "Fortinet FAP-421E"; + compatible = "fortinet,fap-421e", "qcom,ipq8064"; + + memory@0 { + device_type = "memory"; + reg = <0x42000000 0xe000000>; + }; + + reserved-memory { + rsvd@41200000 { + no-map; + reg = <0x41200000 0x300000>; + }; + wifi_dump@44000000 { + no-map; + reg = <0x44000000 0x600000>; + }; + }; + + aliases { + led-boot = &led_power_yellow; + led-failsafe = &led_power_yellow; + led-running = &led_power_yellow; + led-upgrade = &led_power_yellow; + label-mac-device = &gmac0; + }; + + chosen { + bootargs-override = "console=ttyMSM0,9600n8"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&qcom_pinmux 56 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + eth1_amber { + label = "amber:eth1"; + gpios = <&qcom_pinmux 27 GPIO_ACTIVE_LOW>; + }; + + eth1_yellow { + label = "yellow:eth1"; + gpios = <&qcom_pinmux 26 GPIO_ACTIVE_LOW>; + }; + + eth2_amber { + label = "amber:eth2"; + gpios = <&qcom_pinmux 29 GPIO_ACTIVE_LOW>; + }; + + eth2_yellow { + label = "yellow:eth2"; + gpios = <&qcom_pinmux 28 GPIO_ACTIVE_LOW>; + }; + + power_amber { + label = "amber:power"; + gpios = <&qcom_pinmux 53 GPIO_ACTIVE_LOW>; + }; + + led_power_yellow: power_yellow { + label = "yellow:power"; + gpios = <&qcom_pinmux 58 GPIO_ACTIVE_LOW>; + }; + + 2g_yellow { + label = "yellow:2g"; + gpios = <&qcom_pinmux 30 GPIO_ACTIVE_LOW>; + }; + + 5g_yellow { + label = "yellow:5g"; + gpios = <&qcom_pinmux 64 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&qcom_pinmux { + button_pins: button_pins { + mux { + bias-pull-up; + drive-strength = <2>; + pins = "gpio56"; + }; + }; + + led_pins: led_pins { + mux { + bias-pull-down; + drive-strength = <2>; + function = "gpio"; + output-low; + pins = "gpio23"; + }; + }; + + rgmii2_pins: rgmii2-pins { + mux { + bias-disable; + drive-strength = <16>; + function = "rgmii2"; + pins = "gpio66"; + }; + }; + + spi_pins: spi_pins { + mux { + pins = "gpio18", "gpio19", "gpio21"; + function = "gsbi5"; + bias-pull-down; + }; + + data { + pins = "gpio18", "gpio19"; + drive-strength = <10>; + }; + + cs { + pins = "gpio20"; + drive-strength = <10>; + bias-pull-up; + }; + + clk { + pins = "gpio21"; + drive-strength = <12>; + }; + }; + + uart0_pins: uart0_pins { + mux { + bias-disable; + drive-strength = <12>; + function = "gsbi7"; + pins = "gpio6", "gpio7"; + }; + }; + + usb_pwr_en_pins: usb_pwr_en_pins { + mux { + pins = "gpio22"; + function = "gpio"; + drive-strength = <12>; + bias-pull-down; + output-low; + }; + }; +}; + +&gsbi7 { + status = "okay"; + + qcom,mode = ; +}; + +&gsbi7_serial{ + status = "okay"; + + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; +}; + +&gsbi5 { + status = "okay"; + + qcom,mode = ; + + spi@1a280000 { + status = "okay"; + + pinctrl-0 = <&spi_pins>; + pinctrl-names = "default"; + cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_HIGH>; + + flash@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; + reg = <0>; + m25p,fast-read; + + partition@0 { + label = "SBL1"; + reg = <0x0 0x20000>; + read-only; + }; + + partition@20000 { + label = "MIBIB"; + reg = <0x20000 0x20000>; + read-only; + }; + + partition@40000 { + label = "SBL2"; + reg = <0x40000 0x40000>; + read-only; + }; + + partition@80000 { + label = "SBL3"; + reg = <0x80000 0x80000>; + read-only; + }; + + partition@100000 { + label = "DDRCONFIG"; + reg = <0x100000 0x10000>; + read-only; + }; + + partition@110000 { + label = "SSD"; + reg = <0x110000 0x10000>; + read-only; + }; + + partition@120000 { + label = "TZ"; + reg = <0x120000 0x80000>; + read-only; + }; + + partition@1a0000 { + label = "RPM"; + reg = <0x1a0000 0x80000>; + read-only; + }; + + partition@220000 { + label = "APPSBL"; + reg = <0x220000 0x80000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_appsbl_7ff80: mac-address@7ff80 { + compatible = "mac-base"; + reg = <0x7ff80 0xc>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@2a0000 { + label = "APPSBLENV"; + reg = <0x2a0000 0x40000>; + }; + + partition@2e0000 { + label = "ART"; + reg = <0x2e0000 0x40000>; + read-only; + }; + + partition@320000 { + label = "kernel"; + reg = <0x320000 0x600000>; + }; + + partition@920000 { + label = "ubi"; + reg = <0x920000 0x1400000>; + }; + + partition@1d20000 { + label = "reserved"; + reg = <0x1d20000 0x260000>; + read-only; + }; + + partition@1f80000 { + label = "config"; + reg = <0x1f80000 0x80000>; + read-only; + }; + }; + }; +}; + +&hs_phy_1 { + status = "okay"; +}; + +&ss_phy_1 { + status = "okay"; +}; + +&usb3_1 { + status = "okay"; + + pinctrl-0 = <&usb_pwr_en_pins>; + pinctrl-names = "default"; +}; + +&pcie0 { + status = "okay"; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@1,0 { + compatible = "pci168c,0040"; + reg = <0x00010000 0 0 0 0>; + + nvmem-cells = <&macaddr_appsbl_7ff80 8>; + nvmem-cell-names = "mac-address"; + }; + }; +}; + +&pcie1 { + status = "okay"; + + max-link-speed = <1>; + + bridge@0,0 { + reg = <0x00000000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + + wifi@1,0 { + compatible = "pci168c,0040"; + reg = <0x00010000 0 0 0 0>; + + nvmem-cells = <&macaddr_appsbl_7ff80 16>; + nvmem-cell-names = "mac-address"; + }; + }; +}; + +&adm_dma { + status = "okay"; +}; + +&mdio0 { + status = "okay"; + + #address-cells = <0x1>; + #size-cells = <0x0>; + gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH>, + <&qcom_pinmux 0 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&mdio0_pins>; + pinctrl-names = "default"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; + + phy2: ethernet-phy@2 { + reg = <2>; + }; +}; + +&gmac0 { + status = "okay"; + + phy-mode = "rgmii"; + qcom,id = <0>; + pinctrl-0 = <&rgmii2_pins>; + pinctrl-names = "default"; + nvmem-cells = <&macaddr_appsbl_7ff80 0>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +&gmac2 { + status = "okay"; + + phy-mode = "sgmii"; + qcom,id = <2>; + nvmem-cells = <&macaddr_appsbl_7ff80 1>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index b3743c35e3..824a95b157 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -177,6 +177,18 @@ define Device/extreme_ap3935 endef TARGET_DEVICES += extreme_ap3935 +define Device/fortinet_fap-421e + $(call Device/FitImage) + DEVICE_VENDOR := Fortinet + DEVICE_MODEL := FAP-421E + SOC := qcom-ipq8064 + BLOCKSIZE := 128k + PAGESIZE := 2048 + BOARD_NAME := fap-421e + DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct +endef +TARGET_DEVICES += fortinet_fap-421e + define Device/linksys_ea7500-v1 $(call Device/LegacyImage) $(Device/kernel-size-migration) From b33fa6ac9065028046016ea631f6be0926d7abd0 Mon Sep 17 00:00:00 2001 From: CheWei Chien Date: Thu, 4 Jan 2024 13:28:40 +0800 Subject: [PATCH 113/222] kernel: add kmod-leds-lp5562 and kmod-leds-lp55xx-common Add kernel module for lp5562 LED driver. The kmod-leds-lp5562 depends on kmod-leds-lp55xx-common. Signed-off-by: CheWei Chien --- package/kernel/linux/modules/leds.mk | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/package/kernel/linux/modules/leds.mk b/package/kernel/linux/modules/leds.mk index 24af1b7f61..60465a8ad5 100644 --- a/package/kernel/linux/modules/leds.mk +++ b/package/kernel/linux/modules/leds.mk @@ -261,3 +261,37 @@ define KernelPackage/input-leds/description endef $(eval $(call KernelPackage,input-leds)) + + +define KernelPackage/leds-lp55xx-common + SUBMENU:=$(LEDS_MENU) + TITLE:=LED common driver for LP5521/LP5523/LP55231/LP5562 controllers + DEPENDS:=+kmod-i2c-core + KCONFIG:=CONFIG_LEDS_LP55XX_COMMON + FILES:=$(LINUX_DIR)/drivers/leds/leds-lp55xx-common.ko + AUTOLOAD:=$(call AutoLoad,60,leds-lp55xx-common,1) +endef + +define KernelPackage/leds-lp55xx-common/description + This option enables support for Texas Instruments + LP5521/LP5523/LP55231/LP5562 common driver. +endef + +$(eval $(call KernelPackage,leds-lp55xx-common)) + + +define KernelPackage/leds-lp5562 + SUBMENU:=$(LEDS_MENU) + TITLE:=LED driver for LP5562 controllers + DEPENDS:=+kmod-i2c-core +kmod-leds-lp55xx-common + KCONFIG:=CONFIG_LEDS_LP5562 + FILES:=$(LINUX_DIR)/drivers/leds/leds-lp5562.ko + AUTOLOAD:=$(call AutoLoad,60,leds-lp5562,1) +endef + +define KernelPackage/leds-lp5562/description + This option enables support for Texas Instruments LP5562 + LED controllers. +endef + +$(eval $(call KernelPackage,leds-lp5562)) \ No newline at end of file From fb45194305e6bf9b58f610c1528769320879c749 Mon Sep 17 00:00:00 2001 From: CheWei Chien Date: Thu, 4 Jan 2024 18:09:06 +0800 Subject: [PATCH 114/222] ipq807x: prpl-haze: enable LED driver on device tree Enable LED driver LP5562 on HAZE device tree and include its kernel module package on default package for HAZE. Signed-off-by: CheWei Chien --- .../arch/arm64/boot/dts/qcom/ipq8072-haze.dts | 49 +++++++++++++++++++ target/linux/qualcommax/image/ipq807x.mk | 2 +- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts index 3449964159..8fdfe981f9 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-haze.dts @@ -21,6 +21,10 @@ ethernet2 = &dp3; ethernet3 = &dp2; label-mac-device = &dp6_syn; + led-boot = &led_system_blue; + led-failsafe = &led_system_red; + led-running = &led_system_green; + led-upgrade = &led_system_blue; }; chosen { @@ -78,6 +82,13 @@ bias-pull-up; }; }; + + i2c_3_pins: i2c-3-state { + pins = "gpio46", "gpio47"; + function = "blsp2_i2c"; + drive-strength = <8>; + bias-disable; + }; }; &blsp1_uart5 { @@ -303,3 +314,41 @@ qcom,ath11k-calibration-variant = "prpl-Haze"; }; + +&blsp1_i2c3{ + pinctrl-0 = <&i2c_3_pins>; + pinctrl-names = "default"; + status = "okay"; + + led-controller@30 { + compatible = "ti,lp5562"; + reg = <0x30>; + clock-mode = /bits/ 8 <2>; + #address-cells = <1>; + #size-cells = <0>; + + led_system_red: chan@0 { + chan-name = "red"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + color = ; + reg = <0>; + }; + + led_system_green: chan@1 { + chan-name = "green"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + color = ; + reg = <1>; + }; + + led_system_blue: chan@2 { + chan-name = "blue"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + color = ; + reg = <2>; + }; + }; +}; diff --git a/target/linux/qualcommax/image/ipq807x.mk b/target/linux/qualcommax/image/ipq807x.mk index f513d7f25c..f5f0e26140 100644 --- a/target/linux/qualcommax/image/ipq807x.mk +++ b/target/linux/qualcommax/image/ipq807x.mk @@ -220,7 +220,7 @@ define Device/prpl_haze DEVICE_DTS_CONFIG := config@hk09 SOC := ipq8072 DEVICE_PACKAGES += ath11k-firmware-qcn9074 ipq-wifi-prpl_haze kmod-ath11k-pci \ - mkf2fs f2fsck kmod-fs-f2fs + mkf2fs f2fsck kmod-fs-f2fs kmod-leds-lp5562 endef TARGET_DEVICES += prpl_haze From 4d7bac1dcaae019fb4992bfb74348ef12c02daa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Schr=C3=B6der?= Date: Wed, 10 Jan 2024 11:12:10 +0100 Subject: [PATCH 115/222] mediatek: GL-MT6000: Change LED colors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fine tuning PR: openwrt/openwrt#14355 Ref: 5a82bb909bf1 ("mediatek: GL-MT6000: Add missing LED state definitions") As the only LED is using white in the stock firmware when the device is running and blue for the bootloader I suggest following changes: - Using blue for the BL and preinit+failsafe - White for normal operation (like the original FW) and sysupgrade With this changes it's clear by looking to the LED in which operation mode the device is and a possible BL stuck can be seen easily. Tested with [GL-MT6000](https://openwrt.org/toh/gl.inet/gl-mt6000). Signed-off-by: Thomas Schröder Tested-by: Hannu Nyman --- target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts b/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts index 9a7031df53..26996e7b4a 100644 --- a/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts +++ b/target/linux/mediatek/dts/mt7986a-glinet-gl-mt6000.dts @@ -13,9 +13,9 @@ aliases { serial0 = &uart0; - led-boot = &led_white; - led-failsafe = &led_white; - led-running = &led_blue; + led-boot = &led_blue; + led-failsafe = &led_blue; + led-running = &led_white; led-upgrade = &led_white; }; From 66527d28ea19a7f1ecc8a58345d54391198363eb Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Mon, 15 Jan 2024 17:31:47 +0100 Subject: [PATCH 116/222] fstools: update to Git HEAD (2024-01-15) 325d63d67006 mount_root: fix compilation error for wrong condition Signed-off-by: Christian Marangi --- package/system/fstools/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/system/fstools/Makefile b/package/system/fstools/Makefile index 6198009ac0..87281a0076 100644 --- a/package/system/fstools/Makefile +++ b/package/system/fstools/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/fstools.git -PKG_MIRROR_HASH:=02d0bc1f3a2d731756668108e3dcd305bf1be9f5b947b508ba42ea4f754cbc8b +PKG_MIRROR_HASH:=964c3bf2b1d16369380bad1098ab0a1b996f714bb448322bd82ba80aa9acd03f PKG_SOURCE_DATE:=2024-01-15 -PKG_SOURCE_VERSION:=1858a492c300a0066a91f8096a858231c3cbd246 +PKG_SOURCE_VERSION:=325d63d67006c5526ab9b0fbc62329da48aa93af CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 From 5bfdd83393eb83cbc78915c16f190b26dabe9e13 Mon Sep 17 00:00:00 2001 From: Alexander Egorenkov Date: Thu, 8 Jun 2023 08:34:13 +0200 Subject: [PATCH 117/222] gettext-full: use autoreconf host fixup To prevent use of host's library path on Void Linux: /usr/lib/libacl.so: file not recognized: file format not recognized collect2: error: ld returned 1 exit status libtool: error: error: relink 'libgettextlib.la' with the above command before installing it Signed-off-by: Alexander Egorenkov --- package/libs/gettext-full/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package/libs/gettext-full/Makefile b/package/libs/gettext-full/Makefile index 1ed0e82df0..eb5b6d31bd 100644 --- a/package/libs/gettext-full/Makefile +++ b/package/libs/gettext-full/Makefile @@ -25,6 +25,8 @@ PKG_INSTALL:=1 PKG_BUILD_DEPENDS:=gettext-full/host libunistring libxml2 PKG_BUILD_PARALLEL:=0 +PKG_FIXUP:=autoreconf + HOST_BUILD_DEPENDS:=gperf/host libunistring/host libxml2/host HOST_BUILD_PARALLEL:=0 From b49a0feb2008fcfcf916632950f23423494d3319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20K=C3=B6rner?= Date: Tue, 19 Sep 2023 22:27:11 +0200 Subject: [PATCH 118/222] rtl931x: reformat broken indentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the given code-format did not correctly express the condition and made the code harder to read then necessary. Signed-off-by: Peter Körner --- .../realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c index 0e82d79d4c..07ac25c743 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c @@ -1586,9 +1586,9 @@ static void rtl931x_led_init(struct rtl838x_switch_priv *priv) sw_w32_mask(0x3 << pos, v << pos, RTL931X_LED_PORT_NUM_CTRL(i)); if (priv->ports[i].phy_is_integrated) - pm_fiber |= BIT_ULL(i); - else - pm_copper |= BIT_ULL(i); + pm_fiber |= BIT_ULL(i); + else + pm_copper |= BIT_ULL(i); set = priv->ports[i].led_set; sw_w32_mask(0, set << pos, RTL931X_LED_PORT_COPR_SET_SEL_CTRL(i)); From 668a0491715853117b15578e4e5bca5cef8e99d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20K=C3=B6rner?= Date: Wed, 20 Sep 2023 00:44:39 +0200 Subject: [PATCH 119/222] rtl838x: fix RTL838X_LED_SW_CTRL definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to https://svanheule.net/realtek/maple/register/led_sw_ctrl and also drivers/net/dsa/rtl83xx/debugfs.c LED_SW_CTRL on the RTL838X should be 0xa00c not 0x0128. Please note, that is is 0x0128 on the RTL8390/cypress SOC family. Signed-off-by: Peter Körner --- .../arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h b/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h index d9c0b311ae..81a9ac00f8 100644 --- a/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h +++ b/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h @@ -291,7 +291,7 @@ #define RTL838X_LED_P_EN_CTRL (0xA008) /* LED control by software */ -#define RTL838X_LED_SW_CTRL (0x0128) +#define RTL838X_LED_SW_CTRL (0xA00C) #define RTL839X_LED_SW_CTRL (0xA00C) #define RTL838X_LED_SW_P_EN_CTRL (0xA010) #define RTL839X_LED_SW_P_EN_CTRL (0x012C) From 5798e12e4a23abf71c8cf74e6f3565fe64c8da07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20K=C3=B6rner?= Date: Wed, 20 Sep 2023 00:45:14 +0200 Subject: [PATCH 120/222] rtl838x: debugfs use constants from mach-rtl83xx.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The register constants were duplicated in net/dsa/rtl83xx/debugfs.c and asm mach-rtl838x/mach-rtl83xx.h. This commit removes this duplication. Signed-off-by: Peter Körner --- .../include/asm/mach-rtl838x/mach-rtl83xx.h | 1 + .../drivers/net/dsa/rtl83xx/debugfs.c | 28 ++++++------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h b/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h index 81a9ac00f8..8ea580f3d1 100644 --- a/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h +++ b/target/linux/realtek/files-5.15/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h @@ -302,6 +302,7 @@ #define RTL838X_LED2_SW_P_EN_CTRL (0xA018) #define RTL839X_LED2_SW_P_EN_CTRL (0x0134) #define RTL838X_LED_SW_P_CTRL (0xA01C) +#define RTL838X_LED_SW_P_CTRL_PORT(p) (RTL838X_LED_SW_P_CTRL + (((p) << 2))) #define RTL839X_LED_SW_P_CTRL (0x0144) #define RTL839X_MAC_EFUSE_CTRL (0x02ac) diff --git a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/debugfs.c b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/debugfs.c index 1c32d47c6f..92d6932dc5 100644 --- a/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/debugfs.c +++ b/target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/debugfs.c @@ -8,16 +8,6 @@ #define RTL838X_DRIVER_NAME "rtl838x" -#define RTL8380_LED_GLB_CTRL (0xA000) -#define RTL8380_LED_MODE_SEL (0x1004) -#define RTL8380_LED_MODE_CTRL (0xA004) -#define RTL8380_LED_P_EN_CTRL (0xA008) -#define RTL8380_LED_SW_CTRL (0xA00C) -#define RTL8380_LED0_SW_P_EN_CTRL (0xA010) -#define RTL8380_LED1_SW_P_EN_CTRL (0xA014) -#define RTL8380_LED2_SW_P_EN_CTRL (0xA018) -#define RTL8380_LED_SW_P_CTRL(p) (0xA01C + (((p) << 2))) - #define RTL8390_LED_GLB_CTRL (0x00E4) #define RTL8390_LED_SET_2_3_CTRL (0x00E8) #define RTL8390_LED_SET_0_1_CTRL (0x00EC) @@ -520,28 +510,28 @@ static int rtl838x_dbgfs_leds(struct dentry *parent, struct rtl838x_switch_priv if (priv->family_id == RTL8380_FAMILY_ID) { debugfs_create_x32("led_glb_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_GLB_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_GLB_CTRL)); debugfs_create_x32("led_mode_sel", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_MODE_SEL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_MODE_SEL)); debugfs_create_x32("led_mode_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_MODE_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_MODE_CTRL)); debugfs_create_x32("led_p_en_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_P_EN_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_P_EN_CTRL)); debugfs_create_x32("led_sw_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_SW_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_SW_CTRL)); debugfs_create_x32("led0_sw_p_en_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED0_SW_P_EN_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED0_SW_P_EN_CTRL)); debugfs_create_x32("led1_sw_p_en_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED1_SW_P_EN_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED1_SW_P_EN_CTRL)); debugfs_create_x32("led2_sw_p_en_ctrl", 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED2_SW_P_EN_CTRL)); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED2_SW_P_EN_CTRL)); for (int p = 0; p < 28; p++) { char led_sw_p_ctrl_name[20]; snprintf(led_sw_p_ctrl_name, sizeof(led_sw_p_ctrl_name), "led_sw_p_ctrl.%02d", p); debugfs_create_x32(led_sw_p_ctrl_name, 0644, led_dir, - (u32 *)(RTL838X_SW_BASE + RTL8380_LED_SW_P_CTRL(p))); + (u32 *)(RTL838X_SW_BASE + RTL838X_LED_SW_P_CTRL_PORT(p))); } } else if (priv->family_id == RTL8390_FAMILY_ID) { char port_led_name[20]; From 95157dde046058f745437a37a35d8136c8c84608 Mon Sep 17 00:00:00 2001 From: Philip Prindeville Date: Mon, 1 Jan 2024 15:37:34 -0700 Subject: [PATCH 121/222] base-files: functions.sh: prepend() always adds separator It shouldn't gate on the value, since the value will ostensibly always be set; instead it should depend on the variable being prepended to being non-empty. Fixes #14403 Signed-off-by: Philip Prindeville --- package/base-files/files/lib/functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/base-files/files/lib/functions.sh b/package/base-files/files/lib/functions.sh index 851d2f1791..d23a56e0cf 100644 --- a/package/base-files/files/lib/functions.sh +++ b/package/base-files/files/lib/functions.sh @@ -45,7 +45,7 @@ prepend() { local value="$2" local sep="${3:- }" - eval "export ${NO_EXPORT:+-n} -- \"$var=\${$value:+\${$value}\$sep}\$var\"" + eval "export ${NO_EXPORT:+-n} -- \"$var=\$value\${$var:+\${sep}\${$var}}\"" } list_contains() { From dfc29816c85086f3951e227651e3b28f73153f60 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Mon, 15 Jan 2024 19:53:06 +0100 Subject: [PATCH 122/222] generic: 6.1: renumber MediaTek SGMII PCS patch Renumber MediaTek SGMII PCS patch to make space for upcoming at803x backport patches. Signed-off-by: Christian Marangi --- ...h => 723-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename target/linux/generic/backport-6.1/{707-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch => 723-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch} (100%) diff --git a/target/linux/generic/backport-6.1/707-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch b/target/linux/generic/backport-6.1/723-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch similarity index 100% rename from target/linux/generic/backport-6.1/707-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch rename to target/linux/generic/backport-6.1/723-v6.3-net-pcs-add-driver-for-MediaTek-SGMII-PCS.patch From c2c741ccce0480a5a71bfa6b392b3c71e867d1dc Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Mon, 15 Jan 2024 19:54:23 +0100 Subject: [PATCH 123/222] generic: 6.1: initial backport of at803x PHY driver cleanup Initial backport of at803x PHY driver cleanup. This is in preparation for split and addition of new PHY Family based on at803x needed for ipq807x and other IPQ Series SoC. Other affected patch are automatically refreshed with make target/linux/refresh Signed-off-by: Christian Marangi --- ...edicated-C45-API-to-MDIO-bus-drivers.patch | 326 ++++++++++++++++++ ...-Introduce-PSGMII-PHY-interface-mode.patch | 105 ++++++ ...eplace-of_gpio.h-with-what-indeed-is.patch | 32 ++ ...upport-qca8081-genphy_c45_pma_read_a.patch | 70 ++++ ...3x-merge-qca8081-slave-seed-function.patch | 73 ++++ ...nable-qca8081-slave-seed-conditional.patch | 76 ++++ ...-at803x-support-qca8081-1G-chip-type.patch | 48 +++ ...emove-qca8081-1G-fast-retrain-and-sl.patch | 98 ++++++ ...dd-qca8081-fifo-reset-on-the-link-ch.patch | 55 +++ ...ix-passing-the-wrong-reference-for-c.patch | 45 +++ ...ove-disable-WOL-to-specific-at8031-p.patch | 69 ++++ ...aname-hw_stats-functions-to-qca83xx-.patch | 129 +++++++ ...ove-qca83xx-specific-check-in-dedica.patch | 155 +++++++++ ...ove-specific-DT-option-for-at8031-to.patch | 94 +++++ ...ove-specific-at8031-probe-mode-check.patch | 78 +++++ ...ove-specific-at8031-config_init-to-d.patch | 86 +++++ ...ove-specific-at8031-WOL-bits-to-dedi.patch | 92 +++++ ...ove-specific-at8031-config_intr-to-d.patch | 78 +++++ ...ake-at8031-related-DT-functions-name.patch | 78 +++++ ...ove-at8031-functions-in-dedicated-se.patch | 297 ++++++++++++++++ ...ove-at8035-specific-DT-parse-to-dedi.patch | 114 ++++++ ...rop-specific-PHY-ID-check-from-cable.patch | 219 ++++++++++++ ...ove-specific-qca808x-config_aneg-to-.patch | 116 +++++++ ...ake-read-specific-status-function-mo.patch | 97 ++++++ ...at803x-remove-extra-space-after-cast.patch | 27 ++ ...x-replace-msleep-1-with-usleep_range.patch | 38 ++ ...etter-align-function-varibles-to-ope.patch | 152 ++++++++ ...generalize-cdt-fault-length-function.patch | 62 ++++ ...efactor-qca808x-cable-test-get-statu.patch | 118 +++++++ ...dd-support-for-cdt-cross-short-test-.patch | 182 ++++++++++ ...at803x-make-read_status-more-generic.patch | 62 ++++ ...k-add-pcs_enable-pcs_disable-methods.patch | 14 +- ...5-net-phy-Add-a-binding-for-PHY-LEDs.patch | 6 +- ...ce-Call-into-the-PHY-driver-to-set-L.patch | 4 +- ...ce-Call-into-the-PHY-driver-to-set-L.patch | 2 +- ...ce-Call-into-the-PHY-driver-to-set-L.patch | 2 +- ...detach-callback-to-struct-phy_driver.patch | 2 +- 37 files changed, 3286 insertions(+), 15 deletions(-) create mode 100644 target/linux/generic/backport-6.1/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch create mode 100644 target/linux/generic/backport-6.1/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch create mode 100644 target/linux/generic/backport-6.1/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch create mode 100644 target/linux/generic/backport-6.1/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch create mode 100644 target/linux/generic/backport-6.1/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch create mode 100644 target/linux/generic/backport-6.1/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch create mode 100644 target/linux/generic/backport-6.1/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch create mode 100644 target/linux/generic/backport-6.1/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch create mode 100644 target/linux/generic/backport-6.1/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-01-net-phy-at803x-fix-passing-the-wrong-reference-for-c.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch create mode 100644 target/linux/generic/backport-6.1/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch create mode 100644 target/linux/generic/backport-6.1/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch create mode 100644 target/linux/generic/backport-6.1/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch create mode 100644 target/linux/generic/backport-6.1/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch create mode 100644 target/linux/generic/backport-6.1/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch create mode 100644 target/linux/generic/backport-6.1/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch create mode 100644 target/linux/generic/backport-6.1/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch create mode 100644 target/linux/generic/backport-6.1/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch create mode 100644 target/linux/generic/backport-6.1/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch create mode 100644 target/linux/generic/backport-6.1/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch diff --git a/target/linux/generic/backport-6.1/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch b/target/linux/generic/backport-6.1/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch new file mode 100644 index 0000000000..ff186742ba --- /dev/null +++ b/target/linux/generic/backport-6.1/703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch @@ -0,0 +1,326 @@ +From 4e4aafcddbbfcdd6eed5780e190fcbfac8b4685a Mon Sep 17 00:00:00 2001 +From: Andrew Lunn +Date: Mon, 9 Jan 2023 16:30:41 +0100 +Subject: [PATCH] net: mdio: Add dedicated C45 API to MDIO bus drivers + +Currently C22 and C45 transactions are mixed over a combined API calls +which make use of a special bit in the reg address to indicate if a +C45 transaction should be performed. This makes it impossible to know +if the bus driver actually supports C45. Additionally, many C22 only +drivers don't return -EOPNOTSUPP when asked to perform a C45 +transaction, they mistaking perform a C22 transaction. + +This is the first step to cleanly separate C22 from C45. To maintain +backwards compatibility until all drivers which are capable of +performing C45 are converted to this new API, the helper functions +will fall back to the older API if the new API is not +supported. Eventually this fallback will be removed. + +Signed-off-by: Andrew Lunn +Signed-off-by: Michael Walle +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/mdio_bus.c | 189 +++++++++++++++++++++++++++++++++++++ + include/linux/mdio.h | 39 ++++---- + include/linux/phy.h | 5 + + 3 files changed, 214 insertions(+), 19 deletions(-) + +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -832,6 +832,100 @@ int __mdiobus_modify_changed(struct mii_ + EXPORT_SYMBOL_GPL(__mdiobus_modify_changed); + + /** ++ * __mdiobus_c45_read - Unlocked version of the mdiobus_c45_read function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to read ++ * ++ * Read a MDIO bus register. Caller must hold the mdio bus lock. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) ++{ ++ int retval; ++ ++ lockdep_assert_held_once(&bus->mdio_lock); ++ ++ if (bus->read_c45) ++ retval = bus->read_c45(bus, addr, devad, regnum); ++ else ++ retval = bus->read(bus, addr, mdiobus_c45_addr(devad, regnum)); ++ ++ trace_mdio_access(bus, 1, addr, regnum, retval, retval); ++ mdiobus_stats_acct(&bus->stats[addr], true, retval); ++ ++ return retval; ++} ++EXPORT_SYMBOL(__mdiobus_c45_read); ++ ++/** ++ * __mdiobus_c45_write - Unlocked version of the mdiobus_write function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * Write a MDIO bus register. Caller must hold the mdio bus lock. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val) ++{ ++ int err; ++ ++ lockdep_assert_held_once(&bus->mdio_lock); ++ ++ if (bus->write_c45) ++ err = bus->write_c45(bus, addr, devad, regnum, val); ++ else ++ err = bus->write(bus, addr, mdiobus_c45_addr(devad, regnum), ++ val); ++ ++ trace_mdio_access(bus, 0, addr, regnum, val, err); ++ mdiobus_stats_acct(&bus->stats[addr], false, err); ++ ++ return err; ++} ++EXPORT_SYMBOL(__mdiobus_c45_write); ++ ++/** ++ * __mdiobus_c45_modify_changed - Unlocked version of the mdiobus_modify function ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to modify ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ * ++ * Read, modify, and if any change, write the register value back to the ++ * device. Any error returns a negative number. ++ * ++ * NOTE: MUST NOT be called from interrupt context. ++ */ ++static int __mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, ++ int devad, u32 regnum, u16 mask, ++ u16 set) ++{ ++ int new, ret; ++ ++ ret = __mdiobus_c45_read(bus, addr, devad, regnum); ++ if (ret < 0) ++ return ret; ++ ++ new = (ret & ~mask) | set; ++ if (new == ret) ++ return 0; ++ ++ ret = __mdiobus_c45_write(bus, addr, devad, regnum, new); ++ ++ return ret < 0 ? ret : 1; ++} ++ ++/** + * mdiobus_read_nested - Nested version of the mdiobus_read function + * @bus: the mii_bus struct + * @addr: the phy address +@@ -879,6 +973,29 @@ int mdiobus_read(struct mii_bus *bus, in + EXPORT_SYMBOL(mdiobus_read); + + /** ++ * mdiobus_c45_read - Convenience function for reading a given MII mgmt register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to read ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) ++{ ++ int retval; ++ ++ mutex_lock(&bus->mdio_lock); ++ retval = __mdiobus_c45_read(bus, addr, devad, regnum); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return retval; ++} ++EXPORT_SYMBOL(mdiobus_c45_read); ++ ++/** + * mdiobus_write_nested - Nested version of the mdiobus_write function + * @bus: the mii_bus struct + * @addr: the phy address +@@ -928,6 +1045,31 @@ int mdiobus_write(struct mii_bus *bus, i + EXPORT_SYMBOL(mdiobus_write); + + /** ++ * mdiobus_c45_write - Convenience function for writing a given MII mgmt register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @val: value to write to @regnum ++ * ++ * NOTE: MUST NOT be called from interrupt context, ++ * because the bus read/write functions may wait for an interrupt ++ * to conclude the operation. ++ */ ++int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_write(bus, addr, devad, regnum, val); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err; ++} ++EXPORT_SYMBOL(mdiobus_c45_write); ++ ++/** + * mdiobus_modify - Convenience function for modifying a given mdio device + * register + * @bus: the mii_bus struct +@@ -949,6 +1091,30 @@ int mdiobus_modify(struct mii_bus *bus, + EXPORT_SYMBOL_GPL(mdiobus_modify); + + /** ++ * mdiobus_c45_modify - Convenience function for modifying a given mdio device ++ * register ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ */ ++int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 mask, u16 set) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, ++ mask, set); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err < 0 ? err : 0; ++} ++EXPORT_SYMBOL_GPL(mdiobus_c45_modify); ++ ++/** + * mdiobus_modify_changed - Convenience function for modifying a given mdio + * device register and returning if it changed + * @bus: the mii_bus struct +@@ -971,6 +1137,29 @@ int mdiobus_modify_changed(struct mii_bu + EXPORT_SYMBOL_GPL(mdiobus_modify_changed); + + /** ++ * mdiobus_c45_modify_changed - Convenience function for modifying a given mdio ++ * device register and returning if it changed ++ * @bus: the mii_bus struct ++ * @addr: the phy address ++ * @devad: device address to read ++ * @regnum: register number to write ++ * @mask: bit mask of bits to clear ++ * @set: bit mask of bits to set ++ */ ++int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr, ++ u32 regnum, u16 mask, u16 set) ++{ ++ int err; ++ ++ mutex_lock(&bus->mdio_lock); ++ err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, mask, set); ++ mutex_unlock(&bus->mdio_lock); ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(mdiobus_c45_modify_changed); ++ ++/** + * mdio_bus_match - determine if given MDIO driver supports the given + * MDIO device + * @dev: target MDIO device +--- a/include/linux/mdio.h ++++ b/include/linux/mdio.h +@@ -423,6 +423,17 @@ int mdiobus_modify(struct mii_bus *bus, + u16 set); + int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum, + u16 mask, u16 set); ++int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); ++int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum); ++int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val); ++int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 val); ++int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum, ++ u16 mask, u16 set); ++ ++int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad, ++ u32 regnum, u16 mask, u16 set); + + static inline int mdiodev_read(struct mdio_device *mdiodev, u32 regnum) + { +@@ -463,29 +474,19 @@ static inline u16 mdiobus_c45_devad(u32 + return FIELD_GET(MII_DEVADDR_C45_MASK, regnum); + } + +-static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, +- u16 regnum) +-{ +- return __mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); +-} +- +-static inline int __mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, +- u16 regnum, u16 val) +-{ +- return __mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), +- val); +-} +- +-static inline int mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, +- u16 regnum) ++static inline int mdiodev_c45_modify(struct mdio_device *mdiodev, int devad, ++ u32 regnum, u16 mask, u16 set) + { +- return mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum)); ++ return mdiobus_c45_modify(mdiodev->bus, mdiodev->addr, devad, regnum, ++ mask, set); + } + +-static inline int mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad, +- u16 regnum, u16 val) ++static inline int mdiodev_c45_modify_changed(struct mdio_device *mdiodev, ++ int devad, u32 regnum, u16 mask, ++ u16 set) + { +- return mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), val); ++ return mdiobus_c45_modify_changed(mdiodev->bus, mdiodev->addr, devad, ++ regnum, mask, set); + } + + int mdiobus_register_device(struct mdio_device *mdiodev); +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -364,6 +364,11 @@ struct mii_bus { + int (*read)(struct mii_bus *bus, int addr, int regnum); + /** @write: Perform a write transfer on the bus */ + int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val); ++ /** @read_c45: Perform a C45 read transfer on the bus */ ++ int (*read_c45)(struct mii_bus *bus, int addr, int devnum, int regnum); ++ /** @write_c45: Perform a C45 write transfer on the bus */ ++ int (*write_c45)(struct mii_bus *bus, int addr, int devnum, ++ int regnum, u16 val); + /** @reset: Perform a reset of the bus */ + int (*reset)(struct mii_bus *bus); + diff --git a/target/linux/generic/backport-6.1/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch b/target/linux/generic/backport-6.1/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch new file mode 100644 index 0000000000..80210e6da1 --- /dev/null +++ b/target/linux/generic/backport-6.1/704-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch @@ -0,0 +1,105 @@ +From 9a0e95e34e9c0a713ddfd48c3a88a20d2bdfd514 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Fri, 11 Aug 2023 13:10:07 +0200 +Subject: [PATCH] net: phy: Introduce PSGMII PHY interface mode + +The PSGMII interface is similar to QSGMII. The main difference +is that the PSGMII interface combines five SGMII lines into a +single link while in QSGMII only four lines are combined. + +Similarly to the QSGMII, this interface mode might also needs +special handling within the MAC driver. + +It is commonly used by Qualcomm with their QCA807x PHY series and +modern WiSoC-s. + +Add definitions for the PHY layer to allow to express this type +of connection between the MAC and PHY. + +Signed-off-by: Gabor Juhos +Signed-off-by: Robert Marko +Signed-off-by: David S. Miller +--- + Documentation/networking/phy.rst | 4 ++++ + drivers/net/phy/phy-core.c | 2 ++ + drivers/net/phy/phylink.c | 3 +++ + include/linux/phy.h | 4 ++++ + 4 files changed, 13 insertions(+) + +--- a/Documentation/networking/phy.rst ++++ b/Documentation/networking/phy.rst +@@ -323,6 +323,10 @@ Some of the interface modes are describe + contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this + interface mode has different autonegotiation and only supports full duplex. + ++``PHY_INTERFACE_MODE_PSGMII`` ++ This is the Penta SGMII mode, it is similar to QSGMII but it combines 5 ++ SGMII lines into a single link compared to 4 on QSGMII. ++ + Pause frames / flow control + =========================== + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -140,6 +140,8 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + return 4; ++ case PHY_INTERFACE_MODE_PSGMII: ++ return 5; + case PHY_INTERFACE_MODE_MAX: + WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode"); + return 0; +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -187,6 +187,7 @@ static int phylink_interface_max_speed(p + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_SGMII: +@@ -448,6 +449,7 @@ unsigned long phylink_get_capabilities(p + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_SGMII: +@@ -814,6 +816,7 @@ static int phylink_parse_mode(struct phy + + switch (pl->link_config.interface) { + case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_RGMII: +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -103,6 +103,7 @@ extern const int phy_10gbit_features_arr + * @PHY_INTERFACE_MODE_XGMII: 10 gigabit media-independent interface + * @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface + * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax ++ * @PHY_INTERFACE_MODE_PSGMII: Penta SGMII + * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII + * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII + * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX +@@ -140,6 +141,7 @@ typedef enum { + PHY_INTERFACE_MODE_XGMII, + PHY_INTERFACE_MODE_XLGMII, + PHY_INTERFACE_MODE_MOCA, ++ PHY_INTERFACE_MODE_PSGMII, + PHY_INTERFACE_MODE_QSGMII, + PHY_INTERFACE_MODE_TRGMII, + PHY_INTERFACE_MODE_100BASEX, +@@ -247,6 +249,8 @@ static inline const char *phy_modes(phy_ + return "xlgmii"; + case PHY_INTERFACE_MODE_MOCA: + return "moca"; ++ case PHY_INTERFACE_MODE_PSGMII: ++ return "psgmii"; + case PHY_INTERFACE_MODE_QSGMII: + return "qsgmii"; + case PHY_INTERFACE_MODE_TRGMII: diff --git a/target/linux/generic/backport-6.1/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch b/target/linux/generic/backport-6.1/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch new file mode 100644 index 0000000000..7cacb71b18 --- /dev/null +++ b/target/linux/generic/backport-6.1/705-v6.4-net-phy-at803x-Replace-of_gpio.h-with-what-indeed-is.patch @@ -0,0 +1,32 @@ +From a593a2fcfdfb92cfd0ffc54bc81b07e6bfaaaf46 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Thu, 16 Mar 2023 14:08:26 +0200 +Subject: [PATCH] net: phy: at803x: Replace of_gpio.h with what indeed is used + +of_gpio.h in this driver is solely used as a proxy to other headers. +This is incorrect usage of the of_gpio.h. Replace it .h with what +indeed is used in the code. + +Signed-off-by: Andy Shevchenko +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -13,12 +13,11 @@ + #include + #include + #include +-#include + #include +-#include + #include + #include + #include ++#include + #include + #include + #include diff --git a/target/linux/generic/backport-6.1/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch b/target/linux/generic/backport-6.1/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch new file mode 100644 index 0000000000..dab4928960 --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-01-net-phy-at803x-support-qca8081-genphy_c45_pma_read_a.patch @@ -0,0 +1,70 @@ +From 8b8bc13d89a7d23d14b0e041c73f037c9db997b1 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:19 +0800 +Subject: [PATCH 1/6] net: phy: at803x: support qca8081 + genphy_c45_pma_read_abilities + +qca8081 PHY supports to use genphy_c45_pma_read_abilities for +getting the PHY features supported except for the autoneg ability + +but autoneg ability exists in MDIO_STAT1 instead of MMD7.1, add it +manually after calling genphy_c45_pma_read_abilities. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 28 ++++++++++++++++++---------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -902,15 +902,6 @@ static int at803x_get_features(struct ph + if (err) + return err; + +- if (phydev->drv->phy_id == QCA8081_PHY_ID) { +- err = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_NG_EXTABLE); +- if (err < 0) +- return err; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported, +- err & MDIO_PMA_NG_EXTABLE_2_5GBT); +- } +- + if (phydev->drv->phy_id != ATH8031_PHY_ID) + return 0; + +@@ -1996,6 +1987,23 @@ static int qca808x_cable_test_get_status + return 0; + } + ++static int qca808x_get_features(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_c45_pma_read_abilities(phydev); ++ if (ret) ++ return ret; ++ ++ /* The autoneg ability is not existed in bit3 of MMD7.1, ++ * but it is supported by qca808x PHY, so we add it here ++ * manually. ++ */ ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); ++ ++ return 0; ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -2163,7 +2171,7 @@ static struct phy_driver at803x_driver[] + .set_tunable = at803x_set_tunable, + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, +- .get_features = at803x_get_features, ++ .get_features = qca808x_get_features, + .config_aneg = at803x_config_aneg, + .suspend = genphy_suspend, + .resume = genphy_resume, diff --git a/target/linux/generic/backport-6.1/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch b/target/linux/generic/backport-6.1/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch new file mode 100644 index 0000000000..28874068ce --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-02-net-phy-at803x-merge-qca8081-slave-seed-function.patch @@ -0,0 +1,73 @@ +From f3db55ae860a82e1224a909072783ef850e5d228 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:20 +0800 +Subject: [PATCH 2/6] net: phy: at803x: merge qca8081 slave seed function + +merge the seed enablement and seed value configuration into +one function, since the random seed value is needed to be +configured when the seed is enabled. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 29 +++++++++-------------------- + 1 file changed, 9 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1730,24 +1730,19 @@ static int qca808x_phy_fast_retrain_conf + return 0; + } + +-static int qca808x_phy_ms_random_seed_set(struct phy_device *phydev) +-{ +- u16 seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); +- +- return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_CFG, +- FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value)); +-} +- + static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable) + { +- u16 seed_enable = 0; ++ u16 seed_value; + +- if (enable) +- seed_enable = QCA808X_MASTER_SLAVE_SEED_ENABLE; ++ if (!enable) ++ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, ++ QCA808X_MASTER_SLAVE_SEED_ENABLE, 0); + ++ seed_value = prandom_u32_max(QCA808X_MASTER_SLAVE_SEED_RANGE); + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED, +- QCA808X_MASTER_SLAVE_SEED_ENABLE, seed_enable); ++ QCA808X_MASTER_SLAVE_SEED_CFG | QCA808X_MASTER_SLAVE_SEED_ENABLE, ++ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value) | ++ QCA808X_MASTER_SLAVE_SEED_ENABLE); + } + + static int qca808x_config_init(struct phy_device *phydev) +@@ -1771,12 +1766,7 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_random_seed_set(phydev); +- if (ret) +- return ret; +- +- /* Enable seed */ ++ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ + ret = qca808x_phy_ms_seed_enable(phydev, true); + if (ret) + return ret; +@@ -1821,7 +1811,6 @@ static int qca808x_read_status(struct ph + if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { +- qca808x_phy_ms_random_seed_set(phydev); + qca808x_phy_ms_seed_enable(phydev, true); + } + } diff --git a/target/linux/generic/backport-6.1/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch b/target/linux/generic/backport-6.1/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch new file mode 100644 index 0000000000..b91d2cab30 --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-03-net-phy-at803x-enable-qca8081-slave-seed-conditional.patch @@ -0,0 +1,76 @@ +From 7cc3209558002d95c0d45a1276ba4f5f741eec42 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:21 +0800 +Subject: [PATCH 3/6] net: phy: at803x: enable qca8081 slave seed conditionally + +qca8081 is the single port PHY, the slave prefer mode is used +by default. + +if the phy master perfer mode is configured, the slave seed +configuration should not be enabled, since the slave seed +enablement is for making PHY linked as slave mode easily. + +disable slave seed if the master mode is preferred. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1745,6 +1745,12 @@ static int qca808x_phy_ms_seed_enable(st + QCA808X_MASTER_SLAVE_SEED_ENABLE); + } + ++static bool qca808x_is_prefer_master(struct phy_device *phydev) ++{ ++ return (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_FORCE) || ++ (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); ++} ++ + static int qca808x_config_init(struct phy_device *phydev) + { + int ret; +@@ -1766,11 +1772,17 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); +- if (ret) ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) + return ret; + ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } ++ + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, + QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); +@@ -1802,13 +1814,16 @@ static int qca808x_read_status(struct ph + phydev->interface = PHY_INTERFACE_MODE_SGMII; + } else { + /* generate seed as a lower random value to make PHY linked as SLAVE easily, +- * except for master/slave configuration fault detected. ++ * except for master/slave configuration fault detected or the master mode ++ * preferred. ++ * + * the reason for not putting this code into the function link_change_notify is + * the corner case where the link partner is also the qca8081 PHY and the seed + * value is configured as the same value, the link can't be up and no link change + * occurs. + */ +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { + qca808x_phy_ms_seed_enable(phydev, true); diff --git a/target/linux/generic/backport-6.1/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch b/target/linux/generic/backport-6.1/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch new file mode 100644 index 0000000000..b8db89d853 --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-04-net-phy-at803x-support-qca8081-1G-chip-type.patch @@ -0,0 +1,48 @@ +From fea7cfb83d1a2782e39cd101dd44ed2548539de5 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:22 +0800 +Subject: [PATCH 4/6] net: phy: at803x: support qca8081 1G chip type + +The qca8081 1G chip version does not support 2.5 capability, which +is distinguished from qca8081 2.5G chip according to the bit0 of +register mmd7.0x901d, the 1G version chip also has the same PHY ID +as the normal qca8081 2.5G chip. + +Signed-off-by: Luo Jie +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -272,6 +272,10 @@ + #define QCA808X_CDT_STATUS_STAT_OPEN 2 + #define QCA808X_CDT_STATUS_STAT_SHORT 3 + ++/* QCA808X 1G chip type */ ++#define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d ++#define QCA808X_PHY_CHIP_TYPE_1G BIT(0) ++ + MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); +@@ -2005,6 +2009,17 @@ static int qca808x_get_features(struct p + */ + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); + ++ /* As for the qca8081 1G version chip, the 2500baseT ability is also ++ * existed in the bit0 of MMD1.21, we need to remove it manually if ++ * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); ++ if (ret < 0) ++ return ret; ++ ++ if (QCA808X_PHY_CHIP_TYPE_1G & ret) ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++ + return 0; + } + diff --git a/target/linux/generic/backport-6.1/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch b/target/linux/generic/backport-6.1/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch new file mode 100644 index 0000000000..b54a86e5f5 --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-05-net-phy-at803x-remove-qca8081-1G-fast-retrain-and-sl.patch @@ -0,0 +1,98 @@ +From df9401ff3e6eeaa42bfb06761967f1b71f5afce7 Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:23 +0800 +Subject: [PATCH 5/6] net: phy: at803x: remove qca8081 1G fast retrain and + slave seed config + +The fast retrain and slave seed configs are only applicable when the 2.5G +ability is supported. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 50 +++++++++++++++++++++++++--------------- + 1 file changed, 32 insertions(+), 18 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1755,6 +1755,11 @@ static bool qca808x_is_prefer_master(str + (phydev->master_slave_get == MASTER_SLAVE_CFG_MASTER_PREFERRED); + } + ++static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) ++{ ++ return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); ++} ++ + static int qca808x_config_init(struct phy_device *phydev) + { + int ret; +@@ -1771,20 +1776,24 @@ static int qca808x_config_init(struct ph + if (ret) + return ret; + +- /* Config the fast retrain for the link 2500M */ +- ret = qca808x_phy_fast_retrain_config(phydev); +- if (ret) +- return ret; +- +- ret = genphy_read_master_slave(phydev); +- if (ret < 0) +- return ret; +- +- if (!qca808x_is_prefer_master(phydev)) { +- /* Enable seed and configure lower ramdom seed to make phy linked as slave mode */ +- ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ /* Config the fast retrain for the link 2500M */ ++ ret = qca808x_phy_fast_retrain_config(phydev); + if (ret) + return ret; ++ ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (!qca808x_is_prefer_master(phydev)) { ++ /* Enable seed and configure lower ramdom seed to make phy ++ * linked as slave mode. ++ */ ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ if (ret) ++ return ret; ++ } + } + + /* Configure adc threshold as 100mv for the link 10M */ +@@ -1826,11 +1835,13 @@ static int qca808x_read_status(struct ph + * value is configured as the same value, the link can't be up and no link change + * occurs. + */ +- if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { +- qca808x_phy_ms_seed_enable(phydev, false); +- } else { +- qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { ++ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || ++ qca808x_is_prefer_master(phydev)) { ++ qca808x_phy_ms_seed_enable(phydev, false); ++ } else { ++ qca808x_phy_ms_seed_enable(phydev, true); ++ } + } + } + +@@ -1845,7 +1856,10 @@ static int qca808x_soft_reset(struct phy + if (ret < 0) + return ret; + +- return qca808x_phy_ms_seed_enable(phydev, true); ++ if (qca808x_has_fast_retrain_or_slave_seed(phydev)) ++ ret = qca808x_phy_ms_seed_enable(phydev, true); ++ ++ return ret; + } + + static bool qca808x_cdt_fault_length_valid(int cdt_code) diff --git a/target/linux/generic/backport-6.1/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch b/target/linux/generic/backport-6.1/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch new file mode 100644 index 0000000000..e382cf7876 --- /dev/null +++ b/target/linux/generic/backport-6.1/706-v6.6-06-net-phy-at803x-add-qca8081-fifo-reset-on-the-link-ch.patch @@ -0,0 +1,55 @@ +From 723970affdd8766fa0d91cd34bf2ffc861538b5f Mon Sep 17 00:00:00 2001 +From: Luo Jie +Date: Sun, 16 Jul 2023 16:49:24 +0800 +Subject: [PATCH 6/6] net: phy: at803x: add qca8081 fifo reset on the link + changed + +The qca8081 sgmii fifo needs to be reset on link down and +released on the link up in case of any abnormal issue +such as the packet blocked on the PHY. + +Signed-off-by: Luo Jie +Reviewed-by: Andrew Lunn +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -276,6 +276,9 @@ + #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d + #define QCA808X_PHY_CHIP_TYPE_1G BIT(0) + ++#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072 ++#define QCA8081_PHY_FIFO_RSTN BIT(11) ++ + MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver"); + MODULE_AUTHOR("Matus Ujhelyi"); + MODULE_LICENSE("GPL"); +@@ -2037,6 +2040,16 @@ static int qca808x_get_features(struct p + return 0; + } + ++static void qca808x_link_change_notify(struct phy_device *phydev) ++{ ++ /* Assert interface sgmii fifo on link down, deassert it on link up, ++ * the interface device address is always phy address added by 1. ++ */ ++ mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++} ++ + static struct phy_driver at803x_driver[] = { + { + /* Qualcomm Atheros AR8035 */ +@@ -2213,6 +2226,7 @@ static struct phy_driver at803x_driver[] + .soft_reset = qca808x_soft_reset, + .cable_test_start = qca808x_cable_test_start, + .cable_test_get_status = qca808x_cable_test_get_status, ++ .link_change_notify = qca808x_link_change_notify, + }, }; + + module_phy_driver(at803x_driver); diff --git a/target/linux/generic/backport-6.1/707-v6.8-01-net-phy-at803x-fix-passing-the-wrong-reference-for-c.patch b/target/linux/generic/backport-6.1/707-v6.8-01-net-phy-at803x-fix-passing-the-wrong-reference-for-c.patch new file mode 100644 index 0000000000..b206b18052 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-01-net-phy-at803x-fix-passing-the-wrong-reference-for-c.patch @@ -0,0 +1,45 @@ +From f8fdbf3389f44c7026f16e36cb1f2ff017f7f5b2 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:48 +0100 +Subject: [PATCH 01/13] net: phy: at803x: fix passing the wrong reference for + config_intr + +Fix passing the wrong reference for config_initr on passing the function +pointer, drop the wrong & from at803x_config_intr in the PHY struct. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -2104,7 +2104,7 @@ static struct phy_driver at803x_driver[] + .write_page = at803x_write_page, + .get_features = at803x_get_features, + .read_status = at803x_read_status, +- .config_intr = &at803x_config_intr, ++ .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, +@@ -2134,7 +2134,7 @@ static struct phy_driver at803x_driver[] + .resume = at803x_resume, + .flags = PHY_POLL_CABLE_TEST, + /* PHY_BASIC_FEATURES */ +- .config_intr = &at803x_config_intr, ++ .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, + .cable_test_get_status = at803x_cable_test_get_status, +@@ -2150,7 +2150,7 @@ static struct phy_driver at803x_driver[] + .resume = at803x_resume, + .flags = PHY_POLL_CABLE_TEST, + /* PHY_BASIC_FEATURES */ +- .config_intr = &at803x_config_intr, ++ .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, + .cable_test_get_status = at803x_cable_test_get_status, diff --git a/target/linux/generic/backport-6.1/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch b/target/linux/generic/backport-6.1/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch new file mode 100644 index 0000000000..eb9172b1cc --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-02-net-phy-at803x-move-disable-WOL-to-specific-at8031-p.patch @@ -0,0 +1,69 @@ +From 6a3b8c573b5a152a6aa7a0b54c5e18b84c6ba6f5 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:49 +0100 +Subject: [PATCH 02/13] net: phy: at803x: move disable WOL to specific at8031 + probe + +Move the WOL disable call to specific at8031 probe to make at803x_probe +more generic and drop extra check for PHY ID. + +Keep the same previous behaviour by first calling at803x_probe and then +disabling WOL. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -886,15 +886,6 @@ static int at803x_probe(struct phy_devic + priv->is_fiber = true; + break; + } +- +- /* Disable WoL in 1588 register which is enabled +- * by default +- */ +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +- if (ret) +- return ret; + } + + return 0; +@@ -1591,6 +1582,22 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_probe(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ /* Disable WoL in 1588 register which is enabled ++ * by default ++ */ ++ return phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2092,7 +2099,7 @@ static struct phy_driver at803x_driver[] + PHY_ID_MATCH_EXACT(ATH8031_PHY_ID), + .name = "Qualcomm Atheros AR8031/AR8033", + .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, ++ .probe = at8031_probe, + .config_init = at803x_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, diff --git a/target/linux/generic/backport-6.1/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch b/target/linux/generic/backport-6.1/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch new file mode 100644 index 0000000000..5a9d1764f1 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-03-net-phy-at803x-raname-hw_stats-functions-to-qca83xx-.patch @@ -0,0 +1,129 @@ +From 07b1ad83b9ed6db1735ba10baf67b7a565ac0cef Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:50 +0100 +Subject: [PATCH 03/13] net: phy: at803x: raname hw_stats functions to qca83xx + specific name + +The function and the struct related to hw_stats were specific to qca83xx +PHY but were called following the convention in the driver of calling +everything with at803x prefix. + +To better organize the code, rename these function a more specific name +to better describe that they are specific to 83xx PHY family. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 44 ++++++++++++++++++++-------------------- + 1 file changed, 22 insertions(+), 22 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -295,7 +295,7 @@ struct at803x_hw_stat { + enum stat_access_type access_type; + }; + +-static struct at803x_hw_stat at803x_hw_stats[] = { ++static struct at803x_hw_stat qca83xx_hw_stats[] = { + { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY}, + { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY}, + { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, +@@ -311,7 +311,7 @@ struct at803x_priv { + bool is_1000basex; + struct regulator_dev *vddio_rdev; + struct regulator_dev *vddh_rdev; +- u64 stats[ARRAY_SIZE(at803x_hw_stats)]; ++ u64 stats[ARRAY_SIZE(qca83xx_hw_stats)]; + }; + + struct at803x_context { +@@ -529,24 +529,24 @@ static void at803x_get_wol(struct phy_de + wol->wolopts |= WAKE_MAGIC; + } + +-static int at803x_get_sset_count(struct phy_device *phydev) ++static int qca83xx_get_sset_count(struct phy_device *phydev) + { +- return ARRAY_SIZE(at803x_hw_stats); ++ return ARRAY_SIZE(qca83xx_hw_stats); + } + +-static void at803x_get_strings(struct phy_device *phydev, u8 *data) ++static void qca83xx_get_strings(struct phy_device *phydev, u8 *data) + { + int i; + +- for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) { ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) { + strscpy(data + i * ETH_GSTRING_LEN, +- at803x_hw_stats[i].string, ETH_GSTRING_LEN); ++ qca83xx_hw_stats[i].string, ETH_GSTRING_LEN); + } + } + +-static u64 at803x_get_stat(struct phy_device *phydev, int i) ++static u64 qca83xx_get_stat(struct phy_device *phydev, int i) + { +- struct at803x_hw_stat stat = at803x_hw_stats[i]; ++ struct at803x_hw_stat stat = qca83xx_hw_stats[i]; + struct at803x_priv *priv = phydev->priv; + int val; + u64 ret; +@@ -567,13 +567,13 @@ static u64 at803x_get_stat(struct phy_de + return ret; + } + +-static void at803x_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) ++static void qca83xx_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) + { + int i; + +- for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) +- data[i] = at803x_get_stat(phydev, i); ++ for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++) ++ data[i] = qca83xx_get_stat(phydev, i); + } + + static int at803x_suspend(struct phy_device *phydev) +@@ -2175,9 +2175,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { +@@ -2191,9 +2191,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { +@@ -2207,9 +2207,9 @@ static struct phy_driver at803x_driver[] + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, + .soft_reset = genphy_soft_reset, +- .get_sset_count = at803x_get_sset_count, +- .get_strings = at803x_get_strings, +- .get_stats = at803x_get_stats, ++ .get_sset_count = qca83xx_get_sset_count, ++ .get_strings = qca83xx_get_strings, ++ .get_stats = qca83xx_get_stats, + .suspend = qca83xx_suspend, + .resume = qca83xx_resume, + }, { diff --git a/target/linux/generic/backport-6.1/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch b/target/linux/generic/backport-6.1/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch new file mode 100644 index 0000000000..f09142c5ed --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-04-net-phy-at803x-move-qca83xx-specific-check-in-dedica.patch @@ -0,0 +1,155 @@ +From d43cff3f82336c0bd965ea552232d9f4ddac71a6 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:51 +0100 +Subject: [PATCH 04/13] net: phy: at803x: move qca83xx specific check in + dedicated functions + +Rework qca83xx specific check to dedicated function to tidy things up +and drop useless phy_id check. + +Also drop an useless link_change_notify for QCA8337 as it did nothing an +returned early. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 68 ++++++++++++++++++++++------------------ + 1 file changed, 37 insertions(+), 31 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1623,27 +1623,26 @@ static int qca83xx_config_init(struct ph + break; + } + ++ /* Following original QCA sourcecode set port to prefer master */ ++ phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); ++ ++ return 0; ++} ++ ++static int qca8327_config_init(struct phy_device *phydev) ++{ + /* QCA8327 require DAC amplitude adjustment for 100m set to +6%. + * Disable on init and enable only with 100m speed following + * qca original source code. + */ +- if (phydev->drv->phy_id == QCA8327_A_PHY_ID || +- phydev->drv->phy_id == QCA8327_B_PHY_ID) +- at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, +- QCA8327_DEBUG_MANU_CTRL_EN, 0); ++ at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, ++ QCA8327_DEBUG_MANU_CTRL_EN, 0); + +- /* Following original QCA sourcecode set port to prefer master */ +- phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER); +- +- return 0; ++ return qca83xx_config_init(phydev); + } + + static void qca83xx_link_change_notify(struct phy_device *phydev) + { +- /* QCA8337 doesn't require DAC Amplitude adjustement */ +- if (phydev->drv->phy_id == QCA8337_PHY_ID) +- return; +- + /* Set DAC Amplitude adjustment to +6% for 100m on link running */ + if (phydev->state == PHY_RUNNING) { + if (phydev->speed == SPEED_100) +@@ -1686,19 +1685,6 @@ static int qca83xx_resume(struct phy_dev + + static int qca83xx_suspend(struct phy_device *phydev) + { +- u16 mask = 0; +- +- /* Only QCA8337 support actual suspend. +- * QCA8327 cause port unreliability when phy suspend +- * is set. +- */ +- if (phydev->drv->phy_id == QCA8337_PHY_ID) { +- genphy_suspend(phydev); +- } else { +- mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); +- phy_modify(phydev, MII_BMCR, mask, 0); +- } +- + at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN, + AT803X_DEBUG_GATE_CLK_IN1000, 0); + +@@ -1709,6 +1695,27 @@ static int qca83xx_suspend(struct phy_de + return 0; + } + ++static int qca8337_suspend(struct phy_device *phydev) ++{ ++ /* Only QCA8337 support actual suspend. */ ++ genphy_suspend(phydev); ++ ++ return qca83xx_suspend(phydev); ++} ++ ++static int qca8327_suspend(struct phy_device *phydev) ++{ ++ u16 mask = 0; ++ ++ /* QCA8327 cause port unreliability when phy suspend ++ * is set. ++ */ ++ mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX); ++ phy_modify(phydev, MII_BMCR, mask, 0); ++ ++ return qca83xx_suspend(phydev); ++} ++ + static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) + { + int ret; +@@ -2170,7 +2177,6 @@ static struct phy_driver at803x_driver[] + .phy_id_mask = QCA8K_PHY_ID_MASK, + .name = "Qualcomm Atheros 8337 internal PHY", + /* PHY_GBIT_FEATURES */ +- .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, + .config_init = qca83xx_config_init, +@@ -2178,7 +2184,7 @@ static struct phy_driver at803x_driver[] + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8337_suspend, + .resume = qca83xx_resume, + }, { + /* QCA8327-A from switch QCA8327-AL1A */ +@@ -2189,12 +2195,12 @@ static struct phy_driver at803x_driver[] + .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, ++ .config_init = qca8327_config_init, + .soft_reset = genphy_soft_reset, + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8327_suspend, + .resume = qca83xx_resume, + }, { + /* QCA8327-B from switch QCA8327-BL1A */ +@@ -2205,12 +2211,12 @@ static struct phy_driver at803x_driver[] + .link_change_notify = qca83xx_link_change_notify, + .probe = at803x_probe, + .flags = PHY_IS_INTERNAL, +- .config_init = qca83xx_config_init, ++ .config_init = qca8327_config_init, + .soft_reset = genphy_soft_reset, + .get_sset_count = qca83xx_get_sset_count, + .get_strings = qca83xx_get_strings, + .get_stats = qca83xx_get_stats, +- .suspend = qca83xx_suspend, ++ .suspend = qca8327_suspend, + .resume = qca83xx_resume, + }, { + /* Qualcomm QCA8081 */ diff --git a/target/linux/generic/backport-6.1/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch b/target/linux/generic/backport-6.1/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch new file mode 100644 index 0000000000..a5cc67a8c8 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-05-net-phy-at803x-move-specific-DT-option-for-at8031-to.patch @@ -0,0 +1,94 @@ +From 900eef75cc5018e149c52fe305c9c3fe424c52a7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:52 +0100 +Subject: [PATCH 05/13] net: phy: at803x: move specific DT option for at8031 to + specific probe + +Move specific DT options for at8031 to specific probe to tidy things up +and make at803x_parse_dt more generic. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 55 ++++++++++++++++++++++------------------ + 1 file changed, 31 insertions(+), 24 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -825,30 +825,6 @@ static int at803x_parse_dt(struct phy_de + } + } + +- /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping +- * options. +- */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- if (of_property_read_bool(node, "qca,keep-pll-enabled")) +- priv->flags |= AT803X_KEEP_PLL_ENABLED; +- +- ret = at8031_register_regulators(phydev); +- if (ret < 0) +- return ret; +- +- ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, +- "vddio"); +- if (ret) { +- phydev_err(phydev, "failed to get VDDIO regulator\n"); +- return ret; +- } +- +- /* Only AR8031/8033 support 1000Base-X for SFP modules */ +- ret = phy_sfp_probe(phydev, &at803x_sfp_ops); +- if (ret < 0) +- return ret; +- } +- + return 0; + } + +@@ -1582,6 +1558,30 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_parse_dt(struct phy_device *phydev) ++{ ++ struct device_node *node = phydev->mdio.dev.of_node; ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ if (of_property_read_bool(node, "qca,keep-pll-enabled")) ++ priv->flags |= AT803X_KEEP_PLL_ENABLED; ++ ++ ret = at8031_register_regulators(phydev); ++ if (ret < 0) ++ return ret; ++ ++ ret = devm_regulator_get_enable_optional(&phydev->mdio.dev, ++ "vddio"); ++ if (ret) { ++ phydev_err(phydev, "failed to get VDDIO regulator\n"); ++ return ret; ++ } ++ ++ /* Only AR8031/8033 support 1000Base-X for SFP modules */ ++ return phy_sfp_probe(phydev, &at803x_sfp_ops); ++} ++ + static int at8031_probe(struct phy_device *phydev) + { + int ret; +@@ -1590,6 +1590,13 @@ static int at8031_probe(struct phy_devic + if (ret) + return ret; + ++ /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping ++ * options. ++ */ ++ ret = at8031_parse_dt(phydev); ++ if (ret) ++ return ret; ++ + /* Disable WoL in 1588 register which is enabled + * by default + */ diff --git a/target/linux/generic/backport-6.1/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch b/target/linux/generic/backport-6.1/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch new file mode 100644 index 0000000000..9e10e000e5 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-06-net-phy-at803x-move-specific-at8031-probe-mode-check.patch @@ -0,0 +1,78 @@ +From 25d2ba94005fac18fe68878cddff59a67e115554 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:53 +0100 +Subject: [PATCH 06/13] net: phy: at803x: move specific at8031 probe mode check + to dedicated probe + +Move specific at8031 probe mode check to dedicated probe to make +at803x_probe more generic and keep code tidy. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 39 +++++++++++++++++++-------------------- + 1 file changed, 19 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -844,26 +844,6 @@ static int at803x_probe(struct phy_devic + if (ret) + return ret; + +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); +- int mode_cfg; +- +- if (ccr < 0) +- return ccr; +- mode_cfg = ccr & AT803X_MODE_CFG_MASK; +- +- switch (mode_cfg) { +- case AT803X_MODE_CFG_BX1000_RGMII_50OHM: +- case AT803X_MODE_CFG_BX1000_RGMII_75OHM: +- priv->is_1000basex = true; +- fallthrough; +- case AT803X_MODE_CFG_FX100_RGMII_50OHM: +- case AT803X_MODE_CFG_FX100_RGMII_75OHM: +- priv->is_fiber = true; +- break; +- } +- } +- + return 0; + } + +@@ -1584,6 +1564,9 @@ static int at8031_parse_dt(struct phy_de + + static int at8031_probe(struct phy_device *phydev) + { ++ struct at803x_priv *priv = phydev->priv; ++ int mode_cfg; ++ int ccr; + int ret; + + ret = at803x_probe(phydev); +@@ -1597,6 +1580,22 @@ static int at8031_probe(struct phy_devic + if (ret) + return ret; + ++ ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); ++ if (ccr < 0) ++ return ccr; ++ mode_cfg = ccr & AT803X_MODE_CFG_MASK; ++ ++ switch (mode_cfg) { ++ case AT803X_MODE_CFG_BX1000_RGMII_50OHM: ++ case AT803X_MODE_CFG_BX1000_RGMII_75OHM: ++ priv->is_1000basex = true; ++ fallthrough; ++ case AT803X_MODE_CFG_FX100_RGMII_50OHM: ++ case AT803X_MODE_CFG_FX100_RGMII_75OHM: ++ priv->is_fiber = true; ++ break; ++ } ++ + /* Disable WoL in 1588 register which is enabled + * by default + */ diff --git a/target/linux/generic/backport-6.1/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch b/target/linux/generic/backport-6.1/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch new file mode 100644 index 0000000000..c9ef6df827 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-07-net-phy-at803x-move-specific-at8031-config_init-to-d.patch @@ -0,0 +1,86 @@ +From 3ae3bc426eaf57ca8f53d75777d9a5ef779bc7b7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:54 +0100 +Subject: [PATCH 07/13] net: phy: at803x: move specific at8031 config_init to + dedicated function + +Move specific at8031 config_init to dedicated function to make +at803x_config_init more generic and tidy things up. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 45 ++++++++++++++++++++++------------------ + 1 file changed, 25 insertions(+), 20 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -951,27 +951,8 @@ static int at803x_hibernation_mode_confi + + static int at803x_config_init(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int ret; + +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- /* Some bootloaders leave the fiber page selected. +- * Switch to the appropriate page (fiber or copper), as otherwise we +- * read the PHY capabilities from the wrong page. +- */ +- phy_lock_mdio_bus(phydev); +- ret = at803x_write_page(phydev, +- priv->is_fiber ? AT803X_PAGE_FIBER : +- AT803X_PAGE_COPPER); +- phy_unlock_mdio_bus(phydev); +- if (ret) +- return ret; +- +- ret = at8031_pll_config(phydev); +- if (ret < 0) +- return ret; +- } +- + /* The RX and TX delay default is: + * after HW reset: RX delay enabled and TX delay disabled + * after SW reset: RX delay enabled, while TX delay retains the +@@ -1604,6 +1585,30 @@ static int at8031_probe(struct phy_devic + AT803X_WOL_EN, 0); + } + ++static int at8031_config_init(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; ++ ++ /* Some bootloaders leave the fiber page selected. ++ * Switch to the appropriate page (fiber or copper), as otherwise we ++ * read the PHY capabilities from the wrong page. ++ */ ++ phy_lock_mdio_bus(phydev); ++ ret = at803x_write_page(phydev, ++ priv->is_fiber ? AT803X_PAGE_FIBER : ++ AT803X_PAGE_COPPER); ++ phy_unlock_mdio_bus(phydev); ++ if (ret) ++ return ret; ++ ++ ret = at8031_pll_config(phydev); ++ if (ret < 0) ++ return ret; ++ ++ return at803x_config_init(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2113,7 +2118,7 @@ static struct phy_driver at803x_driver[] + .name = "Qualcomm Atheros AR8031/AR8033", + .flags = PHY_POLL_CABLE_TEST, + .probe = at8031_probe, +- .config_init = at803x_config_init, ++ .config_init = at8031_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, + .set_wol = at803x_set_wol, diff --git a/target/linux/generic/backport-6.1/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch b/target/linux/generic/backport-6.1/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch new file mode 100644 index 0000000000..6746a4d43c --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-08-net-phy-at803x-move-specific-at8031-WOL-bits-to-dedi.patch @@ -0,0 +1,92 @@ +From 27b89c9dc1b0393090d68d651b82f30ad2696baa Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:55 +0100 +Subject: [PATCH 08/13] net: phy: at803x: move specific at8031 WOL bits to + dedicated function + +Move specific at8031 WOL enable/disable to dedicated function to make +at803x_set_wol more generic. + +This is needed in preparation for PHY driver split as qca8081 share the +same function to toggle WOL settings. + +In this new implementation WOL module in at8031 is enabled after the +generic interrupt is setup. This should not cause any problem as the +WOL_INT has a separate implementation and only relay on MAC bits. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 42 ++++++++++++++++++++++++---------------- + 1 file changed, 25 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -466,27 +466,11 @@ static int at803x_set_wol(struct phy_dev + phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], + mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); + +- /* Enable WOL function for 1588 */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- 0, AT803X_WOL_EN); +- if (ret) +- return ret; +- } + /* Enable WOL interrupt */ + ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); + if (ret) + return ret; + } else { +- /* Disable WoL function for 1588 */ +- if (phydev->drv->phy_id == ATH8031_PHY_ID) { +- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, +- AT803X_PHY_MMD3_WOL_CTRL, +- AT803X_WOL_EN, 0); +- if (ret) +- return ret; +- } + /* Disable WOL interrupt */ + ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); + if (ret) +@@ -1609,6 +1593,30 @@ static int at8031_config_init(struct phy + return at803x_config_init(phydev); + } + ++static int at8031_set_wol(struct phy_device *phydev, ++ struct ethtool_wolinfo *wol) ++{ ++ int ret; ++ ++ /* First setup MAC address and enable WOL interrupt */ ++ ret = at803x_set_wol(phydev, wol); ++ if (ret) ++ return ret; ++ ++ if (wol->wolopts & WAKE_MAGIC) ++ /* Enable WOL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ 0, AT803X_WOL_EN); ++ else ++ /* Disable WoL function for 1588 */ ++ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, ++ AT803X_PHY_MMD3_WOL_CTRL, ++ AT803X_WOL_EN, 0); ++ ++ return ret; ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2121,7 +2129,7 @@ static struct phy_driver at803x_driver[] + .config_init = at8031_config_init, + .config_aneg = at803x_config_aneg, + .soft_reset = genphy_soft_reset, +- .set_wol = at803x_set_wol, ++ .set_wol = at8031_set_wol, + .get_wol = at803x_get_wol, + .suspend = at803x_suspend, + .resume = at803x_resume, diff --git a/target/linux/generic/backport-6.1/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch b/target/linux/generic/backport-6.1/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch new file mode 100644 index 0000000000..0d284c3d24 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-09-net-phy-at803x-move-specific-at8031-config_intr-to-d.patch @@ -0,0 +1,78 @@ +From 30dd62191d3dd97c08f7f9dc9ce77ffab457e4fb Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:56 +0100 +Subject: [PATCH 09/13] net: phy: at803x: move specific at8031 config_intr to + dedicated function + +Move specific at8031 config_intr bits to dedicated function to make +at803x_config_initr more generic. + +This is needed in preparation for PHY driver split as qca8081 share the +same function to setup interrupts. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -990,7 +990,6 @@ static int at803x_ack_interrupt(struct p + + static int at803x_config_intr(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int err; + int value; + +@@ -1007,10 +1006,6 @@ static int at803x_config_intr(struct phy + value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED; + value |= AT803X_INTR_ENABLE_LINK_FAIL; + value |= AT803X_INTR_ENABLE_LINK_SUCCESS; +- if (priv->is_fiber) { +- value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; +- value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; +- } + + err = phy_write(phydev, AT803X_INTR_ENABLE, value); + } else { +@@ -1617,6 +1612,29 @@ static int at8031_set_wol(struct phy_dev + return ret; + } + ++static int at8031_config_intr(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int err, value = 0; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED && ++ priv->is_fiber) { ++ /* Clear any pending interrupts */ ++ err = at803x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ value |= AT803X_INTR_ENABLE_LINK_FAIL_BX; ++ value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX; ++ ++ err = phy_set_bits(phydev, AT803X_INTR_ENABLE, value); ++ if (err) ++ return err; ++ } ++ ++ return at803x_config_intr(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2137,7 +2155,7 @@ static struct phy_driver at803x_driver[] + .write_page = at803x_write_page, + .get_features = at803x_get_features, + .read_status = at803x_read_status, +- .config_intr = at803x_config_intr, ++ .config_intr = at8031_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, diff --git a/target/linux/generic/backport-6.1/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch b/target/linux/generic/backport-6.1/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch new file mode 100644 index 0000000000..210949ea81 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-10-net-phy-at803x-make-at8031-related-DT-functions-name.patch @@ -0,0 +1,78 @@ +From a5ab9d8e7ae0da8328ac1637a9755311508dc8ab Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:57 +0100 +Subject: [PATCH 10/13] net: phy: at803x: make at8031 related DT functions name + more specific + +Rename at8031 related DT function name to a more specific name +referencing they are only related to at8031 and not to the generic +at803x PHY family. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -583,7 +583,7 @@ static int at803x_resume(struct phy_devi + return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); + } + +-static int at803x_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, ++static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) + { + struct phy_device *phydev = rdev_get_drvdata(rdev); +@@ -596,7 +596,7 @@ static int at803x_rgmii_reg_set_voltage_ + AT803X_DEBUG_RGMII_1V8, 0); + } + +-static int at803x_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) ++static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) + { + struct phy_device *phydev = rdev_get_drvdata(rdev); + int val; +@@ -610,8 +610,8 @@ static int at803x_rgmii_reg_get_voltage_ + + static const struct regulator_ops vddio_regulator_ops = { + .list_voltage = regulator_list_voltage_table, +- .set_voltage_sel = at803x_rgmii_reg_set_voltage_sel, +- .get_voltage_sel = at803x_rgmii_reg_get_voltage_sel, ++ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, ++ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, + }; + + static const unsigned int vddio_voltage_table[] = { +@@ -666,7 +666,7 @@ static int at8031_register_regulators(st + return 0; + } + +-static int at803x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) + { + struct phy_device *phydev = upstream; + __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); +@@ -710,10 +710,10 @@ static int at803x_sfp_insert(void *upstr + return 0; + } + +-static const struct sfp_upstream_ops at803x_sfp_ops = { ++static const struct sfp_upstream_ops at8031_sfp_ops = { + .attach = phy_sfp_attach, + .detach = phy_sfp_detach, +- .module_insert = at803x_sfp_insert, ++ .module_insert = at8031_sfp_insert, + }; + + static int at803x_parse_dt(struct phy_device *phydev) +@@ -1519,7 +1519,7 @@ static int at8031_parse_dt(struct phy_de + } + + /* Only AR8031/8033 support 1000Base-X for SFP modules */ +- return phy_sfp_probe(phydev, &at803x_sfp_ops); ++ return phy_sfp_probe(phydev, &at8031_sfp_ops); + } + + static int at8031_probe(struct phy_device *phydev) diff --git a/target/linux/generic/backport-6.1/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch b/target/linux/generic/backport-6.1/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch new file mode 100644 index 0000000000..5856b59751 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-11-net-phy-at803x-move-at8031-functions-in-dedicated-se.patch @@ -0,0 +1,297 @@ +From f932a6dc8bae0dae9645b5b1b4c65aed8a8acb2a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:58 +0100 +Subject: [PATCH 11/13] net: phy: at803x: move at8031 functions in dedicated + section + +Move at8031 functions in dedicated section with dedicated at8031 +parse_dt and probe. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 266 +++++++++++++++++++-------------------- + 1 file changed, 133 insertions(+), 133 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -583,139 +583,6 @@ static int at803x_resume(struct phy_devi + return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0); + } + +-static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, +- unsigned int selector) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- +- if (selector) +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- 0, AT803X_DEBUG_RGMII_1V8); +- else +- return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, +- AT803X_DEBUG_RGMII_1V8, 0); +-} +- +-static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) +-{ +- struct phy_device *phydev = rdev_get_drvdata(rdev); +- int val; +- +- val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); +- if (val < 0) +- return val; +- +- return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; +-} +- +-static const struct regulator_ops vddio_regulator_ops = { +- .list_voltage = regulator_list_voltage_table, +- .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, +- .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, +-}; +- +-static const unsigned int vddio_voltage_table[] = { +- 1500000, +- 1800000, +-}; +- +-static const struct regulator_desc vddio_desc = { +- .name = "vddio", +- .of_match = of_match_ptr("vddio-regulator"), +- .n_voltages = ARRAY_SIZE(vddio_voltage_table), +- .volt_table = vddio_voltage_table, +- .ops = &vddio_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static const struct regulator_ops vddh_regulator_ops = { +-}; +- +-static const struct regulator_desc vddh_desc = { +- .name = "vddh", +- .of_match = of_match_ptr("vddh-regulator"), +- .n_voltages = 1, +- .fixed_uV = 2500000, +- .ops = &vddh_regulator_ops, +- .type = REGULATOR_VOLTAGE, +- .owner = THIS_MODULE, +-}; +- +-static int at8031_register_regulators(struct phy_device *phydev) +-{ +- struct at803x_priv *priv = phydev->priv; +- struct device *dev = &phydev->mdio.dev; +- struct regulator_config config = { }; +- +- config.dev = dev; +- config.driver_data = phydev; +- +- priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); +- if (IS_ERR(priv->vddio_rdev)) { +- phydev_err(phydev, "failed to register VDDIO regulator\n"); +- return PTR_ERR(priv->vddio_rdev); +- } +- +- priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); +- if (IS_ERR(priv->vddh_rdev)) { +- phydev_err(phydev, "failed to register VDDH regulator\n"); +- return PTR_ERR(priv->vddh_rdev); +- } +- +- return 0; +-} +- +-static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) +-{ +- struct phy_device *phydev = upstream; +- __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); +- __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); +- DECLARE_PHY_INTERFACE_MASK(interfaces); +- phy_interface_t iface; +- +- linkmode_zero(phy_support); +- phylink_set(phy_support, 1000baseX_Full); +- phylink_set(phy_support, 1000baseT_Full); +- phylink_set(phy_support, Autoneg); +- phylink_set(phy_support, Pause); +- phylink_set(phy_support, Asym_Pause); +- +- linkmode_zero(sfp_support); +- sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); +- /* Some modules support 10G modes as well as others we support. +- * Mask out non-supported modes so the correct interface is picked. +- */ +- linkmode_and(sfp_support, phy_support, sfp_support); +- +- if (linkmode_empty(sfp_support)) { +- dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); +- return -EINVAL; +- } +- +- iface = sfp_select_interface(phydev->sfp_bus, sfp_support); +- +- /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes +- * interface for use with SFP modules. +- * However, some copper modules detected as having a preferred SGMII +- * interface do default to and function in 1000Base-X mode, so just +- * print a warning and allow such modules, as they may have some chance +- * of working. +- */ +- if (iface == PHY_INTERFACE_MODE_SGMII) +- dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); +- else if (iface != PHY_INTERFACE_MODE_1000BASEX) +- return -EINVAL; +- +- return 0; +-} +- +-static const struct sfp_upstream_ops at8031_sfp_ops = { +- .attach = phy_sfp_attach, +- .detach = phy_sfp_detach, +- .module_insert = at8031_sfp_insert, +-}; +- + static int at803x_parse_dt(struct phy_device *phydev) + { + struct device_node *node = phydev->mdio.dev.of_node; +@@ -1498,6 +1365,139 @@ static int at803x_cable_test_start(struc + return 0; + } + ++static int at8031_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev, ++ unsigned int selector) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ ++ if (selector) ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ 0, AT803X_DEBUG_RGMII_1V8); ++ else ++ return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F, ++ AT803X_DEBUG_RGMII_1V8, 0); ++} ++ ++static int at8031_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev) ++{ ++ struct phy_device *phydev = rdev_get_drvdata(rdev); ++ int val; ++ ++ val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F); ++ if (val < 0) ++ return val; ++ ++ return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0; ++} ++ ++static const struct regulator_ops vddio_regulator_ops = { ++ .list_voltage = regulator_list_voltage_table, ++ .set_voltage_sel = at8031_rgmii_reg_set_voltage_sel, ++ .get_voltage_sel = at8031_rgmii_reg_get_voltage_sel, ++}; ++ ++static const unsigned int vddio_voltage_table[] = { ++ 1500000, ++ 1800000, ++}; ++ ++static const struct regulator_desc vddio_desc = { ++ .name = "vddio", ++ .of_match = of_match_ptr("vddio-regulator"), ++ .n_voltages = ARRAY_SIZE(vddio_voltage_table), ++ .volt_table = vddio_voltage_table, ++ .ops = &vddio_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct regulator_ops vddh_regulator_ops = { ++}; ++ ++static const struct regulator_desc vddh_desc = { ++ .name = "vddh", ++ .of_match = of_match_ptr("vddh-regulator"), ++ .n_voltages = 1, ++ .fixed_uV = 2500000, ++ .ops = &vddh_regulator_ops, ++ .type = REGULATOR_VOLTAGE, ++ .owner = THIS_MODULE, ++}; ++ ++static int at8031_register_regulators(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ struct regulator_config config = { }; ++ ++ config.dev = dev; ++ config.driver_data = phydev; ++ ++ priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config); ++ if (IS_ERR(priv->vddio_rdev)) { ++ phydev_err(phydev, "failed to register VDDIO regulator\n"); ++ return PTR_ERR(priv->vddio_rdev); ++ } ++ ++ priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config); ++ if (IS_ERR(priv->vddh_rdev)) { ++ phydev_err(phydev, "failed to register VDDH regulator\n"); ++ return PTR_ERR(priv->vddh_rdev); ++ } ++ ++ return 0; ++} ++ ++static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) ++{ ++ struct phy_device *phydev = upstream; ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); ++ DECLARE_PHY_INTERFACE_MASK(interfaces); ++ phy_interface_t iface; ++ ++ linkmode_zero(phy_support); ++ phylink_set(phy_support, 1000baseX_Full); ++ phylink_set(phy_support, 1000baseT_Full); ++ phylink_set(phy_support, Autoneg); ++ phylink_set(phy_support, Pause); ++ phylink_set(phy_support, Asym_Pause); ++ ++ linkmode_zero(sfp_support); ++ sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); ++ /* Some modules support 10G modes as well as others we support. ++ * Mask out non-supported modes so the correct interface is picked. ++ */ ++ linkmode_and(sfp_support, phy_support, sfp_support); ++ ++ if (linkmode_empty(sfp_support)) { ++ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); ++ return -EINVAL; ++ } ++ ++ iface = sfp_select_interface(phydev->sfp_bus, sfp_support); ++ ++ /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes ++ * interface for use with SFP modules. ++ * However, some copper modules detected as having a preferred SGMII ++ * interface do default to and function in 1000Base-X mode, so just ++ * print a warning and allow such modules, as they may have some chance ++ * of working. ++ */ ++ if (iface == PHY_INTERFACE_MODE_SGMII) ++ dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); ++ else if (iface != PHY_INTERFACE_MODE_1000BASEX) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static const struct sfp_upstream_ops at8031_sfp_ops = { ++ .attach = phy_sfp_attach, ++ .detach = phy_sfp_detach, ++ .module_insert = at8031_sfp_insert, ++}; ++ + static int at8031_parse_dt(struct phy_device *phydev) + { + struct device_node *node = phydev->mdio.dev.of_node; diff --git a/target/linux/generic/backport-6.1/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch b/target/linux/generic/backport-6.1/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch new file mode 100644 index 0000000000..0a822c6d37 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-12-net-phy-at803x-move-at8035-specific-DT-parse-to-dedi.patch @@ -0,0 +1,114 @@ +From 21a2802a8365cfa82cc02187c1f95136d85592ad Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:51:59 +0100 +Subject: [PATCH 12/13] net: phy: at803x: move at8035 specific DT parse to + dedicated probe + +Move at8035 specific DT parse for clock out frequency to dedicated probe +to make at803x probe function more generic. + +This is to tidy code and no behaviour change are intended. + +Detection logic is changed, we check if the clk 25m mask is set and if +it's not zero, we assume the qca,clk-out-frequency property is set. + +The property is checked in the generic at803x_parse_dt called by +at803x_probe. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 60 +++++++++++++++++++++++++++------------- + 1 file changed, 41 insertions(+), 19 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -638,23 +638,6 @@ static int at803x_parse_dt(struct phy_de + + priv->clk_25m_reg |= FIELD_PREP(AT803X_CLK_OUT_MASK, sel); + priv->clk_25m_mask |= AT803X_CLK_OUT_MASK; +- +- /* Fixup for the AR8030/AR8035. This chip has another mask and +- * doesn't support the DSP reference. Eg. the lowest bit of the +- * mask. The upper two bits select the same frequencies. Mask +- * the lowest bit here. +- * +- * Warning: +- * There was no datasheet for the AR8030 available so this is +- * just a guess. But the AR8035 is listed as pin compatible +- * to the AR8030 so there might be a good chance it works on +- * the AR8030 too. +- */ +- if (phydev->drv->phy_id == ATH8030_PHY_ID || +- phydev->drv->phy_id == ATH8035_PHY_ID) { +- priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; +- priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; +- } + } + + ret = of_property_read_u32(node, "qca,clk-out-strength", &strength); +@@ -1635,6 +1618,45 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++static int at8035_parse_dt(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ /* Mask is set by the generic at803x_parse_dt ++ * if property is set. Assume property is set ++ * with the mask not zero. ++ */ ++ if (priv->clk_25m_mask) { ++ /* Fixup for the AR8030/AR8035. This chip has another mask and ++ * doesn't support the DSP reference. Eg. the lowest bit of the ++ * mask. The upper two bits select the same frequencies. Mask ++ * the lowest bit here. ++ * ++ * Warning: ++ * There was no datasheet for the AR8030 available so this is ++ * just a guess. But the AR8035 is listed as pin compatible ++ * to the AR8030 so there might be a good chance it works on ++ * the AR8030 too. ++ */ ++ priv->clk_25m_reg &= AT8035_CLK_OUT_MASK; ++ priv->clk_25m_mask &= AT8035_CLK_OUT_MASK; ++ } ++ ++ return 0; ++} ++ ++/* AR8030 and AR8035 shared the same special mask for clk_25m */ ++static int at8035_probe(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = at803x_probe(phydev); ++ if (ret) ++ return ret; ++ ++ return at8035_parse_dt(phydev); ++} ++ + static int qca83xx_config_init(struct phy_device *phydev) + { + u8 switch_revision; +@@ -2107,7 +2129,7 @@ static struct phy_driver at803x_driver[] + PHY_ID_MATCH_EXACT(ATH8035_PHY_ID), + .name = "Qualcomm Atheros AR8035", + .flags = PHY_POLL_CABLE_TEST, +- .probe = at803x_probe, ++ .probe = at8035_probe, + .config_aneg = at803x_config_aneg, + .config_init = at803x_config_init, + .soft_reset = genphy_soft_reset, +@@ -2128,7 +2150,7 @@ static struct phy_driver at803x_driver[] + .phy_id = ATH8030_PHY_ID, + .name = "Qualcomm Atheros AR8030", + .phy_id_mask = AT8030_PHY_ID_MASK, +- .probe = at803x_probe, ++ .probe = at8035_probe, + .config_init = at803x_config_init, + .link_change_notify = at803x_link_change_notify, + .set_wol = at803x_set_wol, diff --git a/target/linux/generic/backport-6.1/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch b/target/linux/generic/backport-6.1/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch new file mode 100644 index 0000000000..e1ba6ec2d0 --- /dev/null +++ b/target/linux/generic/backport-6.1/707-v6.8-13-net-phy-at803x-drop-specific-PHY-ID-check-from-cable.patch @@ -0,0 +1,219 @@ +From ef9df47b449e32e06501a11272809be49019bdb6 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 8 Dec 2023 15:52:00 +0100 +Subject: [PATCH 13/13] net: phy: at803x: drop specific PHY ID check from cable + test functions + +Drop specific PHY ID check for cable test functions for at803x. This is +done to make functions more generic. While at it better describe what +the functions does by using more symbolic function names. + +PHYs that requires to set additional reg are moved to specific function +calling the more generic one. + +cdt_start and cdt_wait_for_completion are changed to take an additional +arg to pass specific values specific to the PHY. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 95 +++++++++++++++++++++------------------- + 1 file changed, 50 insertions(+), 45 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1222,31 +1222,16 @@ static int at803x_cdt_fault_length(u16 s + return (dt * 824) / 10; + } + +-static int at803x_cdt_start(struct phy_device *phydev, int pair) ++static int at803x_cdt_start(struct phy_device *phydev, ++ u32 cdt_start) + { +- u16 cdt; +- +- /* qca8081 takes the different bit 15 to enable CDT test */ +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- cdt = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT | +- QCA808X_CDT_INTER_CHECK_DIS; +- else +- cdt = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | +- AT803X_CDT_ENABLE_TEST; +- +- return phy_write(phydev, AT803X_CDT, cdt); ++ return phy_write(phydev, AT803X_CDT, cdt_start); + } + +-static int at803x_cdt_wait_for_completion(struct phy_device *phydev) ++static int at803x_cdt_wait_for_completion(struct phy_device *phydev, ++ u32 cdt_en) + { + int val, ret; +- u16 cdt_en; +- +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- cdt_en = QCA808X_CDT_ENABLE_TEST; +- else +- cdt_en = AT803X_CDT_ENABLE_TEST; + + /* One test run takes about 25ms */ + ret = phy_read_poll_timeout(phydev, AT803X_CDT, val, +@@ -1266,11 +1251,13 @@ static int at803x_cable_test_one_pair(st + }; + int ret, val; + +- ret = at803x_cdt_start(phydev, pair); ++ val = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) | ++ AT803X_CDT_ENABLE_TEST; ++ ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; + +- ret = at803x_cdt_wait_for_completion(phydev); ++ ret = at803x_cdt_wait_for_completion(phydev, AT803X_CDT_ENABLE_TEST); + if (ret) + return ret; + +@@ -1292,19 +1279,11 @@ static int at803x_cable_test_one_pair(st + } + + static int at803x_cable_test_get_status(struct phy_device *phydev, +- bool *finished) ++ bool *finished, unsigned long pair_mask) + { +- unsigned long pair_mask; + int retries = 20; + int pair, ret; + +- if (phydev->phy_id == ATH9331_PHY_ID || +- phydev->phy_id == ATH8032_PHY_ID || +- phydev->phy_id == QCA9561_PHY_ID) +- pair_mask = 0x3; +- else +- pair_mask = 0xf; +- + *finished = false; + + /* According to the datasheet the CDT can be performed when +@@ -1331,7 +1310,7 @@ static int at803x_cable_test_get_status( + return 0; + } + +-static int at803x_cable_test_start(struct phy_device *phydev) ++static void at803x_cable_test_autoneg(struct phy_device *phydev) + { + /* Enable auto-negotiation, but advertise no capabilities, no link + * will be established. A restart of the auto-negotiation is not +@@ -1339,11 +1318,11 @@ static int at803x_cable_test_start(struc + */ + phy_write(phydev, MII_BMCR, BMCR_ANENABLE); + phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA); +- if (phydev->phy_id != ATH9331_PHY_ID && +- phydev->phy_id != ATH8032_PHY_ID && +- phydev->phy_id != QCA9561_PHY_ID) +- phy_write(phydev, MII_CTRL1000, 0); ++} + ++static int at803x_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); + /* we do all the (time consuming) work later */ + return 0; + } +@@ -1618,6 +1597,29 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++/* AR8031 and AR8035 share the same cable test get status reg */ ++static int at8031_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0xf); ++} ++ ++/* AR8031 and AR8035 share the same cable test start logic */ ++static int at8031_cable_test_start(struct phy_device *phydev) ++{ ++ at803x_cable_test_autoneg(phydev); ++ phy_write(phydev, MII_CTRL1000, 0); ++ /* we do all the (time consuming) work later */ ++ return 0; ++} ++ ++/* AR8032, AR9331 and QCA9561 share the same cable test get status reg */ ++static int at8032_cable_test_get_status(struct phy_device *phydev, ++ bool *finished) ++{ ++ return at803x_cable_test_get_status(phydev, finished, 0x3); ++} ++ + static int at8035_parse_dt(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; +@@ -2041,11 +2043,14 @@ static int qca808x_cable_test_get_status + + *finished = false; + +- ret = at803x_cdt_start(phydev, 0); ++ val = QCA808X_CDT_ENABLE_TEST | ++ QCA808X_CDT_LENGTH_UNIT | ++ QCA808X_CDT_INTER_CHECK_DIS; ++ ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; + +- ret = at803x_cdt_wait_for_completion(phydev); ++ ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST); + if (ret) + return ret; + +@@ -2143,8 +2148,8 @@ static struct phy_driver at803x_driver[] + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, + }, { + /* Qualcomm Atheros AR8030 */ + .phy_id = ATH8030_PHY_ID, +@@ -2181,8 +2186,8 @@ static struct phy_driver at803x_driver[] + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, + .set_tunable = at803x_set_tunable, +- .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_start = at8031_cable_test_start, ++ .cable_test_get_status = at8031_cable_test_get_status, + }, { + /* Qualcomm Atheros AR8032 */ + PHY_ID_MATCH_EXACT(ATH8032_PHY_ID), +@@ -2197,7 +2202,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + }, { + /* ATHEROS AR9331 */ + PHY_ID_MATCH_EXACT(ATH9331_PHY_ID), +@@ -2210,7 +2215,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + .read_status = at803x_read_status, + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, +@@ -2226,7 +2231,7 @@ static struct phy_driver at803x_driver[] + .config_intr = at803x_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .cable_test_start = at803x_cable_test_start, +- .cable_test_get_status = at803x_cable_test_get_status, ++ .cable_test_get_status = at8032_cable_test_get_status, + .read_status = at803x_read_status, + .soft_reset = genphy_soft_reset, + .config_aneg = at803x_config_aneg, diff --git a/target/linux/generic/backport-6.1/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch b/target/linux/generic/backport-6.1/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch new file mode 100644 index 0000000000..0bb3673c02 --- /dev/null +++ b/target/linux/generic/backport-6.1/708-v6.8-01-net-phy-at803x-move-specific-qca808x-config_aneg-to-.patch @@ -0,0 +1,116 @@ +From 8e732f1c6f2dc5e18f766d0f1b11df9db2dd044a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 14 Dec 2023 01:44:31 +0100 +Subject: [PATCH 1/2] net: phy: at803x: move specific qca808x config_aneg to + dedicated function + +Move specific qca808x config_aneg to dedicated function to permit easier +split of qca808x portion from at803x driver. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 66 ++++++++++++++++++++++++---------------- + 1 file changed, 40 insertions(+), 26 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1045,9 +1045,8 @@ static int at803x_config_mdix(struct phy + FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); + } + +-static int at803x_config_aneg(struct phy_device *phydev) ++static int at803x_prepare_config_aneg(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + int ret; + + ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); +@@ -1064,33 +1063,22 @@ static int at803x_config_aneg(struct phy + return ret; + } + +- if (priv->is_1000basex) +- return genphy_c37_config_aneg(phydev); +- +- /* Do not restart auto-negotiation by setting ret to 0 defautly, +- * when calling __genphy_config_aneg later. +- */ +- ret = 0; +- +- if (phydev->drv->phy_id == QCA8081_PHY_ID) { +- int phy_ctrl = 0; ++ return 0; ++} + +- /* The reg MII_BMCR also needs to be configured for force mode, the +- * genphy_config_aneg is also needed. +- */ +- if (phydev->autoneg == AUTONEG_DISABLE) +- genphy_c45_pma_setup_forced(phydev); ++static int at803x_config_aneg(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ int ret; + +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) +- phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; + +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, +- MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); +- if (ret < 0) +- return ret; +- } ++ if (priv->is_1000basex) ++ return genphy_c37_config_aneg(phydev); + +- return __genphy_config_aneg(phydev, ret); ++ return genphy_config_aneg(phydev); + } + + static int at803x_get_downshift(struct phy_device *phydev, u8 *d) +@@ -2118,6 +2106,32 @@ static int qca808x_get_features(struct p + return 0; + } + ++static int qca808x_config_aneg(struct phy_device *phydev) ++{ ++ int phy_ctrl = 0; ++ int ret; ++ ++ ret = at803x_prepare_config_aneg(phydev); ++ if (ret) ++ return ret; ++ ++ /* The reg MII_BMCR also needs to be configured for force mode, the ++ * genphy_config_aneg is also needed. ++ */ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ genphy_c45_pma_setup_forced(phydev); ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) ++ phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, ++ MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl); ++ if (ret < 0) ++ return ret; ++ ++ return __genphy_config_aneg(phydev, ret); ++} ++ + static void qca808x_link_change_notify(struct phy_device *phydev) + { + /* Assert interface sgmii fifo on link down, deassert it on link up, +@@ -2295,7 +2309,7 @@ static struct phy_driver at803x_driver[] + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, + .get_features = qca808x_get_features, +- .config_aneg = at803x_config_aneg, ++ .config_aneg = qca808x_config_aneg, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_status = qca808x_read_status, diff --git a/target/linux/generic/backport-6.1/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch b/target/linux/generic/backport-6.1/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch new file mode 100644 index 0000000000..54ca3bdfc8 --- /dev/null +++ b/target/linux/generic/backport-6.1/708-v6.8-02-net-phy-at803x-make-read-specific-status-function-mo.patch @@ -0,0 +1,97 @@ +From 38eb804e8458ba181a03a0498ce4bf84eebd1931 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 14 Dec 2023 01:44:32 +0100 +Subject: [PATCH 2/2] net: phy: at803x: make read specific status function more + generic + +Rework read specific status function to be more generic. The function +apply different speed mask based on the PHY ID. Make it more generic by +adding an additional arg to pass the specific speed (ss) mask and use +the provided mask to parse the speed value. + +This is needed to permit an easier deatch of qca808x code from the +at803x driver. + +Signed-off-by: Christian Marangi +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -301,6 +301,11 @@ static struct at803x_hw_stat qca83xx_hw_ + { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD}, + }; + ++struct at803x_ss_mask { ++ u16 speed_mask; ++ u8 speed_shift; ++}; ++ + struct at803x_priv { + int flags; + u16 clk_25m_reg; +@@ -921,7 +926,8 @@ static void at803x_link_change_notify(st + } + } + +-static int at803x_read_specific_status(struct phy_device *phydev) ++static int at803x_read_specific_status(struct phy_device *phydev, ++ struct at803x_ss_mask ss_mask) + { + int ss; + +@@ -940,11 +946,8 @@ static int at803x_read_specific_status(s + if (sfc < 0) + return sfc; + +- /* qca8081 takes the different bits for speed value from at803x */ +- if (phydev->drv->phy_id == QCA8081_PHY_ID) +- speed = FIELD_GET(QCA808X_SS_SPEED_MASK, ss); +- else +- speed = FIELD_GET(AT803X_SS_SPEED_MASK, ss); ++ speed = ss & ss_mask.speed_mask; ++ speed >>= ss_mask.speed_shift; + + switch (speed) { + case AT803X_SS_SPEED_10: +@@ -989,6 +992,7 @@ static int at803x_read_specific_status(s + static int at803x_read_status(struct phy_device *phydev) + { + struct at803x_priv *priv = phydev->priv; ++ struct at803x_ss_mask ss_mask = { 0 }; + int err, old_link = phydev->link; + + if (priv->is_1000basex) +@@ -1012,7 +1016,9 @@ static int at803x_read_status(struct phy + if (err < 0) + return err; + +- err = at803x_read_specific_status(phydev); ++ ss_mask.speed_mask = AT803X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK); ++ err = at803x_read_specific_status(phydev, ss_mask); + if (err < 0) + return err; + +@@ -1869,6 +1875,7 @@ static int qca808x_config_init(struct ph + + static int qca808x_read_status(struct phy_device *phydev) + { ++ struct at803x_ss_mask ss_mask = { 0 }; + int ret; + + ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT); +@@ -1882,7 +1889,10 @@ static int qca808x_read_status(struct ph + if (ret) + return ret; + +- ret = at803x_read_specific_status(phydev); ++ /* qca8081 takes the different bits for speed value from at803x */ ++ ss_mask.speed_mask = QCA808X_SS_SPEED_MASK; ++ ss_mask.speed_shift = __bf_shf(QCA808X_SS_SPEED_MASK); ++ ret = at803x_read_specific_status(phydev, ss_mask); + if (ret < 0) + return ret; + diff --git a/target/linux/generic/backport-6.1/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch b/target/linux/generic/backport-6.1/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch new file mode 100644 index 0000000000..8097a33e49 --- /dev/null +++ b/target/linux/generic/backport-6.1/709-v6.8-01-net-phy-at803x-remove-extra-space-after-cast.patch @@ -0,0 +1,27 @@ +From fc9d7264ddc32eaa647d6bfcdc25cdf9f786fde0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 18 Dec 2023 00:27:39 +0100 +Subject: [PATCH 1/2] net: phy: at803x: remove extra space after cast + +Remove extra space after cast as reported by checkpatch to keep code +clean. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20231217232739.27065-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/at803x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -462,7 +462,7 @@ static int at803x_set_wol(struct phy_dev + if (!ndev) + return -ENODEV; + +- mac = (const u8 *) ndev->dev_addr; ++ mac = (const u8 *)ndev->dev_addr; + + if (!is_valid_ether_addr(mac)) + return -EINVAL; diff --git a/target/linux/generic/backport-6.1/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch b/target/linux/generic/backport-6.1/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch new file mode 100644 index 0000000000..b8d4591087 --- /dev/null +++ b/target/linux/generic/backport-6.1/709-v6.8-02-net-phy-at803x-replace-msleep-1-with-usleep_range.patch @@ -0,0 +1,38 @@ +From 3ab5720881a924fb6405d9e6a3b09f1026467c47 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 18 Dec 2023 00:25:08 +0100 +Subject: [PATCH 2/2] net: phy: at803x: replace msleep(1) with usleep_range + +Replace msleep(1) with usleep_range as suggested by timers-howto guide. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20231217232508.26470-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/at803x.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -916,9 +916,9 @@ static void at803x_link_change_notify(st + at803x_context_save(phydev, &context); + + phy_device_reset(phydev, 1); +- msleep(1); ++ usleep_range(1000, 2000); + phy_device_reset(phydev, 0); +- msleep(1); ++ usleep_range(1000, 2000); + + at803x_context_restore(phydev, &context); + +@@ -1733,7 +1733,7 @@ static int qca83xx_resume(struct phy_dev + if (ret) + return ret; + +- msleep(1); ++ usleep_range(1000, 2000); + + return 0; + } diff --git a/target/linux/generic/backport-6.1/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch b/target/linux/generic/backport-6.1/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch new file mode 100644 index 0000000000..776b7bb43f --- /dev/null +++ b/target/linux/generic/backport-6.1/710-v6.8-net-phy-at803x-better-align-function-varibles-to-ope.patch @@ -0,0 +1,152 @@ +From 7961ef1fa10ec35ad6923fb5751877116e4b035b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 19 Dec 2023 21:21:24 +0100 +Subject: [PATCH] net: phy: at803x: better align function varibles to open + parenthesis + +Better align function variables to open parenthesis as suggested by +checkpatch script for qca808x function to make code cleaner. + +For cable_test_get_status function some additional rework was needed to +handle too long functions. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 67 ++++++++++++++++++++++------------------ + 1 file changed, 37 insertions(+), 30 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1781,27 +1781,27 @@ static int qca808x_phy_fast_retrain_conf + return ret; + + phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1, +- QCA808X_TOP_OPTION1_DATA); ++ QCA808X_TOP_OPTION1_DATA); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB, +- QCA808X_MSE_THRESHOLD_20DB_VALUE); ++ QCA808X_MSE_THRESHOLD_20DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB, +- QCA808X_MSE_THRESHOLD_17DB_VALUE); ++ QCA808X_MSE_THRESHOLD_17DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB, +- QCA808X_MSE_THRESHOLD_27DB_VALUE); ++ QCA808X_MSE_THRESHOLD_27DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB, +- QCA808X_MSE_THRESHOLD_28DB_VALUE); ++ QCA808X_MSE_THRESHOLD_28DB_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1, +- QCA808X_MMD3_DEBUG_1_VALUE); ++ QCA808X_MMD3_DEBUG_1_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4, +- QCA808X_MMD3_DEBUG_4_VALUE); ++ QCA808X_MMD3_DEBUG_4_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5, +- QCA808X_MMD3_DEBUG_5_VALUE); ++ QCA808X_MMD3_DEBUG_5_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3, +- QCA808X_MMD3_DEBUG_3_VALUE); ++ QCA808X_MMD3_DEBUG_3_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6, +- QCA808X_MMD3_DEBUG_6_VALUE); ++ QCA808X_MMD3_DEBUG_6_VALUE); + phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2, +- QCA808X_MMD3_DEBUG_2_VALUE); ++ QCA808X_MMD3_DEBUG_2_VALUE); + + return 0; + } +@@ -1838,13 +1838,14 @@ static int qca808x_config_init(struct ph + + /* Active adc&vga on 802.3az for the link 1000M and 100M */ + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7, +- QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); ++ QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN); + if (ret) + return ret; + + /* Adjust the threshold on 802.3az for the link 1000M */ + ret = phy_write_mmd(phydev, MDIO_MMD_PCS, +- QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, QCA808X_MMD3_AZ_TRAINING_VAL); ++ QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, ++ QCA808X_MMD3_AZ_TRAINING_VAL); + if (ret) + return ret; + +@@ -1870,7 +1871,8 @@ static int qca808x_config_init(struct ph + + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, +- QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV); ++ QCA808X_ADC_THRESHOLD_MASK, ++ QCA808X_ADC_THRESHOLD_100MV); + } + + static int qca808x_read_status(struct phy_device *phydev) +@@ -1883,7 +1885,7 @@ static int qca808x_read_status(struct ph + return ret; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, +- ret & MDIO_AN_10GBT_STAT_LP2_5G); ++ ret & MDIO_AN_10GBT_STAT_LP2_5G); + + ret = genphy_read_status(phydev); + if (ret) +@@ -1913,7 +1915,7 @@ static int qca808x_read_status(struct ph + */ + if (qca808x_has_fast_retrain_or_slave_seed(phydev)) { + if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR || +- qca808x_is_prefer_master(phydev)) { ++ qca808x_is_prefer_master(phydev)) { + qca808x_phy_ms_seed_enable(phydev, false); + } else { + qca808x_phy_ms_seed_enable(phydev, true); +@@ -2070,18 +2072,22 @@ static int qca808x_cable_test_get_status + ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, + qca808x_cable_test_result_trans(pair_d)); + +- if (qca808x_cdt_fault_length_valid(pair_a)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A)); +- if (qca808x_cdt_fault_length_valid(pair_b)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B)); +- if (qca808x_cdt_fault_length_valid(pair_c)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C)); +- if (qca808x_cdt_fault_length_valid(pair_d)) +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, +- qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D)); ++ if (qca808x_cdt_fault_length_valid(pair_a)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_b)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_c)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ } ++ if (qca808x_cdt_fault_length_valid(pair_d)) { ++ val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D); ++ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ } + + *finished = true; + +@@ -2148,8 +2154,9 @@ static void qca808x_link_change_notify(s + * the interface device address is always phy address added by 1. + */ + mdiobus_c45_modify_changed(phydev->mdio.bus, phydev->mdio.addr + 1, +- MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, +- QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); ++ MDIO_MMD_PMAPMD, QCA8081_PHY_SERDES_MMD1_FIFO_CTRL, ++ QCA8081_PHY_FIFO_RSTN, ++ phydev->link ? QCA8081_PHY_FIFO_RSTN : 0); + } + + static struct phy_driver at803x_driver[] = { diff --git a/target/linux/generic/backport-6.1/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch b/target/linux/generic/backport-6.1/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch new file mode 100644 index 0000000000..d7196da46e --- /dev/null +++ b/target/linux/generic/backport-6.1/711-v6.8-01-net-phy-at803x-generalize-cdt-fault-length-function.patch @@ -0,0 +1,62 @@ +From 22eb276098da820d9440fad22901f9b74ed4d659 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:38 +0100 +Subject: [PATCH 1/4] net: phy: at803x: generalize cdt fault length function + +Generalize cable test fault length function since they all base on the +same magic values (already reverse engineered to understand the meaning +of it) to have consistenct values on every PHY. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1192,10 +1192,8 @@ static bool at803x_cdt_fault_length_vali + return false; + } + +-static int at803x_cdt_fault_length(u16 status) ++static int at803x_cdt_fault_length(int dt) + { +- int dt; +- + /* According to the datasheet the distance to the fault is + * DELTA_TIME * 0.824 meters. + * +@@ -1211,8 +1209,6 @@ static int at803x_cdt_fault_length(u16 s + * With a VF of 0.69 we get the factor 0.824 mentioned in the + * datasheet. + */ +- dt = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, status); +- + return (dt * 824) / 10; + } + +@@ -1265,9 +1261,11 @@ static int at803x_cable_test_one_pair(st + ethnl_cable_test_result(phydev, ethtool_pair[pair], + at803x_cable_test_result_trans(val)); + +- if (at803x_cdt_fault_length_valid(val)) ++ if (at803x_cdt_fault_length_valid(val)) { ++ val = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, val); + ethnl_cable_test_fault_length(phydev, ethtool_pair[pair], + at803x_cdt_fault_length(val)); ++ } + + return 1; + } +@@ -1992,7 +1990,8 @@ static int qca808x_cdt_fault_length(stru + if (val < 0) + return val; + +- return (FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val) * 824) / 10; ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val); ++ return at803x_cdt_fault_length(val); + } + + static int qca808x_cable_test_start(struct phy_device *phydev) diff --git a/target/linux/generic/backport-6.1/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch b/target/linux/generic/backport-6.1/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch new file mode 100644 index 0000000000..5d38fe7e91 --- /dev/null +++ b/target/linux/generic/backport-6.1/711-v6.8-02-net-phy-at803x-refactor-qca808x-cable-test-get-statu.patch @@ -0,0 +1,118 @@ +From e0e9ada1df6133513249861c1d91c1dbefd9383b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:39 +0100 +Subject: [PATCH 2/4] net: phy: at803x: refactor qca808x cable test get status + function + +Refactor qca808x cable test get status function to remove code +duplication and clean things up. + +The same logic is applied to each pair hence it can be generalized and +moved to a common function. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 80 ++++++++++++++++++++++++---------------- + 1 file changed, 49 insertions(+), 31 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -2035,10 +2035,43 @@ static int qca808x_cable_test_start(stru + return 0; + } + ++static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, ++ u16 status) ++{ ++ u16 pair_code; ++ int length; ++ ++ switch (pair) { ++ case ETHTOOL_A_CABLE_PAIR_A: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_B: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_C: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status); ++ break; ++ case ETHTOOL_A_CABLE_PAIR_D: ++ pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ ethnl_cable_test_result(phydev, pair, ++ qca808x_cable_test_result_trans(pair_code)); ++ ++ if (qca808x_cdt_fault_length_valid(pair_code)) { ++ length = qca808x_cdt_fault_length(phydev, pair); ++ ethnl_cable_test_fault_length(phydev, pair, length); ++ } ++ ++ return 0; ++} ++ + static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished) + { + int ret, val; +- int pair_a, pair_b, pair_c, pair_d; + + *finished = false; + +@@ -2057,36 +2090,21 @@ static int qca808x_cable_test_get_status + if (val < 0) + return val; + +- pair_a = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, val); +- pair_b = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, val); +- pair_c = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, val); +- pair_d = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, val); +- +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, +- qca808x_cable_test_result_trans(pair_a)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B, +- qca808x_cable_test_result_trans(pair_b)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C, +- qca808x_cable_test_result_trans(pair_c)); +- ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, +- qca808x_cable_test_result_trans(pair_d)); +- +- if (qca808x_cdt_fault_length_valid(pair_a)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_b)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_c)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C, val); +- } +- if (qca808x_cdt_fault_length_valid(pair_d)) { +- val = qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D); +- ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D, val); +- } ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val); ++ if (ret) ++ return ret; ++ ++ ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val); ++ if (ret) ++ return ret; + + *finished = true; + diff --git a/target/linux/generic/backport-6.1/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch b/target/linux/generic/backport-6.1/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch new file mode 100644 index 0000000000..d5793860a9 --- /dev/null +++ b/target/linux/generic/backport-6.1/711-v6.8-03-net-phy-at803x-add-support-for-cdt-cross-short-test-.patch @@ -0,0 +1,182 @@ +From ea73e5ea442ee2aade67b1fb1233ccb3cbea2ceb Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:40 +0100 +Subject: [PATCH 3/4] net: phy: at803x: add support for cdt cross short test + for qca808x + +QCA808x PHY Family supports Cable Diagnostic Test also for Cross Pair +Short. + +Add all the define to make enable and support these additional tests. + +Cross Short test was previously disabled by default, this is now changed +and enabled by default. In this mode, the mask changed a bit and length +is shifted based on the fault condition. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 86 ++++++++++++++++++++++++++++++++-------- + 1 file changed, 69 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -254,6 +254,7 @@ + + #define QCA808X_CDT_ENABLE_TEST BIT(15) + #define QCA808X_CDT_INTER_CHECK_DIS BIT(13) ++#define QCA808X_CDT_STATUS BIT(11) + #define QCA808X_CDT_LENGTH_UNIT BIT(10) + + #define QCA808X_MMD3_CDT_STATUS 0x8064 +@@ -261,16 +262,44 @@ + #define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066 + #define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067 + #define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068 +-#define QCA808X_CDT_DIAG_LENGTH GENMASK(7, 0) ++#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8) ++#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0) + + #define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12) + #define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8) + #define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4) + #define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0) +-#define QCA808X_CDT_STATUS_STAT_FAIL 0 +-#define QCA808X_CDT_STATUS_STAT_NORMAL 1 +-#define QCA808X_CDT_STATUS_STAT_OPEN 2 +-#define QCA808X_CDT_STATUS_STAT_SHORT 3 ++ ++#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0) ++#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0) ++#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1) ++#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2) ++#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3) ++ ++#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1) ++#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2) ++#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3) ++ ++/* NORMAL are MDI with type set to 0 */ ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI1) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI2) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3 ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\ ++ QCA808X_CDT_STATUS_STAT_MDI3) ++ ++/* Added for reference of existence but should be handled by wait_for_completion already */ ++#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3)) + + /* QCA808X 1G chip type */ + #define QCA808X_PHY_MMD7_CHIP_TYPE 0x901d +@@ -1941,8 +1970,17 @@ static int qca808x_soft_reset(struct phy + static bool qca808x_cdt_fault_length_valid(int cdt_code) + { + switch (cdt_code) { +- case QCA808X_CDT_STATUS_STAT_SHORT: +- case QCA808X_CDT_STATUS_STAT_OPEN: ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: + return true; + default: + return false; +@@ -1954,17 +1992,28 @@ static int qca808x_cable_test_result_tra + switch (cdt_code) { + case QCA808X_CDT_STATUS_STAT_NORMAL: + return ETHTOOL_A_CABLE_RESULT_CODE_OK; +- case QCA808X_CDT_STATUS_STAT_SHORT: ++ case QCA808X_CDT_STATUS_STAT_SAME_SHORT: + return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; +- case QCA808X_CDT_STATUS_STAT_OPEN: ++ case QCA808X_CDT_STATUS_STAT_SAME_OPEN: + return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN: ++ case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT: ++ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; + case QCA808X_CDT_STATUS_STAT_FAIL: + default: + return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; + } + } + +-static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair) ++static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair, ++ int result) + { + int val; + u32 cdt_length_reg = 0; +@@ -1990,7 +2039,11 @@ static int qca808x_cdt_fault_length(stru + if (val < 0) + return val; + +- val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val); ++ if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT) ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val); ++ else ++ val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val); ++ + return at803x_cdt_fault_length(val); + } + +@@ -2038,8 +2091,8 @@ static int qca808x_cable_test_start(stru + static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair, + u16 status) + { ++ int length, result; + u16 pair_code; +- int length; + + switch (pair) { + case ETHTOOL_A_CABLE_PAIR_A: +@@ -2058,11 +2111,11 @@ static int qca808x_cable_test_get_pair_s + return -EINVAL; + } + +- ethnl_cable_test_result(phydev, pair, +- qca808x_cable_test_result_trans(pair_code)); ++ result = qca808x_cable_test_result_trans(pair_code); ++ ethnl_cable_test_result(phydev, pair, result); + + if (qca808x_cdt_fault_length_valid(pair_code)) { +- length = qca808x_cdt_fault_length(phydev, pair); ++ length = qca808x_cdt_fault_length(phydev, pair, result); + ethnl_cable_test_fault_length(phydev, pair, length); + } + +@@ -2076,8 +2129,7 @@ static int qca808x_cable_test_get_status + *finished = false; + + val = QCA808X_CDT_ENABLE_TEST | +- QCA808X_CDT_LENGTH_UNIT | +- QCA808X_CDT_INTER_CHECK_DIS; ++ QCA808X_CDT_LENGTH_UNIT; + ret = at803x_cdt_start(phydev, val); + if (ret) + return ret; diff --git a/target/linux/generic/backport-6.1/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch b/target/linux/generic/backport-6.1/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch new file mode 100644 index 0000000000..c146e502fe --- /dev/null +++ b/target/linux/generic/backport-6.1/711-v6.8-04-net-phy-at803x-make-read_status-more-generic.patch @@ -0,0 +1,62 @@ +From c34d9452d4e5d98a655d7b625e85466320885416 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 4 Jan 2024 22:30:41 +0100 +Subject: [PATCH 4/4] net: phy: at803x: make read_status more generic + +Make read_status more generic in preparation on moving it to shared +library as other PHY Family Driver will have the exact same +implementation. + +The only specific part was a check for AR8031/33 if 1000basex was used. +The check is moved to a dedicated function specific for those PHYs. + +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +--- + drivers/net/phy/at803x.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/at803x.c ++++ b/drivers/net/phy/at803x.c +@@ -1020,13 +1020,9 @@ static int at803x_read_specific_status(s + + static int at803x_read_status(struct phy_device *phydev) + { +- struct at803x_priv *priv = phydev->priv; + struct at803x_ss_mask ss_mask = { 0 }; + int err, old_link = phydev->link; + +- if (priv->is_1000basex) +- return genphy_c37_read_status(phydev); +- + /* Update the link, but return if there was an error */ + err = genphy_update_link(phydev); + if (err) +@@ -1618,6 +1614,17 @@ static int at8031_config_intr(struct phy + return at803x_config_intr(phydev); + } + ++/* AR8031 and AR8033 share the same read status logic */ ++static int at8031_read_status(struct phy_device *phydev) ++{ ++ struct at803x_priv *priv = phydev->priv; ++ ++ if (priv->is_1000basex) ++ return genphy_c37_read_status(phydev); ++ ++ return at803x_read_status(phydev); ++} ++ + /* AR8031 and AR8035 share the same cable test get status reg */ + static int at8031_cable_test_get_status(struct phy_device *phydev, + bool *finished) +@@ -2281,7 +2288,7 @@ static struct phy_driver at803x_driver[] + .read_page = at803x_read_page, + .write_page = at803x_write_page, + .get_features = at803x_get_features, +- .read_status = at803x_read_status, ++ .read_status = at8031_read_status, + .config_intr = at8031_config_intr, + .handle_interrupt = at803x_handle_interrupt, + .get_tunable = at803x_get_tunable, diff --git a/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch b/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch index eac8966a48..893a81246d 100644 --- a/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch +++ b/target/linux/generic/backport-6.1/792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch @@ -35,7 +35,7 @@ Signed-off-by: David S. Miller bool mac_link_dropped; bool using_mac_select_pcs; -@@ -987,6 +992,22 @@ static void phylink_mac_pcs_an_restart(s +@@ -990,6 +995,22 @@ static void phylink_mac_pcs_an_restart(s } } @@ -58,7 +58,7 @@ Signed-off-by: David S. Miller static void phylink_major_config(struct phylink *pl, bool restart, const struct phylink_link_state *state) { -@@ -1023,11 +1044,16 @@ static void phylink_major_config(struct +@@ -1026,11 +1047,16 @@ static void phylink_major_config(struct /* If we have a new PCS, switch to the new PCS after preparing the MAC * for the change. */ @@ -76,7 +76,7 @@ Signed-off-by: David S. Miller if (pl->pcs) { err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, state->interface, -@@ -1499,6 +1525,7 @@ struct phylink *phylink_create(struct ph +@@ -1502,6 +1528,7 @@ struct phylink *phylink_create(struct ph pl->link_config.speed = SPEED_UNKNOWN; pl->link_config.duplex = DUPLEX_UNKNOWN; pl->link_config.an_enabled = true; @@ -84,7 +84,7 @@ Signed-off-by: David S. Miller pl->mac_ops = mac_ops; __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); timer_setup(&pl->link_poll, phylink_fixed_poll, 0); -@@ -1900,6 +1927,8 @@ void phylink_start(struct phylink *pl) +@@ -1903,6 +1930,8 @@ void phylink_start(struct phylink *pl) if (pl->netdev) netif_carrier_off(pl->netdev); @@ -93,7 +93,7 @@ Signed-off-by: David S. Miller /* Apply the link configuration to the MAC when starting. This allows * a fixed-link to start with the correct parameters, and also * ensures that we set the appropriate advertisement for Serdes links. -@@ -1910,6 +1939,8 @@ void phylink_start(struct phylink *pl) +@@ -1913,6 +1942,8 @@ void phylink_start(struct phylink *pl) */ phylink_mac_initial_config(pl, true); @@ -102,7 +102,7 @@ Signed-off-by: David S. Miller phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED); if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) { -@@ -1928,15 +1959,9 @@ void phylink_start(struct phylink *pl) +@@ -1931,15 +1962,9 @@ void phylink_start(struct phylink *pl) poll = true; } @@ -120,7 +120,7 @@ Signed-off-by: David S. Miller if (poll) mod_timer(&pl->link_poll, jiffies + HZ); if (pl->phydev) -@@ -1973,6 +1998,10 @@ void phylink_stop(struct phylink *pl) +@@ -1976,6 +2001,10 @@ void phylink_stop(struct phylink *pl) } phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); diff --git a/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch b/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch index a3184513ee..d33fc72dd1 100644 --- a/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch +++ b/target/linux/generic/backport-6.1/801-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch @@ -153,7 +153,7 @@ Signed-off-by: David S. Miller #include #include #include -@@ -593,6 +594,7 @@ struct macsec_ops; +@@ -602,6 +603,7 @@ struct macsec_ops; * @phy_num_led_triggers: Number of triggers in @phy_led_triggers * @led_link_trigger: LED trigger for link up/down * @last_triggered: last LED trigger for link speed @@ -161,7 +161,7 @@ Signed-off-by: David S. Miller * @master_slave_set: User requested master/slave configuration * @master_slave_get: Current master/slave advertisement * @master_slave_state: Current master/slave configuration -@@ -685,6 +687,7 @@ struct phy_device { +@@ -694,6 +696,7 @@ struct phy_device { struct phy_led_trigger *led_link_trigger; #endif @@ -169,7 +169,7 @@ Signed-off-by: David S. Miller /* * Interrupt number for this PHY -@@ -759,6 +762,19 @@ struct phy_tdr_config { +@@ -768,6 +771,19 @@ struct phy_tdr_config { #define PHY_PAIR_ALL -1 /** diff --git a/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index 57db12ed4a..c1678ce2ea 100644 --- a/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/target/linux/generic/backport-6.1/801-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -59,7 +59,7 @@ Signed-off-by: David S. Miller init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -765,15 +765,19 @@ struct phy_tdr_config { +@@ -774,15 +774,19 @@ struct phy_tdr_config { * struct phy_led: An LED driven by the PHY * * @list: List of LEDs @@ -79,7 +79,7 @@ Signed-off-by: David S. Miller /** * struct phy_driver - Driver structure for a particular PHY type * -@@ -988,6 +992,15 @@ struct phy_driver { +@@ -997,6 +1001,15 @@ struct phy_driver { int (*get_sqi)(struct phy_device *dev); /** @get_sqi_max: Get the maximum signal quality indication */ int (*get_sqi_max)(struct phy_device *dev); diff --git a/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index e868722afa..f234b2bff1 100644 --- a/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/target/linux/generic/backport-6.1/801-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -52,7 +52,7 @@ Signed-off-by: David S. Miller init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -1001,6 +1001,18 @@ struct phy_driver { +@@ -1010,6 +1010,18 @@ struct phy_driver { */ int (*led_brightness_set)(struct phy_device *dev, u8 index, enum led_brightness value); diff --git a/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index 6cd798fc5d..daa970884e 100644 --- a/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/target/linux/generic/backport-6.1/826-v6.6-02-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -107,7 +107,7 @@ Signed-off-by: Jakub Kicinski init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -1013,6 +1013,39 @@ struct phy_driver { +@@ -1022,6 +1022,39 @@ struct phy_driver { int (*led_blink_set)(struct phy_device *dev, u8 index, unsigned long *delay_on, unsigned long *delay_off); diff --git a/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch index 8d2803158e..425f82376b 100644 --- a/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos sysfs_remove_link(&dev->dev.kobj, "phydev"); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -878,6 +878,12 @@ struct phy_driver { +@@ -887,6 +887,12 @@ struct phy_driver { /** @handle_interrupt: Override default interrupt handling */ irqreturn_t (*handle_interrupt)(struct phy_device *phydev); From 84a489b7cfc4c98b8747c9965826b2588eb3a57d Mon Sep 17 00:00:00 2001 From: Bryan Berg Date: Sun, 26 Nov 2023 13:34:01 -0800 Subject: [PATCH 124/222] ipq806x: Stabilize LAN 2 MAC address, interface ordering Part 1 of #13629 split. * Sets the LAN 2 MAC address in the DTS by deriving it from LAN 1's address. The factory OS derives this from the `eth1addr` u-boot env variable, but the nvmem_u-boot-env driver doesn't support parsing MAC addresses from fields other than `ethaddr`. But for all of the device samples I've checked (~10) it derives the correct MAC. * Updates 02_network to ensure that interfaces are assigned to roles correctly and consistently. Signed-off-by: Bryan Berg --- target/linux/ipq806x/base-files/etc/board.d/02_network | 4 ++-- .../ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ap3935.dts | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network index 8f24566b62..a408fc14ac 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -46,8 +46,7 @@ ipq806x_setup_interfaces() ucidef_set_network_device_conduit "lan1" "eth1" ucidef_set_network_device_conduit "wan" "eth0" ;; - edgecore,ecw5410 |\ - extreme,ap3935) + edgecore,ecw5410) ucidef_set_interfaces_lan_wan "eth1" "eth0" ;; qcom,ipq8064-ap161) @@ -63,6 +62,7 @@ ipq806x_setup_interfaces() meraki,mr42) ucidef_set_interface_lan "eth0" ;; + extreme,ap3935 |\ meraki,mr52) ucidef_set_interfaces_lan_wan "eth0" "eth1" ;; diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ap3935.dts b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ap3935.dts index bf65630f18..6d473d43ab 100644 --- a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ap3935.dts +++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ap3935.dts @@ -195,6 +195,7 @@ reg = <0x2a0000 0x0010000>; ethaddr: ethaddr { + #nvmem-cell-cells = <1>; }; }; @@ -327,7 +328,7 @@ phy-mode = "rgmii"; phy-handle = <&phy1>; - nvmem-cells = <ðaddr>; + nvmem-cells = <ðaddr 0>; nvmem-cell-names = "mac-address"; fixed-link { @@ -344,6 +345,9 @@ phy-mode = "sgmii"; phy-handle = <&phy2>; + + nvmem-cells = <ðaddr 1>; + nvmem-cell-names = "mac-address"; }; &adm_dma { From ef94541c07b13d2c07bc92df8a52e2eeccd9b488 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Mon, 15 Jan 2024 22:47:20 +0100 Subject: [PATCH 125/222] generic: 6.1: backport FIELD_PREP_CONST patch Backport FIELD_PREP_CONST patch needed for at803x backport patches to correctly compile and work. This MACRO is needed to treat values derived from FIELD_PREP usage as const to be used by switch case or other needed usage. Signed-off-by: Christian Marangi --- ...0-v6.3-bitfield-add-FIELD_PREP_CONST.patch | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 target/linux/generic/backport-6.1/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch diff --git a/target/linux/generic/backport-6.1/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch b/target/linux/generic/backport-6.1/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch new file mode 100644 index 0000000000..2e6d881fe9 --- /dev/null +++ b/target/linux/generic/backport-6.1/200-v6.3-bitfield-add-FIELD_PREP_CONST.patch @@ -0,0 +1,58 @@ +From e2192de59e457aef8d1f055a452131f0b3e5d097 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 18 Jan 2023 14:26:53 +0100 +Subject: [PATCH] bitfield: add FIELD_PREP_CONST() + +Neither FIELD_PREP() nor *_encode_bits() can be used +in constant contexts (such as initializers), but we +don't want to define shift constants for all masks +just for use in initializers, and having checks that +the values fit is also useful. + +Therefore, add FIELD_PREP_CONST() which is a smaller +version of FIELD_PREP() that can only take constant +arguments and has less friendly (but not less strict) +error checks, and expands to a constant value. + +Signed-off-by: Johannes Berg +Link: https://lore.kernel.org/r/20230118142652.53f20593504b.Iaeea0aee77a6493d70e573b4aa55c91c00e01e4b@changeid +Signed-off-by: Johannes Berg +--- + include/linux/bitfield.h | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +--- a/include/linux/bitfield.h ++++ b/include/linux/bitfield.h +@@ -115,6 +115,32 @@ + ((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask); \ + }) + ++#define __BF_CHECK_POW2(n) BUILD_BUG_ON_ZERO(((n) & ((n) - 1)) != 0) ++ ++/** ++ * FIELD_PREP_CONST() - prepare a constant bitfield element ++ * @_mask: shifted mask defining the field's length and position ++ * @_val: value to put in the field ++ * ++ * FIELD_PREP_CONST() masks and shifts up the value. The result should ++ * be combined with other fields of the bitfield using logical OR. ++ * ++ * Unlike FIELD_PREP() this is a constant expression and can therefore ++ * be used in initializers. Error checking is less comfortable for this ++ * version, and non-constant masks cannot be used. ++ */ ++#define FIELD_PREP_CONST(_mask, _val) \ ++ ( \ ++ /* mask must be non-zero */ \ ++ BUILD_BUG_ON_ZERO((_mask) == 0) + \ ++ /* check if value fits */ \ ++ BUILD_BUG_ON_ZERO(~((_mask) >> __bf_shf(_mask)) & (_val)) + \ ++ /* check if mask is contiguous */ \ ++ __BF_CHECK_POW2((_mask) + (1ULL << __bf_shf(_mask))) + \ ++ /* and create the value */ \ ++ (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) \ ++ ) ++ + /** + * FIELD_GET() - extract a bitfield element + * @_mask: shifted mask defining the field's length and position From d6beb5657697a186e3e13134050c387ab48ddfbf Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Tue, 16 Jan 2024 01:00:31 +0100 Subject: [PATCH 126/222] ipq40xx: drop PSGMII PHY patch Drop PSGMII PHY patch as it has been moved to generic in preparation for the PHY driver to be also used for ipq807x SoC as the same PHY is also used there. Signed-off-by: Christian Marangi --- ...-Introduce-PSGMII-PHY-interface-mode.patch | 105 ------------------ 1 file changed, 105 deletions(-) delete mode 100644 target/linux/ipq40xx/patches-6.1/003-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch diff --git a/target/linux/ipq40xx/patches-6.1/003-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch b/target/linux/ipq40xx/patches-6.1/003-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch deleted file mode 100644 index a28394f629..0000000000 --- a/target/linux/ipq40xx/patches-6.1/003-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 9a0e95e34e9c0a713ddfd48c3a88a20d2bdfd514 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Fri, 11 Aug 2023 13:10:07 +0200 -Subject: [PATCH] net: phy: Introduce PSGMII PHY interface mode - -The PSGMII interface is similar to QSGMII. The main difference -is that the PSGMII interface combines five SGMII lines into a -single link while in QSGMII only four lines are combined. - -Similarly to the QSGMII, this interface mode might also needs -special handling within the MAC driver. - -It is commonly used by Qualcomm with their QCA807x PHY series and -modern WiSoC-s. - -Add definitions for the PHY layer to allow to express this type -of connection between the MAC and PHY. - -Signed-off-by: Gabor Juhos -Signed-off-by: Robert Marko -Signed-off-by: David S. Miller ---- - Documentation/networking/phy.rst | 4 ++++ - drivers/net/phy/phy-core.c | 2 ++ - drivers/net/phy/phylink.c | 3 +++ - include/linux/phy.h | 4 ++++ - 4 files changed, 13 insertions(+) - ---- a/Documentation/networking/phy.rst -+++ b/Documentation/networking/phy.rst -@@ -323,6 +323,10 @@ Some of the interface modes are describe - contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this - interface mode has different autonegotiation and only supports full duplex. - -+``PHY_INTERFACE_MODE_PSGMII`` -+ This is the Penta SGMII mode, it is similar to QSGMII but it combines 5 -+ SGMII lines into a single link compared to 4 on QSGMII. -+ - Pause frames / flow control - =========================== - ---- a/drivers/net/phy/phy-core.c -+++ b/drivers/net/phy/phy-core.c -@@ -140,6 +140,8 @@ int phy_interface_num_ports(phy_interfac - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - return 4; -+ case PHY_INTERFACE_MODE_PSGMII: -+ return 5; - case PHY_INTERFACE_MODE_MAX: - WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode"); - return 0; ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -192,6 +192,7 @@ static int phylink_interface_max_speed(p - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - case PHY_INTERFACE_MODE_SGMII: -@@ -453,6 +454,7 @@ unsigned long phylink_get_capabilities(p - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - case PHY_INTERFACE_MODE_SGMII: -@@ -819,6 +821,7 @@ static int phylink_parse_mode(struct phy - - switch (pl->link_config.interface) { - case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - case PHY_INTERFACE_MODE_RGMII: ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -104,6 +104,7 @@ extern const int phy_10gbit_features_arr - * @PHY_INTERFACE_MODE_XGMII: 10 gigabit media-independent interface - * @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface - * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax -+ * @PHY_INTERFACE_MODE_PSGMII: Penta SGMII - * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII - * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII - * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX -@@ -141,6 +142,7 @@ typedef enum { - PHY_INTERFACE_MODE_XGMII, - PHY_INTERFACE_MODE_XLGMII, - PHY_INTERFACE_MODE_MOCA, -+ PHY_INTERFACE_MODE_PSGMII, - PHY_INTERFACE_MODE_QSGMII, - PHY_INTERFACE_MODE_TRGMII, - PHY_INTERFACE_MODE_100BASEX, -@@ -248,6 +250,8 @@ static inline const char *phy_modes(phy_ - return "xlgmii"; - case PHY_INTERFACE_MODE_MOCA: - return "moca"; -+ case PHY_INTERFACE_MODE_PSGMII: -+ return "psgmii"; - case PHY_INTERFACE_MODE_QSGMII: - return "qsgmii"; - case PHY_INTERFACE_MODE_TRGMII: From cb7068d5c5588810ffa47880e622998d3be3b389 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 10 Jan 2024 22:10:28 +0100 Subject: [PATCH 127/222] bcm27xx: Remove unneeded kernel patch This problem was fixed upstream in a different way, see: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-6.1.y&id=f434703fb893ddffcdbc1eec7646ce321e1190a8 Remove this now obsolete patch. Signed-off-by: Hauke Mehrtens --- ...is7xx-Don-t-spin-if-no-data-received.patch | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0146-sc16is7xx-Don-t-spin-if-no-data-received.patch diff --git a/target/linux/bcm27xx/patches-6.1/950-0146-sc16is7xx-Don-t-spin-if-no-data-received.patch b/target/linux/bcm27xx/patches-6.1/950-0146-sc16is7xx-Don-t-spin-if-no-data-received.patch deleted file mode 100644 index 30fcdb5218..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0146-sc16is7xx-Don-t-spin-if-no-data-received.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 1f9195cda30b320038cf94b4d14f85e58dd69d6d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 6 Nov 2018 12:57:48 +0000 -Subject: [PATCH] sc16is7xx: Don't spin if no data received - -See: https://github.com/raspberrypi/linux/issues/2676 - -Signed-off-by: Phil Elwell ---- - drivers/tty/serial/sc16is7xx.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/tty/serial/sc16is7xx.c -+++ b/drivers/tty/serial/sc16is7xx.c -@@ -783,6 +783,8 @@ static bool sc16is7xx_port_irq(struct sc - - if (rxlen) - sc16is7xx_handle_rx(port, rxlen, iir); -+ else -+ return false; - break; - /* CTSRTS interrupt comes only when CTS goes inactive */ - case SC16IS7XX_IIR_CTSRTS_SRC: From d549809c05997116823c1a1486d79cb8bda689b9 Mon Sep 17 00:00:00 2001 From: Yangyu Chen Date: Tue, 19 Dec 2023 03:21:53 +0800 Subject: [PATCH 128/222] bcm27xx: 6.1: turn on cpu erratum for A72 and disable A53 The original configuration might be copied from bcm2710 which uses cortex A53 rather than A72 in BCM2711, without errata might be harmful to system stability and security. Signed-off-by: Yangyu Chen --- target/linux/bcm27xx/bcm2711/config-6.1 | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/target/linux/bcm27xx/bcm2711/config-6.1 b/target/linux/bcm27xx/bcm2711/config-6.1 index ff88926e3d..1912b653e5 100644 --- a/target/linux/bcm27xx/bcm2711/config-6.1 +++ b/target/linux/bcm27xx/bcm2711/config-6.1 @@ -24,14 +24,8 @@ CONFIG_ARM64=y CONFIG_ARM64_4K_PAGES=y CONFIG_ARM64_CNP=y CONFIG_ARM64_EPAN=y -CONFIG_ARM64_ERRATUM_819472=y -CONFIG_ARM64_ERRATUM_824069=y -CONFIG_ARM64_ERRATUM_826319=y -CONFIG_ARM64_ERRATUM_827319=y -CONFIG_ARM64_ERRATUM_832075=y -CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_ERRATUM_1319367=y CONFIG_ARM64_HW_AFDBM=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PAN=y CONFIG_ARM64_PA_BITS=48 From 6bc26c7d499ba5c261d4b158241d44ffe3c520d9 Mon Sep 17 00:00:00 2001 From: Sieng-Piaw Liew Date: Wed, 9 Aug 2023 13:13:57 +0800 Subject: [PATCH 129/222] bmips: bcm6328: add Innacomm W3400V6 Innacomm W3400V6 is an xDSL B/G wireless router based on Broadcom BCM6328 SoC. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SoC: Broadcom BCM6328 CPU: BMIPS4350 V8.0, 320 MHz, 1 core Flash: SPI-NOR 8MB, MX25L6406E RAM: 64 MB Ethernet: 4x 10/100 Mbps Switch: Integrated Wireless: 802.11b/g, BCM4312 LEDs/Buttons: 9x / 2x Flash instruction, web UI: 1. Set a static IP on your computer compatible with 192.168.1.1, i.e 192.168.1.100. 2. Connect the ethernet cable from your computer to the router. 3. Make sure the router is powered off. 4. Press the reset button, don't release it yet! 5. While pressing reset, power on the router. 6. Wait 10 seconds or more. Note: The power LED is red at first then turns to solid green when ready. 7. Release the reset button. 8. Browse to 192.168.1.1 9. Select .bin file. 10. Upgrade the image. 11. Wait for it to reboot. Signed-off-by: Sieng-Piaw Liew [Fix cfe nvmem-layout and pinctrl_leds indentation] Signed-off-by: Álvaro Fernández Rojas --- .../bcm6328/base-files/etc/board.d/02_network | 1 + .../bmips/dts/bcm6328-innacomm-w3400v6.dts | 200 ++++++++++++++++++ target/linux/bmips/image/bcm6328.mk | 12 ++ 3 files changed, 213 insertions(+) create mode 100644 target/linux/bmips/dts/bcm6328-innacomm-w3400v6.dts diff --git a/target/linux/bmips/bcm6328/base-files/etc/board.d/02_network b/target/linux/bmips/bcm6328/base-files/etc/board.d/02_network index 391e38c4dc..104f20ef0e 100644 --- a/target/linux/bmips/bcm6328/base-files/etc/board.d/02_network +++ b/target/linux/bmips/bcm6328/base-files/etc/board.d/02_network @@ -11,6 +11,7 @@ arcadyan,ar7516) ;; comtrend,ar-5381u |\ comtrend,ar-5387un |\ +innacomm,w3400v6 |\ nucom,r5010unv2) ucidef_set_bridge_device switch ucidef_set_interface_lan "lan1 lan2 lan3 lan4" diff --git a/target/linux/bmips/dts/bcm6328-innacomm-w3400v6.dts b/target/linux/bmips/dts/bcm6328-innacomm-w3400v6.dts new file mode 100644 index 0000000000..f2f70fcb17 --- /dev/null +++ b/target/linux/bmips/dts/bcm6328-innacomm-w3400v6.dts @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "bcm6328.dtsi" + +/ { + model = "Innacomm W3400V6"; + compatible = "innacomm,w3400v6", "brcm,bcm6328"; + + aliases { + led-boot = &led_power_green; + led-failsafe = &led_power_red; + led-running = &led_power_green; + led-upgrade = &led_power_green; + }; + + keys { + compatible = "gpio-keys-polled"; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&gpio 23 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + }; + + wps { + label = "wps"; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + }; + }; + + bcm4318-sprom { + compatible = "brcm,bcma-sprom"; + + pci-bus = <1>; + pci-dev = <0>; + + nvmem-cells = <&macaddr_cfe_6a0 1>; + nvmem-cell-names = "mac-address"; + + brcm,sprom = "brcm/bcm4318-sprom.bin"; + }; +}; + +ðernet { + status = "okay"; + + nvmem-cells = <&macaddr_cfe_6a0 0>; + nvmem-cell-names = "mac-address"; +}; + +&hsspi { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + spi-max-frequency = <16666667>; + spi-tx-bus-width = <2>; + spi-rx-bus-width = <2>; + reg = <0>; + + #address-cells = <1>; + #size-cells = <1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x000000 0x010000>; + label = "cfe"; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_cfe_6a0: macaddr@6a0 { + compatible = "mac-base"; + reg = <0x6a0 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@10000 { + compatible = "brcm,bcm963xx-imagetag"; + reg = <0x010000 0x7e0000>; + label = "firmware"; + }; + + partition@7f0000 { + reg = <0x7f0000 0x010000>; + label = "nvram"; + }; + }; + }; +}; + +&leds { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_leds>; + + led@1 { + reg = <1>; + active-low; + label = "green:internet"; + }; + + led@2 { + reg = <2>; + active-low; + label = "red:internet"; + }; + + led@3 { + reg = <3>; + active-low; + label = "green:dsl"; + }; + + led_power_green: led@4 { + reg = <4>; + active-low; + label = "green:power"; + default-state = "on"; + }; + + led_power_red: led@5 { + reg = <5>; + active-low; + label = "red:power"; + panic-indicator; + }; + + led@11 { + reg = <11>; + active-low; + label = "green:wps"; + }; +}; + +&pcie { + status = "okay"; +}; + +&pinctrl { + pinctrl_leds: leds { + function = "led"; + pins = "gpio1", "gpio2", "gpio3", + "gpio4", "gpio5", "gpio11"; + }; +}; + +&switch0 { + ports { + port@0 { + reg = <0>; + label = "lan4"; + + phy-handle = <&phy1>; + phy-mode = "mii"; + }; + + port@1 { + reg = <1>; + label = "lan3"; + + phy-handle = <&phy2>; + phy-mode = "mii"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + + phy-handle = <&phy3>; + phy-mode = "mii"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + + phy-handle = <&phy4>; + phy-mode = "mii"; + }; + }; +}; + +&uart0 { + status = "okay"; +}; diff --git a/target/linux/bmips/image/bcm6328.mk b/target/linux/bmips/image/bcm6328.mk index fd0cf16dbb..b28926b1e7 100644 --- a/target/linux/bmips/image/bcm6328.mk +++ b/target/linux/bmips/image/bcm6328.mk @@ -39,6 +39,18 @@ define Device/comtrend_ar-5387un endef TARGET_DEVICES += comtrend_ar-5387un +define Device/innacomm_w3400v6 + $(Device/bcm63xx-cfe) + DEVICE_VENDOR := Innacomm + DEVICE_MODEL := W3400V6 + CHIP_ID := 6328 + CFE_BOARD_ID := 96328ang + FLASH_MB := 8 + DEVICE_PACKAGES += $(B43_PACKAGES) \ + broadcom-4318-sprom kmod-leds-bcm6328 +endef +TARGET_DEVICES += innacomm_w3400v6 + define Device/nucom_r5010unv2 $(Device/bcm63xx-cfe) DEVICE_VENDOR := NuCom From 6f328dfe19a7873d1cef3f88595d02c35c7fa054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 16 Jan 2024 10:59:47 +0100 Subject: [PATCH 130/222] bmips: dts: remove unneeded cfe alias MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is no longer needed after nvmem-layout changes. Signed-off-by: Álvaro Fernández Rojas --- target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts | 2 +- target/linux/bmips/dts/bcm6328-arcadyan-ar7516.dts | 2 +- target/linux/bmips/dts/bcm6328-comtrend-ar-5381u.dts | 2 +- target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts | 2 +- target/linux/bmips/dts/bcm6328-nucom-r5010unv2.dts | 2 +- target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts | 2 +- target/linux/bmips/dts/bcm6368-actiontec-r1000h.dts | 2 +- target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts | 2 +- target/linux/bmips/dts/bcm6368-comtrend-vr-3025un.dts | 2 +- target/linux/bmips/dts/bcm6368-netgear-dgnd3700.dtsi | 2 +- target/linux/bmips/dts/bcm6368-observa-vh4032n.dts | 2 +- target/linux/bmips/dts/bcm6369-comtrend-wap-5813n.dts | 2 +- target/linux/bmips/dts/bcm6369-netgear-evg2000.dts | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts b/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts index 3321bbd004..052f61002b 100644 --- a/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts +++ b/target/linux/bmips/dts/bcm6318-comtrend-ar-5315u.dts @@ -85,7 +85,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { reg = <0x000000 0x010000>; label = "cfe"; read-only; diff --git a/target/linux/bmips/dts/bcm6328-arcadyan-ar7516.dts b/target/linux/bmips/dts/bcm6328-arcadyan-ar7516.dts index 779f1da1b9..649c595848 100644 --- a/target/linux/bmips/dts/bcm6328-arcadyan-ar7516.dts +++ b/target/linux/bmips/dts/bcm6328-arcadyan-ar7516.dts @@ -69,7 +69,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "cfe"; reg = <0x000000 0x010000>; read-only; diff --git a/target/linux/bmips/dts/bcm6328-comtrend-ar-5381u.dts b/target/linux/bmips/dts/bcm6328-comtrend-ar-5381u.dts index fc7462810c..09e6f99389 100644 --- a/target/linux/bmips/dts/bcm6328-comtrend-ar-5381u.dts +++ b/target/linux/bmips/dts/bcm6328-comtrend-ar-5381u.dts @@ -73,7 +73,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { reg = <0x000000 0x010000>; label = "cfe"; read-only; diff --git a/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts b/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts index ba15a64265..7ee87c636e 100644 --- a/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts +++ b/target/linux/bmips/dts/bcm6328-comtrend-ar-5387un.dts @@ -91,7 +91,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { reg = <0x000000 0x010000>; label = "cfe"; read-only; diff --git a/target/linux/bmips/dts/bcm6328-nucom-r5010unv2.dts b/target/linux/bmips/dts/bcm6328-nucom-r5010unv2.dts index b9cbae7af8..d096a1a42c 100644 --- a/target/linux/bmips/dts/bcm6328-nucom-r5010unv2.dts +++ b/target/linux/bmips/dts/bcm6328-nucom-r5010unv2.dts @@ -71,7 +71,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "cfe"; reg = <0x000000 0x010000>; read-only; diff --git a/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts b/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts index c30612191e..c2693fa716 100644 --- a/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts +++ b/target/linux/bmips/dts/bcm6358-huawei-hg556a-b.dts @@ -178,7 +178,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "cfe"; reg = <0x000000 0x020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6368-actiontec-r1000h.dts b/target/linux/bmips/dts/bcm6368-actiontec-r1000h.dts index c5e2e7f67f..fec67d0db9 100644 --- a/target/linux/bmips/dts/bcm6368-actiontec-r1000h.dts +++ b/target/linux/bmips/dts/bcm6368-actiontec-r1000h.dts @@ -174,7 +174,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x000000 0x020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts index eecf3806f2..63a07fe70e 100644 --- a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts +++ b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025u.dts @@ -101,7 +101,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025un.dts b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025un.dts index fb86adb899..937fbdd1a1 100644 --- a/target/linux/bmips/dts/bcm6368-comtrend-vr-3025un.dts +++ b/target/linux/bmips/dts/bcm6368-comtrend-vr-3025un.dts @@ -101,7 +101,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x000000 0x010000>; read-only; diff --git a/target/linux/bmips/dts/bcm6368-netgear-dgnd3700.dtsi b/target/linux/bmips/dts/bcm6368-netgear-dgnd3700.dtsi index 97836e92e0..c647559d6c 100644 --- a/target/linux/bmips/dts/bcm6368-netgear-dgnd3700.dtsi +++ b/target/linux/bmips/dts/bcm6368-netgear-dgnd3700.dtsi @@ -203,7 +203,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6368-observa-vh4032n.dts b/target/linux/bmips/dts/bcm6368-observa-vh4032n.dts index 8d6135fbdd..0f74c4b902 100644 --- a/target/linux/bmips/dts/bcm6368-observa-vh4032n.dts +++ b/target/linux/bmips/dts/bcm6368-observa-vh4032n.dts @@ -152,7 +152,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6369-comtrend-wap-5813n.dts b/target/linux/bmips/dts/bcm6369-comtrend-wap-5813n.dts index 53d20ecba3..70572b49a9 100644 --- a/target/linux/bmips/dts/bcm6369-comtrend-wap-5813n.dts +++ b/target/linux/bmips/dts/bcm6369-comtrend-wap-5813n.dts @@ -165,7 +165,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x000000 0x010000>; read-only; diff --git a/target/linux/bmips/dts/bcm6369-netgear-evg2000.dts b/target/linux/bmips/dts/bcm6369-netgear-evg2000.dts index db7f9b0e5b..00017238c8 100644 --- a/target/linux/bmips/dts/bcm6369-netgear-evg2000.dts +++ b/target/linux/bmips/dts/bcm6369-netgear-evg2000.dts @@ -184,7 +184,7 @@ #address-cells = <1>; #size-cells = <1>; - cfe: partition@0 { + partition@0 { label = "CFE"; reg = <0x000000 0x020000>; read-only; From 5cfb416b85f82b0da2568bd921bac5a1456bdf48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 16 Jan 2024 11:02:01 +0100 Subject: [PATCH 131/222] bmips: move to kernel 6.1 by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move bmips to kernel 6.1 by default. Signed-off-by: Álvaro Fernández Rojas --- target/linux/bmips/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target/linux/bmips/Makefile b/target/linux/bmips/Makefile index f45a70c289..c391e4b785 100644 --- a/target/linux/bmips/Makefile +++ b/target/linux/bmips/Makefile @@ -9,8 +9,7 @@ BOARDNAME:=Broadcom BMIPS SUBTARGETS:=bcm6318 bcm6328 bcm6358 bcm6362 bcm6368 bcm63268 FEATURES:=gpio squashfs usb -KERNEL_PATCHVER:=5.15 -KERNEL_TESTING_PATCHVER:=6.1 +KERNEL_PATCHVER:=6.1 define Target/Description Build firmware images for BCM33xx cable modem chips, From 81b4160a6f9b87d454d2f6b57968ca3c4c354cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 16 Jan 2024 11:04:29 +0100 Subject: [PATCH 132/222] bmips: drop patches/config for kernel 5.15 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop patches/config for kernel 5.15 now that they are not used anymore. Signed-off-by: Álvaro Fernández Rojas --- target/linux/bmips/bcm6318/config-5.15 | 271 ------------- target/linux/bmips/bcm63268/config-5.15 | 285 ------------- target/linux/bmips/bcm6328/config-5.15 | 283 ------------- target/linux/bmips/bcm6358/config-5.15 | 265 ------------- target/linux/bmips/bcm6362/config-5.15 | 285 ------------- target/linux/bmips/bcm6368/config-5.15 | 281 ------------- ...ort-for-bcm6345-style-external-inter.patch | 373 ------------------ ...s-automatically-detect-CPU-frequency.patch | 239 ----------- ...-bmips-automatically-detect-RAM-size.patch | 196 --------- ...202-mips-bmips-tweak-Kconfig-options.patch | 42 -- .../203-mips-bmips-dma-fix-CBR-address.patch | 84 ---- ...4-mips-bmips-enable-RAC-on-BMIPS4350.patch | 42 -- ...cronix_nand_block_protection_support.patch | 114 ------ ...add-BCM6368-enetsw-controller-driver.patch | 44 --- ...m-add-BCM6348-enet-controller-driver.patch | 43 -- ...net-mdio-mux-bcm6368-allow-disabling.patch | 23 -- .../600-mips-bmips-add-pci-support.patch | 34 -- ...controllers-add-bcm6328-pcie-support.patch | 36 -- ...controllers-add-bcm6318-pcie-support.patch | 36 -- ...-controllers-add-bcm6348-pci-support.patch | 36 -- ...rt-for-Sercomm-MSP430-LED-controller.patch | 45 --- ...d-unaligned-accesses-failing-on-bcm6.patch | 26 -- 22 files changed, 3083 deletions(-) delete mode 100644 target/linux/bmips/bcm6318/config-5.15 delete mode 100644 target/linux/bmips/bcm63268/config-5.15 delete mode 100644 target/linux/bmips/bcm6328/config-5.15 delete mode 100644 target/linux/bmips/bcm6358/config-5.15 delete mode 100644 target/linux/bmips/bcm6362/config-5.15 delete mode 100644 target/linux/bmips/bcm6368/config-5.15 delete mode 100644 target/linux/bmips/patches-5.15/100-irqchip-add-support-for-bcm6345-style-external-inter.patch delete mode 100644 target/linux/bmips/patches-5.15/200-mips-bmips-automatically-detect-CPU-frequency.patch delete mode 100644 target/linux/bmips/patches-5.15/201-mips-bmips-automatically-detect-RAM-size.patch delete mode 100644 target/linux/bmips/patches-5.15/202-mips-bmips-tweak-Kconfig-options.patch delete mode 100644 target/linux/bmips/patches-5.15/203-mips-bmips-dma-fix-CBR-address.patch delete mode 100644 target/linux/bmips/patches-5.15/204-mips-bmips-enable-RAC-on-BMIPS4350.patch delete mode 100644 target/linux/bmips/patches-5.15/210-macronix_nand_block_protection_support.patch delete mode 100644 target/linux/bmips/patches-5.15/500-net-broadcom-add-BCM6368-enetsw-controller-driver.patch delete mode 100644 target/linux/bmips/patches-5.15/501-net-broadcom-add-BCM6348-enet-controller-driver.patch delete mode 100644 target/linux/bmips/patches-5.15/502-net-mdio-mux-bcm6368-allow-disabling.patch delete mode 100644 target/linux/bmips/patches-5.15/600-mips-bmips-add-pci-support.patch delete mode 100644 target/linux/bmips/patches-5.15/601-pci-controllers-add-bcm6328-pcie-support.patch delete mode 100644 target/linux/bmips/patches-5.15/602-pci-controllers-add-bcm6318-pcie-support.patch delete mode 100644 target/linux/bmips/patches-5.15/603-pci-controllers-add-bcm6348-pci-support.patch delete mode 100644 target/linux/bmips/patches-5.15/700-leds-add-support-for-Sercomm-MSP430-LED-controller.patch delete mode 100644 target/linux/bmips/patches-5.15/800-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch diff --git a/target/linux/bmips/bcm6318/config-5.15 b/target/linux/bmips/bcm6318/config-5.15 deleted file mode 100644 index 50401a58e8..0000000000 --- a/target/linux/bmips/bcm6318/config-5.15 +++ /dev/null @@ -1,271 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_MMAP_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -# CONFIG_BCM6348_ENET is not set -CONFIG_BCM6368_ENETSW=y -CONFIG_BCM63XX_POWER=y -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -# CONFIG_CLK_BCM63268_TIMER is not set -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_BUS_MUX=y -CONFIG_MDIO_BUS_MUX_BCM6368=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PADATA=y -CONFIG_PCI=y -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_BCM6318=y -# CONFIG_PCIE_BCM6328 is not set -CONFIG_PCIE_PME=y -# CONFIG_PCI_BCM6348 is not set -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -CONFIG_PINCTRL_BCM6318=y -# CONFIG_PINCTRL_BCM63268 is not set -# CONFIG_PINCTRL_BCM6328 is not set -# CONFIG_PINCTRL_BCM6358 is not set -# CONFIG_PINCTRL_BCM6362 is not set -# CONFIG_PINCTRL_BCM6368 is not set -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BCM63XX=y -CONFIG_SPI=y -# CONFIG_SPI_BCM63XX is not set -CONFIG_SPI_BCM63XX_HSSPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/bcm63268/config-5.15 b/target/linux/bmips/bcm63268/config-5.15 deleted file mode 100644 index 09754e9f8b..0000000000 --- a/target/linux/bmips/bcm63268/config-5.15 +++ /dev/null @@ -1,285 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_MMAP_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -# CONFIG_BCM6348_ENET is not set -CONFIG_BCM6368_ENETSW=y -CONFIG_BCM63XX_POWER=y -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -CONFIG_CLK_BCM63268_TIMER=y -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_BCM2835=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_BUS_MUX=y -CONFIG_MDIO_BUS_MUX_BCM6368=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_NAND_BRCMNAND=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_MTD_SPLIT_BCM_WFI_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PADATA=y -CONFIG_PCI=y -CONFIG_PCIEPORTBUS=y -# CONFIG_PCIE_BCM6318 is not set -CONFIG_PCIE_BCM6328=y -CONFIG_PCIE_PME=y -# CONFIG_PCI_BCM6348 is not set -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_BCM6318 is not set -CONFIG_PINCTRL_BCM63268=y -# CONFIG_PINCTRL_BCM6328 is not set -# CONFIG_PINCTRL_BCM6358 is not set -# CONFIG_PINCTRL_BCM6362 is not set -# CONFIG_PINCTRL_BCM6368 is not set -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BCM63XX=y -CONFIG_SPI=y -CONFIG_SPI_BCM63XX=y -CONFIG_SPI_BCM63XX_HSSPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/bcm6328/config-5.15 b/target/linux/bmips/bcm6328/config-5.15 deleted file mode 100644 index 1e7712ead6..0000000000 --- a/target/linux/bmips/bcm6328/config-5.15 +++ /dev/null @@ -1,283 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_MMAP_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -# CONFIG_BCM6348_ENET is not set -CONFIG_BCM6368_ENETSW=y -CONFIG_BCM63XX_POWER=y -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -# CONFIG_CLK_BCM63268_TIMER is not set -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_BUS_MUX=y -CONFIG_MDIO_BUS_MUX_BCM6368=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_NAND_BRCMNAND=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_MTD_SPLIT_BCM_WFI_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PADATA=y -CONFIG_PCI=y -CONFIG_PCIEPORTBUS=y -# CONFIG_PCIE_BCM6318 is not set -CONFIG_PCIE_BCM6328=y -CONFIG_PCIE_PME=y -CONFIG_PCI_BCM6348=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_BCM6318 is not set -# CONFIG_PINCTRL_BCM63268 is not set -CONFIG_PINCTRL_BCM6328=y -# CONFIG_PINCTRL_BCM6358 is not set -# CONFIG_PINCTRL_BCM6362 is not set -# CONFIG_PINCTRL_BCM6368 is not set -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BCM63XX=y -CONFIG_SPI=y -# CONFIG_SPI_BCM63XX is not set -CONFIG_SPI_BCM63XX_HSSPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/bcm6358/config-5.15 b/target/linux/bmips/bcm6358/config-5.15 deleted file mode 100644 index 5d7a299444..0000000000 --- a/target/linux/bmips/bcm6358/config-5.15 +++ /dev/null @@ -1,265 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -CONFIG_BCM6348_ENET=y -# CONFIG_BCM6368_ENETSW is not set -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -# CONFIG_CLK_BCM63268_TIMER is not set -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -# CONFIG_MDIO_BUS_MUX_BCM6368 is not set -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PADATA=y -CONFIG_PCI=y -# CONFIG_PCIE_BCM6318 is not set -# CONFIG_PCIE_BCM6328 is not set -CONFIG_PCI_BCM6348=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_BCM6318 is not set -# CONFIG_PINCTRL_BCM63268 is not set -# CONFIG_PINCTRL_BCM6328 is not set -CONFIG_PINCTRL_BCM6358=y -# CONFIG_PINCTRL_BCM6362 is not set -# CONFIG_PINCTRL_BCM6368 is not set -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -# CONFIG_SOC_BCM63XX is not set -CONFIG_SPI=y -CONFIG_SPI_BCM63XX=y -# CONFIG_SPI_BCM63XX_HSSPI is not set -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/bcm6362/config-5.15 b/target/linux/bmips/bcm6362/config-5.15 deleted file mode 100644 index 5f9b528d95..0000000000 --- a/target/linux/bmips/bcm6362/config-5.15 +++ /dev/null @@ -1,285 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_MMAP_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -# CONFIG_BCM6348_ENET is not set -CONFIG_BCM6368_ENETSW=y -CONFIG_BCM63XX_POWER=y -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -# CONFIG_CLK_BCM63268_TIMER is not set -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_BCM2835=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_BUS_MUX=y -CONFIG_MDIO_BUS_MUX_BCM6368=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_NAND_BRCMNAND=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_MTD_SPLIT_BCM_WFI_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PADATA=y -CONFIG_PCI=y -CONFIG_PCIEPORTBUS=y -# CONFIG_PCIE_BCM6318 is not set -CONFIG_PCIE_BCM6328=y -CONFIG_PCIE_PME=y -# CONFIG_PCI_BCM6348 is not set -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_BCM6318 is not set -# CONFIG_PINCTRL_BCM63268 is not set -# CONFIG_PINCTRL_BCM6328 is not set -# CONFIG_PINCTRL_BCM6358 is not set -CONFIG_PINCTRL_BCM6362=y -# CONFIG_PINCTRL_BCM6368 is not set -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_GENERIC_DOMAINS=y -CONFIG_PM_GENERIC_DOMAINS_OF=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BCM63XX=y -CONFIG_SPI=y -CONFIG_SPI_BCM63XX=y -CONFIG_SPI_BCM63XX_HSSPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/bcm6368/config-5.15 b/target/linux/bmips/bcm6368/config-5.15 deleted file mode 100644 index 910d36ce0b..0000000000 --- a/target/linux/bmips/bcm6368/config-5.15 +++ /dev/null @@ -1,281 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_B53=y -CONFIG_B53_MDIO_DRIVER=y -CONFIG_B53_MMAP_DRIVER=y -CONFIG_B53_SPI_DRIVER=y -CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L1_IRQ=y -# CONFIG_BCM6348_ENET is not set -CONFIG_BCM6368_ENETSW=y -CONFIG_BCM7038_WDT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BMIPS_GENERIC=y -CONFIG_CEVT_R4K=y -# CONFIG_CLK_BCM63268_TIMER is not set -CONFIG_CLK_BCM_63XX_GATE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_BMIPS=y -CONFIG_CPU_BMIPS32_3300=y -CONFIG_CPU_BMIPS4350=y -CONFIG_CPU_BMIPS4380=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_NO_EFFICIENT_FFS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_CPUFREQ=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CRASH_DUMP=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CSRC_R4K=y -CONFIG_DEBUG_INFO=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTC=y -# CONFIG_DT_BCM93384WVG is not set -# CONFIG_DT_BCM93384WVG_VIPER is not set -# CONFIG_DT_BCM96368MVWG is not set -# CONFIG_DT_BCM97125CBMB is not set -# CONFIG_DT_BCM97346DBSMB is not set -# CONFIG_DT_BCM97358SVMB is not set -# CONFIG_DT_BCM97360SVMB is not set -# CONFIG_DT_BCM97362SVMB is not set -# CONFIG_DT_BCM97420C is not set -# CONFIG_DT_BCM97425SVMB is not set -# CONFIG_DT_BCM97435SVMB is not set -# CONFIG_DT_BCM9EJTAGPRB is not set -# CONFIG_DT_COMTREND_VR3032U is not set -# CONFIG_DT_NETGEAR_CVG834G is not set -CONFIG_DT_NONE=y -# CONFIG_DT_SFR_NEUFBOX4_SERCOMM is not set -# CONFIG_DT_SFR_NEUFBOX6_SERCOMM is not set -CONFIG_FIXED_PHY=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GPIO_BRCMSTB is not set -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_REGMAP=y -CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_BCM2835=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_LEDS_SERCOMM_MSP430 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_BUS_MUX=y -CONFIG_MDIO_BUS_MUX_BCM6368=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CLOCK_VSYSCALL=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_EBPF_JIT=y -CONFIG_MIPS_EXTERNAL_TIMER=y -CONFIG_MIPS_L1_CACHE_SHIFT=6 -CONFIG_MIPS_L1_CACHE_SHIFT_4=y -CONFIG_MIPS_L1_CACHE_SHIFT_6=y -CONFIG_MIPS_LD_CAN_LINK_VDSO=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_O32_FP64_SUPPORT=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MTD_BCM63XX_PARTS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_GEOMETRY is not set -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_NAND_BRCMNAND=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -# CONFIG_MTD_PARSER_IMAGETAG is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPLIT_BCM63XX_FW=y -CONFIG_MTD_SPLIT_BCM_WFI_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_COMMON=y -CONFIG_NET_DSA_TAG_BRCM_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_SWITCHDEV=y -CONFIG_NO_EXCEPT_FILL=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PADATA=y -CONFIG_PCI=y -# CONFIG_PCIE_BCM6318 is not set -# CONFIG_PCIE_BCM6328 is not set -CONFIG_PCI_BCM6348=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLINK=y -CONFIG_PHYSICAL_START=0x80010000 -CONFIG_PHY_BCM63XX_USBH=y -# CONFIG_PHY_BRCM_SATA is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_BCM6318 is not set -# CONFIG_PINCTRL_BCM63268 is not set -# CONFIG_PINCTRL_BCM6328 is not set -# CONFIG_PINCTRL_BCM6358 is not set -# CONFIG_PINCTRL_BCM6362 is not set -CONFIG_PINCTRL_BCM6368=y -CONFIG_PINCTRL_BCM63XX=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_SUPPLY=y -CONFIG_PROC_VMCORE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RELAY=y -CONFIG_RESET_BCM6345=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_BCM63XX=y -CONFIG_SERIAL_BCM63XX_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -# CONFIG_SOC_BCM63XX is not set -CONFIG_SPI=y -CONFIG_SPI_BCM63XX=y -# CONFIG_SPI_BCM63XX_HSSPI is not set -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SWPHY=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_BMIPS=y -CONFIG_SYS_HAS_CPU_BMIPS32_3300=y -CONFIG_SYS_HAS_CPU_BMIPS4350=y -CONFIG_SYS_HAS_CPU_BMIPS4380=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_TARGET_ISA_REV=0 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_OF=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/bmips/patches-5.15/100-irqchip-add-support-for-bcm6345-style-external-inter.patch b/target/linux/bmips/patches-5.15/100-irqchip-add-support-for-bcm6345-style-external-inter.patch deleted file mode 100644 index 44cdb068f9..0000000000 --- a/target/linux/bmips/patches-5.15/100-irqchip-add-support-for-bcm6345-style-external-inter.patch +++ /dev/null @@ -1,373 +0,0 @@ -From cf908990d4a8ccdb73ee4484aa8cadad379ca314 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Sun, 30 Nov 2014 14:54:27 +0100 -Subject: [PATCH] irqchip: add support for bcm6345-style external interrupt - controller - -Signed-off-by: Jonas Gorski ---- - .../brcm,bcm6345-ext-intc.txt | 29 ++ - drivers/irqchip/Kconfig | 4 + - drivers/irqchip/Makefile | 1 + - drivers/irqchip/irq-bcm6345-ext.c | 280 ++++++++++++++++++ - include/linux/irqchip/irq-bcm6345-ext.h | 14 + - 5 files changed, 328 insertions(+) - create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt - create mode 100644 drivers/irqchip/irq-bcm6345-ext.c - create mode 100644 include/linux/irqchip/irq-bcm6345-ext.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt -@@ -0,0 +1,29 @@ -+Broadcom BCM6345-style external interrupt controller -+ -+Required properties: -+ -+- compatible: Should be "brcm,bcm6345-ext-intc" or "brcm,bcm6318-ext-intc". -+- reg: Specifies the base physical addresses and size of the registers. -+- interrupt-controller: identifies the node as an interrupt controller. -+- #interrupt-cells: Specifies the number of cells needed to encode an interrupt -+ source, Should be 2. -+- interrupt-parent: Specifies the phandle to the parent interrupt controller -+ this one is cascaded from. -+- interrupts: Specifies the interrupt line(s) in the interrupt-parent controller -+ node, valid values depend on the type of parent interrupt controller. -+ -+Optional properties: -+ -+- brcm,field-width: Size of each field (mask, clear, sense, ...) in bits in the -+ register. Defaults to 4. -+ -+Example: -+ -+ext_intc: interrupt-controller@10000018 { -+ compatible = "brcm,bcm6345-ext-intc"; -+ interrupt-parent = <&periph_intc>; -+ #interrupt-cells = <2>; -+ reg = <0x10000018 0x4>; -+ interrupt-controller; -+ interrupts = <24>, <25>, <26>, <27>; -+}; ---- a/drivers/irqchip/Kconfig -+++ b/drivers/irqchip/Kconfig -@@ -108,6 +108,10 @@ config I8259 - bool - select IRQ_DOMAIN - -+config BCM6345_EXT_IRQ -+ bool "BCM6345 External IRQ Controller" -+ select IRQ_DOMAIN -+ - config BCM6345_L1_IRQ - bool - select GENERIC_IRQ_CHIP ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -62,6 +62,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_BCM6345_EXT_IRQ) += irq-bcm6345-ext.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-bcm6345-ext.c -@@ -0,0 +1,280 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2014 Jonas Gorski -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAX_IRQS 4 -+ -+#define EXTIRQ_CFG_SENSE 0 -+#define EXTIRQ_CFG_STAT 1 -+#define EXTIRQ_CFG_CLEAR 2 -+#define EXTIRQ_CFG_MASK 3 -+#define EXTIRQ_CFG_BOTHEDGE 4 -+#define EXTIRQ_CFG_LEVELSENSE 5 -+ -+struct intc_data { -+ struct irq_chip chip; -+ struct irq_domain *domain; -+ raw_spinlock_t lock; -+ -+ int parent_irq[MAX_IRQS]; -+ void __iomem *reg; -+ int shift; -+ unsigned int toggle_clear_on_ack:1; -+}; -+ -+static void bcm6345_ext_intc_irq_handle(struct irq_desc *desc) -+{ -+ struct intc_data *data = irq_desc_get_handler_data(desc); -+ struct irq_chip *chip = irq_desc_get_chip(desc); -+ unsigned int irq = irq_desc_get_irq(desc); -+ unsigned int idx; -+ -+ chained_irq_enter(chip, desc); -+ -+ for (idx = 0; idx < MAX_IRQS; idx++) { -+ if (data->parent_irq[idx] != irq) -+ continue; -+ -+ generic_handle_irq(irq_find_mapping(data->domain, idx)); -+ } -+ -+ chained_irq_exit(chip, desc); -+} -+ -+static void bcm6345_ext_intc_irq_ack(struct irq_data *data) -+{ -+ struct intc_data *priv = data->domain->host_data; -+ irq_hw_number_t hwirq = irqd_to_hwirq(data); -+ u32 reg; -+ -+ raw_spin_lock(&priv->lock); -+ reg = __raw_readl(priv->reg); -+ __raw_writel(reg | (1 << (hwirq + EXTIRQ_CFG_CLEAR * priv->shift)), -+ priv->reg); -+ if (priv->toggle_clear_on_ack) -+ __raw_writel(reg, priv->reg); -+ raw_spin_unlock(&priv->lock); -+} -+ -+static void bcm6345_ext_intc_irq_mask(struct irq_data *data) -+{ -+ struct intc_data *priv = data->domain->host_data; -+ irq_hw_number_t hwirq = irqd_to_hwirq(data); -+ u32 reg; -+ -+ raw_spin_lock(&priv->lock); -+ reg = __raw_readl(priv->reg); -+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_MASK * priv->shift)); -+ __raw_writel(reg, priv->reg); -+ raw_spin_unlock(&priv->lock); -+} -+ -+static void bcm6345_ext_intc_irq_unmask(struct irq_data *data) -+{ -+ struct intc_data *priv = data->domain->host_data; -+ irq_hw_number_t hwirq = irqd_to_hwirq(data); -+ u32 reg; -+ -+ raw_spin_lock(&priv->lock); -+ reg = __raw_readl(priv->reg); -+ reg |= 1 << (hwirq + EXTIRQ_CFG_MASK * priv->shift); -+ __raw_writel(reg, priv->reg); -+ raw_spin_unlock(&priv->lock); -+} -+ -+static int bcm6345_ext_intc_set_type(struct irq_data *data, -+ unsigned int flow_type) -+{ -+ struct intc_data *priv = data->domain->host_data; -+ irq_hw_number_t hwirq = irqd_to_hwirq(data); -+ bool levelsense = 0, sense = 0, bothedge = 0; -+ u32 reg; -+ -+ flow_type &= IRQ_TYPE_SENSE_MASK; -+ -+ if (flow_type == IRQ_TYPE_NONE) -+ flow_type = IRQ_TYPE_LEVEL_LOW; -+ -+ switch (flow_type) { -+ case IRQ_TYPE_EDGE_BOTH: -+ bothedge = 1; -+ break; -+ -+ case IRQ_TYPE_EDGE_RISING: -+ sense = 1; -+ break; -+ -+ case IRQ_TYPE_EDGE_FALLING: -+ break; -+ -+ case IRQ_TYPE_LEVEL_HIGH: -+ levelsense = 1; -+ sense = 1; -+ break; -+ -+ case IRQ_TYPE_LEVEL_LOW: -+ levelsense = 1; -+ break; -+ -+ default: -+ pr_err("bogus flow type combination given!\n"); -+ return -EINVAL; -+ } -+ -+ raw_spin_lock(&priv->lock); -+ reg = __raw_readl(priv->reg); -+ -+ if (levelsense) -+ reg |= 1 << (hwirq + EXTIRQ_CFG_LEVELSENSE * priv->shift); -+ else -+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_LEVELSENSE * priv->shift)); -+ if (sense) -+ reg |= 1 << (hwirq + EXTIRQ_CFG_SENSE * priv->shift); -+ else -+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_SENSE * priv->shift)); -+ if (bothedge) -+ reg |= 1 << (hwirq + EXTIRQ_CFG_BOTHEDGE * priv->shift); -+ else -+ reg &= ~(1 << (hwirq + EXTIRQ_CFG_BOTHEDGE * priv->shift)); -+ -+ __raw_writel(reg, priv->reg); -+ raw_spin_unlock(&priv->lock); -+ -+ irqd_set_trigger_type(data, flow_type); -+ if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) -+ irq_set_handler_locked(data, handle_level_irq); -+ else -+ irq_set_handler_locked(data, handle_edge_irq); -+ -+ return 0; -+} -+ -+static int bcm6345_ext_intc_map(struct irq_domain *d, unsigned int irq, -+ irq_hw_number_t hw) -+{ -+ struct intc_data *priv = d->host_data; -+ -+ irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops bcm6345_ext_domain_ops = { -+ .xlate = irq_domain_xlate_twocell, -+ .map = bcm6345_ext_intc_map, -+}; -+ -+static int __init __bcm6345_ext_intc_init(struct device_node *node, -+ int num_irqs, int *irqs, -+ void __iomem *reg, int shift, -+ bool toggle_clear_on_ack) -+{ -+ struct intc_data *data; -+ unsigned int i; -+ -+ data = kzalloc(sizeof(*data), GFP_KERNEL); -+ if (!data) -+ return -ENOMEM; -+ -+ raw_spin_lock_init(&data->lock); -+ -+ for (i = 0; i < num_irqs; i++) { -+ data->parent_irq[i] = irqs[i]; -+ -+ irq_set_handler_data(irqs[i], data); -+ irq_set_chained_handler(irqs[i], bcm6345_ext_intc_irq_handle); -+ } -+ -+ data->reg = reg; -+ data->shift = shift; -+ data->toggle_clear_on_ack = toggle_clear_on_ack; -+ -+ data->chip.name = "bcm6345-ext-intc"; -+ data->chip.irq_ack = bcm6345_ext_intc_irq_ack; -+ data->chip.irq_mask = bcm6345_ext_intc_irq_mask; -+ data->chip.irq_unmask = bcm6345_ext_intc_irq_unmask; -+ data->chip.irq_set_type = bcm6345_ext_intc_set_type; -+ -+ data->domain = irq_domain_add_linear(node, num_irqs, -+ &bcm6345_ext_domain_ops, data); -+ if (!data->domain) { -+ kfree(data); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+void __init bcm6345_ext_intc_init(int num_irqs, int *irqs, void __iomem *reg, -+ int shift) -+{ -+ __bcm6345_ext_intc_init(NULL, num_irqs, irqs, reg, shift, false); -+} -+ -+#ifdef CONFIG_OF -+static int __init bcm6345_ext_intc_of_init(struct device_node *node, -+ struct device_node *parent) -+{ -+ int num_irqs, ret = -EINVAL; -+ unsigned i; -+ void __iomem *base; -+ int irqs[MAX_IRQS] = { 0 }; -+ u32 shift; -+ bool toggle_clear_on_ack = false; -+ -+ num_irqs = of_irq_count(node); -+ -+ if (!num_irqs || num_irqs > MAX_IRQS) -+ return -EINVAL; -+ -+ if (of_property_read_u32(node, "brcm,field-width", &shift)) -+ shift = 4; -+ -+ /* on BCM6318 setting CLEAR seems to continuously mask interrupts */ -+ if (of_device_is_compatible(node, "brcm,bcm6318-ext-intc")) -+ toggle_clear_on_ack = true; -+ -+ for (i = 0; i < num_irqs; i++) { -+ irqs[i] = irq_of_parse_and_map(node, i); -+ if (!irqs[i]) -+ return -ENOMEM; -+ } -+ -+ base = of_iomap(node, 0); -+ if (!base) -+ return -ENXIO; -+ -+ ret = __bcm6345_ext_intc_init(node, num_irqs, irqs, base, shift, -+ toggle_clear_on_ack); -+ if (!ret) -+ return 0; -+ -+ iounmap(base); -+ -+ for (i = 0; i < num_irqs; i++) -+ irq_dispose_mapping(irqs[i]); -+ -+ return ret; -+} -+ -+IRQCHIP_DECLARE(bcm6318_ext_intc, "brcm,bcm6318-ext-intc", -+ bcm6345_ext_intc_of_init); -+IRQCHIP_DECLARE(bcm6345_ext_intc, "brcm,bcm6345-ext-intc", -+ bcm6345_ext_intc_of_init); -+#endif ---- /dev/null -+++ b/include/linux/irqchip/irq-bcm6345-ext.h -@@ -0,0 +1,14 @@ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 2014 Jonas Gorski -+ */ -+ -+#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H -+#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H -+ -+void bcm6345_ext_intc_init(int n_irqs, int *irqs, void __iomem *reg, int shift); -+ -+#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H */ diff --git a/target/linux/bmips/patches-5.15/200-mips-bmips-automatically-detect-CPU-frequency.patch b/target/linux/bmips/patches-5.15/200-mips-bmips-automatically-detect-CPU-frequency.patch deleted file mode 100644 index e2b73e6ac4..0000000000 --- a/target/linux/bmips/patches-5.15/200-mips-bmips-automatically-detect-CPU-frequency.patch +++ /dev/null @@ -1,239 +0,0 @@ -From 0377ad93031d3e51c2afe44231241185f684b6af Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Fri, 5 Mar 2021 15:14:32 +0100 -Subject: [PATCH] mips: bmips: automatically detect CPU frequency -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some BCM63xx SoCs support multiple CPU frequencies depending on HW config. - -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/bmips/setup.c | 197 ++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 190 insertions(+), 7 deletions(-) - ---- a/arch/mips/bmips/setup.c -+++ b/arch/mips/bmips/setup.c -@@ -31,13 +31,52 @@ - - #define RELO_NORMAL_VEC BIT(18) - -+#define REG_BCM6318_SOB ((void __iomem *)CKSEG1ADDR(0x10000900)) -+#define BCM6318_FREQ_SHIFT 23 -+#define BCM6318_FREQ_MASK (0x3 << BCM6318_FREQ_SHIFT) -+ - #define REG_BCM6328_OTP ((void __iomem *)CKSEG1ADDR(0x1000062c)) - #define BCM6328_TP1_DISABLED BIT(9) -+#define REG_BCM6328_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001a40)) -+#define BCM6328_FCVO_SHIFT 7 -+#define BCM6328_FCVO_MASK (0x1f << BCM6328_FCVO_SHIFT) -+ -+#define REG_BCM6358_DDR_PLLC ((void __iomem *)0xfffe12b8) -+#define BCM6358_PLLC_M1_SHIFT 0 -+#define BCM6358_PLLC_M1_MASK (0xff << BCM6358_PLLC_M1_SHIFT) -+#define BCM6358_PLLC_N1_SHIFT 23 -+#define BCM6358_PLLC_N1_MASK (0x3f << BCM6358_PLLC_N1_SHIFT) -+#define BCM6358_PLLC_N2_SHIFT 29 -+#define BCM6358_PLLC_N2_MASK (0x7 << BCM6358_PLLC_N2_SHIFT) -+ -+#define REG_BCM6362_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814)) -+#define BCM6362_FCVO_SHIFT 1 -+#define BCM6362_FCVO_MASK (0x1f << BCM6362_FCVO_SHIFT) -+ -+#define REG_BCM6368_DDR_PLLC ((void __iomem *)CKSEG1ADDR(0x100012a0)) -+#define BCM6368_PLLC_P1_SHIFT 0 -+#define BCM6368_PLLC_P1_MASK (0xf << BCM6368_PLLC_P1_SHIFT) -+#define BCM6368_PLLC_P2_SHIFT 4 -+#define BCM6368_PLLC_P2_MASK (0xf << BCM6368_PLLC_P2_SHIFT) -+#define BCM6368_PLLC_NDIV_SHIFT 16 -+#define BCM6368_PLLC_NDIV_MASK (0x1ff << BCM6368_PLLC_NDIV_SHIFT) -+#define REG_BCM6368_DDR_PLLD ((void __iomem *)CKSEG1ADDR(0x100012a4)) -+#define BCM6368_PLLD_MDIV_SHIFT 0 -+#define BCM6368_PLLD_MDIV_MASK (0xff << BCM6368_PLLD_MDIV_SHIFT) -+ -+#define REG_BCM63268_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814)) -+#define BCM63268_FCVO_SHIFT 21 -+#define BCM63268_FCVO_MASK (0xf << BCM63268_FCVO_SHIFT) - - extern bool bmips_rac_flush_disable; - - static const unsigned long kbase = VMLINUX_LOAD_ADDRESS & 0xfff00000; - -+struct bmips_cpufreq { -+ const char *compatible; -+ u32 (*cpu_freq)(void); -+}; -+ - struct bmips_quirk { - const char *compatible; - void (*quirk_fn)(void); -@@ -142,17 +181,161 @@ const char *get_system_type(void) - return "Generic BMIPS kernel"; - } - -+static u32 bcm6318_cpufreq(void) -+{ -+ u32 val = __raw_readl(REG_BCM6318_SOB); -+ -+ switch ((val & BCM6318_FREQ_MASK) >> BCM6318_FREQ_SHIFT) { -+ case 0: -+ return 166000000; -+ case 2: -+ return 250000000; -+ case 3: -+ return 333000000; -+ case 1: -+ return 400000000; -+ default: -+ return 0; -+ } -+} -+ -+static u32 bcm6328_cpufreq(void) -+{ -+ u32 val = __raw_readl(REG_BCM6328_MISC_SB); -+ -+ switch ((val & BCM6328_FCVO_MASK) >> BCM6328_FCVO_SHIFT) { -+ case 0x12: -+ case 0x14: -+ case 0x19: -+ return 160000000; -+ case 0x1c: -+ return 192000000; -+ case 0x13: -+ case 0x15: -+ return 200000000; -+ case 0x1a: -+ return 384000000; -+ case 0x16: -+ return 400000000; -+ default: -+ return 320000000; -+ } -+} -+ -+static u32 bcm6358_cpufreq(void) -+{ -+ u32 val, n1, n2, m1; -+ -+ val = __raw_readl(REG_BCM6358_DDR_PLLC); -+ n1 = (val & BCM6358_PLLC_N1_MASK) >> BCM6358_PLLC_N1_SHIFT; -+ n2 = (val & BCM6358_PLLC_N2_MASK) >> BCM6358_PLLC_N2_SHIFT; -+ m1 = (val & BCM6358_PLLC_M1_MASK) >> BCM6358_PLLC_M1_SHIFT; -+ -+ return (16 * 1000000 * n1 * n2) / m1; -+} -+ -+static u32 bcm6362_cpufreq(void) -+{ -+ u32 val = __raw_readl(REG_BCM6362_MISC_SB); -+ -+ switch ((val & BCM6362_FCVO_MASK) >> BCM6362_FCVO_SHIFT) { -+ case 0x04: -+ case 0x0c: -+ case 0x14: -+ case 0x1c: -+ return 160000000; -+ case 0x15: -+ case 0x1d: -+ return 200000000; -+ case 0x03: -+ case 0x0b: -+ case 0x13: -+ case 0x1b: -+ return 240000000; -+ case 0x07: -+ case 0x17: -+ return 384000000; -+ case 0x05: -+ case 0x0e: -+ case 0x16: -+ case 0x1e: -+ case 0x1f: -+ return 400000000; -+ case 0x06: -+ return 440000000; -+ default: -+ return 320000000; -+ } -+} -+ -+static u32 bcm6368_cpufreq(void) -+{ -+ u32 val, p1, p2, ndiv, m1; -+ -+ val = __raw_readl(REG_BCM6368_DDR_PLLC); -+ p1 = (val & BCM6368_PLLC_P1_MASK) >> BCM6368_PLLC_P1_SHIFT; -+ p2 = (val & BCM6368_PLLC_P2_MASK) >> BCM6368_PLLC_P2_SHIFT; -+ ndiv = (val & BCM6368_PLLC_NDIV_MASK) >> -+ BCM6368_PLLC_NDIV_SHIFT; -+ -+ val = __raw_readl(REG_BCM6368_DDR_PLLD); -+ m1 = (val & BCM6368_PLLD_MDIV_MASK) >> BCM6368_PLLD_MDIV_SHIFT; -+ -+ return (((64 * 1000000) / p1) * p2 * ndiv) / m1; -+} -+ -+static u32 bcm63268_cpufreq(void) -+{ -+ u32 val = __raw_readl(REG_BCM63268_MISC_SB); -+ -+ switch ((val & BCM63268_FCVO_MASK) >> BCM63268_FCVO_SHIFT) { -+ case 0x3: -+ case 0xe: -+ return 320000000; -+ case 0xa: -+ return 333000000; -+ case 0x2: -+ case 0xb: -+ case 0xf: -+ return 400000000; -+ default: -+ return 0; -+ } -+} -+ -+static const struct bmips_cpufreq bmips_cpufreq_list[] = { -+ { "brcm,bcm6318", &bcm6318_cpufreq }, -+ { "brcm,bcm6328", &bcm6328_cpufreq }, -+ { "brcm,bcm6358", &bcm6358_cpufreq }, -+ { "brcm,bcm6362", &bcm6362_cpufreq }, -+ { "brcm,bcm6368", &bcm6368_cpufreq }, -+ { "brcm,bcm63268", &bcm63268_cpufreq }, -+ { /* sentinel */ } -+}; -+ - void __init plat_time_init(void) - { -+ const struct bmips_cpufreq *cf; - struct device_node *np; -- u32 freq; -+ u32 freq = 0; - -- np = of_find_node_by_name(NULL, "cpus"); -- if (!np) -- panic("missing 'cpus' DT node"); -- if (of_property_read_u32(np, "mips-hpt-frequency", &freq) < 0) -- panic("missing 'mips-hpt-frequency' property"); -- of_node_put(np); -+ for (cf = bmips_cpufreq_list; cf->cpu_freq; cf++) { -+ if (of_flat_dt_is_compatible(of_get_flat_dt_root(), -+ cf->compatible)) { -+ freq = cf->cpu_freq() / 2; -+ printk("%s detected @ %u MHz\n", cf->compatible, freq / 500000); -+ break; -+ } -+ } -+ -+ if (!freq) { -+ np = of_find_node_by_name(NULL, "cpus"); -+ if (!np) -+ panic("missing 'cpus' DT node"); -+ if (of_property_read_u32(np, "mips-hpt-frequency", &freq) < 0) -+ panic("missing 'mips-hpt-frequency' property"); -+ of_node_put(np); -+ } - - mips_hpt_frequency = freq; - } diff --git a/target/linux/bmips/patches-5.15/201-mips-bmips-automatically-detect-RAM-size.patch b/target/linux/bmips/patches-5.15/201-mips-bmips-automatically-detect-RAM-size.patch deleted file mode 100644 index c0bdb0d5ce..0000000000 --- a/target/linux/bmips/patches-5.15/201-mips-bmips-automatically-detect-RAM-size.patch +++ /dev/null @@ -1,196 +0,0 @@ -From f9ee3f28ecb979c77423be965ef9dd313bdb9e9b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Mon, 8 Mar 2021 16:58:34 +0100 -Subject: [PATCH] mips: bmips: automatically detect RAM size -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some devices have different amounts of RAM installed depending on HW revision. - -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/bmips/setup.c | 119 ++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 119 insertions(+) - ---- a/arch/mips/bmips/setup.c -+++ b/arch/mips/bmips/setup.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -34,13 +35,16 @@ - #define REG_BCM6318_SOB ((void __iomem *)CKSEG1ADDR(0x10000900)) - #define BCM6318_FREQ_SHIFT 23 - #define BCM6318_FREQ_MASK (0x3 << BCM6318_FREQ_SHIFT) -+#define BCM6318_SDRAM_ADDR ((void __iomem *)CKSEG1ADDR(0x10004000)) - - #define REG_BCM6328_OTP ((void __iomem *)CKSEG1ADDR(0x1000062c)) - #define BCM6328_TP1_DISABLED BIT(9) - #define REG_BCM6328_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001a40)) - #define BCM6328_FCVO_SHIFT 7 - #define BCM6328_FCVO_MASK (0x1f << BCM6328_FCVO_SHIFT) -+#define BCM6328_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10003000)) - -+#define BCM6358_MEMC_ADDR ((void __iomem *)0xfffe1200) - #define REG_BCM6358_DDR_PLLC ((void __iomem *)0xfffe12b8) - #define BCM6358_PLLC_M1_SHIFT 0 - #define BCM6358_PLLC_M1_MASK (0xff << BCM6358_PLLC_M1_SHIFT) -@@ -52,7 +56,9 @@ - #define REG_BCM6362_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814)) - #define BCM6362_FCVO_SHIFT 1 - #define BCM6362_FCVO_MASK (0x1f << BCM6362_FCVO_SHIFT) -+#define BCM6362_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10003000)) - -+#define BCM6368_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10001200)) - #define REG_BCM6368_DDR_PLLC ((void __iomem *)CKSEG1ADDR(0x100012a0)) - #define BCM6368_PLLC_P1_SHIFT 0 - #define BCM6368_PLLC_P1_MASK (0xf << BCM6368_PLLC_P1_SHIFT) -@@ -67,6 +73,21 @@ - #define REG_BCM63268_MISC_SB ((void __iomem *)CKSEG1ADDR(0x10001814)) - #define BCM63268_FCVO_SHIFT 21 - #define BCM63268_FCVO_MASK (0xf << BCM63268_FCVO_SHIFT) -+#define BCM63268_MEMC_ADDR ((void __iomem *)CKSEG1ADDR(0x10003000)) -+ -+#define SDRAM_CFG_REG 0x0 -+#define SDRAM_SPACE_SHIFT 4 -+#define SDRAM_SPACE_MASK (0xf << SDRAM_SPACE_SHIFT) -+ -+#define MEMC_CFG_REG 0x4 -+#define MEMC_CFG_32B_SHIFT 1 -+#define MEMC_CFG_32B_MASK (1 << MEMC_CFG_32B_SHIFT) -+#define MEMC_CFG_COL_SHIFT 3 -+#define MEMC_CFG_COL_MASK (0x3 << MEMC_CFG_COL_SHIFT) -+#define MEMC_CFG_ROW_SHIFT 6 -+#define MEMC_CFG_ROW_MASK (0x3 << MEMC_CFG_ROW_SHIFT) -+ -+#define DDR_CSEND_REG 0x8 - - extern bool bmips_rac_flush_disable; - -@@ -77,6 +98,11 @@ struct bmips_cpufreq { - u32 (*cpu_freq)(void); - }; - -+struct bmips_memsize { -+ const char *compatible; -+ phys_addr_t (*mem_size)(void); -+}; -+ - struct bmips_quirk { - const char *compatible; - void (*quirk_fn)(void); -@@ -340,9 +366,90 @@ void __init plat_time_init(void) - mips_hpt_frequency = freq; - } - -+static inline phys_addr_t bmips_dram_size(unsigned int cols, -+ unsigned int rows, -+ unsigned int is_32b, -+ unsigned int banks) -+{ -+ rows += 11; /* 0 => 11 address bits ... 2 => 13 address bits */ -+ cols += 8; /* 0 => 8 address bits ... 2 => 10 address bits */ -+ is_32b += 1; -+ -+ return 1 << (cols + rows + is_32b + banks); -+} -+ -+static phys_addr_t _bcm6318_memsize(void __iomem *addr) -+{ -+ u32 val; -+ -+ val = __raw_readl(addr + SDRAM_CFG_REG); -+ val = (val & SDRAM_SPACE_MASK) >> SDRAM_SPACE_SHIFT; -+ -+ return (1 << (val + 20)); -+} -+ -+static phys_addr_t _bcm6328_memsize(void __iomem *addr) -+{ -+ return __raw_readl(addr + DDR_CSEND_REG) << 24; -+} -+ -+static phys_addr_t _bcm6358_memsize(void __iomem *addr) -+{ -+ unsigned int cols, rows, is_32b; -+ u32 val; -+ -+ val = __raw_readl(addr + MEMC_CFG_REG); -+ rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT; -+ cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT; -+ is_32b = (val & MEMC_CFG_32B_MASK) ? 0 : 1; -+ -+ return bmips_dram_size(cols, rows, is_32b, 2); -+} -+ -+static phys_addr_t bcm6318_memsize(void) -+{ -+ return _bcm6318_memsize(BCM6318_SDRAM_ADDR); -+} -+ -+static phys_addr_t bcm6328_memsize(void) -+{ -+ return _bcm6328_memsize(BCM6328_MEMC_ADDR); -+} -+ -+static phys_addr_t bcm6358_memsize(void) -+{ -+ return _bcm6358_memsize(BCM6358_MEMC_ADDR); -+} -+ -+static phys_addr_t bcm6362_memsize(void) -+{ -+ return _bcm6328_memsize(BCM6362_MEMC_ADDR); -+} -+ -+static phys_addr_t bcm6368_memsize(void) -+{ -+ return _bcm6358_memsize(BCM6368_MEMC_ADDR); -+} -+ -+static phys_addr_t bcm63268_memsize(void) -+{ -+ return _bcm6328_memsize(BCM63268_MEMC_ADDR); -+} -+ -+static const struct bmips_memsize bmips_memsize_list[] = { -+ { "brcm,bcm6318", &bcm6318_memsize }, -+ { "brcm,bcm6328", &bcm6328_memsize }, -+ { "brcm,bcm6358", &bcm6358_memsize }, -+ { "brcm,bcm6362", &bcm6362_memsize }, -+ { "brcm,bcm6368", &bcm6368_memsize }, -+ { "brcm,bcm63268", &bcm63268_memsize }, -+ { /* sentinel */ } -+}; -+ - void __init plat_mem_setup(void) - { - void *dtb; -+ const struct bmips_memsize *ms; - const struct bmips_quirk *q; - - set_io_port_base(0); -@@ -360,6 +467,18 @@ void __init plat_mem_setup(void) - - __dt_setup_arch(dtb); - -+ for (ms = bmips_memsize_list; ms->mem_size; ms++) { -+ if (of_flat_dt_is_compatible(of_get_flat_dt_root(), -+ ms->compatible)) { -+ phys_addr_t mem = ms->mem_size(); -+ if (mem) { -+ memblock_add(0, mem); -+ printk("%uMB of RAM installed\n", mem >> 20); -+ break; -+ } -+ } -+ } -+ - for (q = bmips_quirk_list; q->quirk_fn; q++) { - if (of_flat_dt_is_compatible(of_get_flat_dt_root(), - q->compatible)) { diff --git a/target/linux/bmips/patches-5.15/202-mips-bmips-tweak-Kconfig-options.patch b/target/linux/bmips/patches-5.15/202-mips-bmips-tweak-Kconfig-options.patch deleted file mode 100644 index 79d4f98e0a..0000000000 --- a/target/linux/bmips/patches-5.15/202-mips-bmips-tweak-Kconfig-options.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 20a4b57c0fafd23ae0f6bcab5b5adf4af4c80280 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Thu, 16 Mar 2023 19:31:21 +0100 -Subject: [PATCH] mips: bmips: tweak Kconfig options -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/Kconfig | 7 +------ - 1 file changed, 1 insertion(+), 6 deletions(-) - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -276,25 +276,20 @@ config BMIPS_GENERIC - select SYNC_R4K - select COMMON_CLK - select BCM6345_L1_IRQ -- select BCM7038_L1_IRQ -- select BCM7120_L2_IRQ -- select BRCMSTB_L2_IRQ - select IRQ_MIPS_CPU - select DMA_NONCOHERENT - select SYS_SUPPORTS_32BIT_KERNEL -- select SYS_SUPPORTS_LITTLE_ENDIAN - select SYS_SUPPORTS_BIG_ENDIAN -- select SYS_SUPPORTS_HIGHMEM - select SYS_HAS_CPU_BMIPS32_3300 - select SYS_HAS_CPU_BMIPS4350 - select SYS_HAS_CPU_BMIPS4380 -- select SYS_HAS_CPU_BMIPS5000 - select SWAP_IO_SPACE - select USB_EHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN - select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN - select USB_OHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN - select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN - select HARDIRQS_SW_RESEND -+ select MIPS_L1_CACHE_SHIFT_4 - help - Build a generic DT-based kernel image that boots on select - BCM33xx cable modem chips, BCM63xx DSL chips, and BCM7xxx set-top diff --git a/target/linux/bmips/patches-5.15/203-mips-bmips-dma-fix-CBR-address.patch b/target/linux/bmips/patches-5.15/203-mips-bmips-dma-fix-CBR-address.patch deleted file mode 100644 index 57bf395e2e..0000000000 --- a/target/linux/bmips/patches-5.15/203-mips-bmips-dma-fix-CBR-address.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 3e4c3863e0cfb8c2abdff6bb494ca69d3d2aed9c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Sat, 10 Jun 2023 17:01:40 +0200 -Subject: [PATCH] mips: bmips: dma: fix CBR address -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some BCM63xx SoCs may return CBR address as 0. - -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/bmips/dma.c | 12 ++++-------- - arch/mips/bmips/setup.c | 11 ++++------- - 2 files changed, 8 insertions(+), 15 deletions(-) - ---- a/arch/mips/bmips/dma.c -+++ b/arch/mips/bmips/dma.c -@@ -64,11 +64,10 @@ phys_addr_t dma_to_phys(struct device *d - return dma_addr; - } - --bool bmips_rac_flush_disable; -+void __iomem *bmips_cbr_addr; - - void arch_sync_dma_for_cpu_all(void) - { -- void __iomem *cbr = BMIPS_GET_CBR(); - u32 cfg; - - if (boot_cpu_type() != CPU_BMIPS3300 && -@@ -76,13 +75,10 @@ void arch_sync_dma_for_cpu_all(void) - boot_cpu_type() != CPU_BMIPS4380) - return; - -- if (unlikely(bmips_rac_flush_disable)) -- return; -- - /* Flush stale data out of the readahead cache */ -- cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG); -- __raw_writel(cfg | 0x100, cbr + BMIPS_RAC_CONFIG); -- __raw_readl(cbr + BMIPS_RAC_CONFIG); -+ cfg = __raw_readl(bmips_cbr_addr + BMIPS_RAC_CONFIG); -+ __raw_writel(cfg | 0x100, bmips_cbr_addr + BMIPS_RAC_CONFIG); -+ __raw_readl(bmips_cbr_addr + BMIPS_RAC_CONFIG); - } - - static int __init bmips_init_dma_ranges(void) ---- a/arch/mips/bmips/setup.c -+++ b/arch/mips/bmips/setup.c -@@ -89,7 +89,7 @@ - - #define DDR_CSEND_REG 0x8 - --extern bool bmips_rac_flush_disable; -+extern void __iomem *bmips_cbr_addr; - - static const unsigned long kbase = VMLINUX_LOAD_ADDRESS & 0xfff00000; - -@@ -170,12 +170,6 @@ static void bcm6358_quirks(void) - * disable SMP for now - */ - bmips_smp_enabled = 0; -- -- /* -- * RAC flush causes kernel panics on BCM6358 when booting from TP1 -- * because the bootloader is not initializing it properly. -- */ -- bmips_rac_flush_disable = !!(read_c0_brcm_cmt_local() & (1 << 31)); - } - - static void bcm6368_quirks(void) -@@ -198,6 +192,11 @@ static const struct bmips_quirk bmips_qu - - void __init prom_init(void) - { -+ if (!(read_c0_brcm_cbr() >> 18)) -+ bmips_cbr_addr = (void __iomem *)0xff400000; -+ else -+ bmips_cbr_addr = BMIPS_GET_CBR(); -+ - bmips_cpu_setup(); - register_bmips_smp_ops(); - } diff --git a/target/linux/bmips/patches-5.15/204-mips-bmips-enable-RAC-on-BMIPS4350.patch b/target/linux/bmips/patches-5.15/204-mips-bmips-enable-RAC-on-BMIPS4350.patch deleted file mode 100644 index 26bd03e329..0000000000 --- a/target/linux/bmips/patches-5.15/204-mips-bmips-enable-RAC-on-BMIPS4350.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 7f862eaedac56b67972393f0a9affcd2fe53479b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Daniel=20Gonz=C3=A1lez=20Cabanelas?= -Date: Sun, 18 Jun 2023 19:59:25 +0200 -Subject: [PATCH] mips: bmips: enable RAC on BMIPS4350 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The data RAC is left disabled by the bootloader in some SoCs, at least in -the core it boots from. -Enabling this feature increases the performance up to +30% depending on the -task. - -Signed-off-by: Daniel González Cabanelas -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/kernel/smp-bmips.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - ---- a/arch/mips/kernel/smp-bmips.c -+++ b/arch/mips/kernel/smp-bmips.c -@@ -614,6 +614,20 @@ void bmips_cpu_setup(void) - __raw_readl(cbr + BMIPS_RAC_ADDRESS_RANGE); - break; - -+ case CPU_BMIPS4350: -+ /* Enable data RAC */ -+ if (!(read_c0_brcm_cmt_local() & (1 << 31))) { -+ cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG); -+ __raw_writel(cfg | 0xa, cbr + BMIPS_RAC_CONFIG); -+ __raw_readl(cbr + BMIPS_RAC_CONFIG); -+ } else { -+ cbr = (void __iomem *)0xff400000; -+ cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG_1); -+ __raw_writel(cfg | 0xa, cbr + BMIPS_RAC_CONFIG_1); -+ __raw_readl(cbr + BMIPS_RAC_CONFIG_1); -+ } -+ break; -+ - case CPU_BMIPS4380: - /* CBG workaround for early BMIPS4380 CPUs */ - switch (read_c0_prid()) { diff --git a/target/linux/bmips/patches-5.15/210-macronix_nand_block_protection_support.patch b/target/linux/bmips/patches-5.15/210-macronix_nand_block_protection_support.patch deleted file mode 100644 index 25a16084ef..0000000000 --- a/target/linux/bmips/patches-5.15/210-macronix_nand_block_protection_support.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 5a37811de679bff03e9c5a746f75574910ede964 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 22 Mar 2023 20:52:13 +0100 -Subject: [PATCH] Revert "mtd: rawnand: Macronix: Add support for block - protection" -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This reverts commit 03a539c7a118427a6609a26461358c56ac8f3a06. - -Macronix block protection doesn't seem to be supported on Sercomm H-500s -devices since it hangs the device. - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/mtd/nand/raw/nand_macronix.c | 72 ---------------------------- - 1 file changed, 72 deletions(-) - ---- a/drivers/mtd/nand/raw/nand_macronix.c -+++ b/drivers/mtd/nand/raw/nand_macronix.c -@@ -12,10 +12,6 @@ - #define MACRONIX_READ_RETRY_BIT BIT(0) - #define MACRONIX_NUM_READ_RETRY_MODES 6 - --#define ONFI_FEATURE_ADDR_MXIC_PROTECTION 0xA0 --#define MXIC_BLOCK_PROTECTION_ALL_LOCK 0x38 --#define MXIC_BLOCK_PROTECTION_ALL_UNLOCK 0x0 -- - #define ONFI_FEATURE_ADDR_MXIC_RANDOMIZER 0xB0 - #define MACRONIX_RANDOMIZER_BIT BIT(1) - #define MACRONIX_RANDOMIZER_ENPGM BIT(0) -@@ -179,73 +175,6 @@ static void macronix_nand_fix_broken_get - ONFI_FEATURE_ADDR_TIMING_MODE, 1); - } - --/* -- * Macronix NAND supports Block Protection by Protectoin(PT) pin; -- * active high at power-on which protects the entire chip even the #WP is -- * disabled. Lock/unlock protection area can be partition according to -- * protection bits, i.e. upper 1/2 locked, upper 1/4 locked and so on. -- */ --static int mxic_nand_lock(struct nand_chip *chip, loff_t ofs, uint64_t len) --{ -- u8 feature[ONFI_SUBFEATURE_PARAM_LEN]; -- int ret; -- -- feature[0] = MXIC_BLOCK_PROTECTION_ALL_LOCK; -- nand_select_target(chip, 0); -- ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION, -- feature); -- nand_deselect_target(chip); -- if (ret) -- pr_err("%s all blocks failed\n", __func__); -- -- return ret; --} -- --static int mxic_nand_unlock(struct nand_chip *chip, loff_t ofs, uint64_t len) --{ -- u8 feature[ONFI_SUBFEATURE_PARAM_LEN]; -- int ret; -- -- feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK; -- nand_select_target(chip, 0); -- ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION, -- feature); -- nand_deselect_target(chip); -- if (ret) -- pr_err("%s all blocks failed\n", __func__); -- -- return ret; --} -- --static void macronix_nand_block_protection_support(struct nand_chip *chip) --{ -- u8 feature[ONFI_SUBFEATURE_PARAM_LEN]; -- int ret; -- -- bitmap_set(chip->parameters.get_feature_list, -- ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1); -- -- feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK; -- nand_select_target(chip, 0); -- ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION, -- feature); -- nand_deselect_target(chip); -- if (ret || feature[0] != MXIC_BLOCK_PROTECTION_ALL_LOCK) { -- if (ret) -- pr_err("Block protection check failed\n"); -- -- bitmap_clear(chip->parameters.get_feature_list, -- ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1); -- return; -- } -- -- bitmap_set(chip->parameters.set_feature_list, -- ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1); -- -- chip->ops.lock_area = mxic_nand_lock; -- chip->ops.unlock_area = mxic_nand_unlock; --} -- - static int nand_power_down_op(struct nand_chip *chip) - { - int ret; -@@ -323,7 +252,6 @@ static int macronix_nand_init(struct nan - - macronix_nand_fix_broken_get_timings(chip); - macronix_nand_onfi_init(chip); -- macronix_nand_block_protection_support(chip); - macronix_nand_deep_power_down_support(chip); - - return 0; diff --git a/target/linux/bmips/patches-5.15/500-net-broadcom-add-BCM6368-enetsw-controller-driver.patch b/target/linux/bmips/patches-5.15/500-net-broadcom-add-BCM6368-enetsw-controller-driver.patch deleted file mode 100644 index 71ed53235f..0000000000 --- a/target/linux/bmips/patches-5.15/500-net-broadcom-add-BCM6368-enetsw-controller-driver.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 590b60fb08cb1e70fe02d3f407c6b3dbe9ad06ff Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Mon, 1 Mar 2021 07:34:39 +0100 -Subject: [PATCH] net: broadcom: add BCM6368 enetsw controller driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This controller is present on BCM6318, BCM6328, BCM6362, BCM6368 and BCM63268 -SoCs. - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/net/ethernet/broadcom/Kconfig | 8 ++++++++ - drivers/net/ethernet/broadcom/Makefile | 1 + - 2 files changed, 9 insertions(+) - ---- a/drivers/net/ethernet/broadcom/Kconfig -+++ b/drivers/net/ethernet/broadcom/Kconfig -@@ -68,6 +68,14 @@ config BCM63XX_ENET - This driver supports the ethernet MACs in the Broadcom 63xx - MIPS chipset family (BCM63XX). - -+config BCM6368_ENETSW -+ tristate "Broadcom BCM6368 internal mac support" -+ depends on BMIPS_GENERIC || COMPILE_TEST -+ default y -+ help -+ This driver supports Ethernet controller integrated into Broadcom -+ BCM6368 family SoCs. -+ - config BCMGENET - tristate "Broadcom GENET internal MAC support" - depends on HAS_IOMEM ---- a/drivers/net/ethernet/broadcom/Makefile -+++ b/drivers/net/ethernet/broadcom/Makefile -@@ -6,6 +6,7 @@ - obj-$(CONFIG_B44) += b44.o - obj-$(CONFIG_BCM4908_ENET) += bcm4908_enet.o - obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o -+obj-$(CONFIG_BCM6368_ENETSW) += bcm6368-enetsw.o - obj-$(CONFIG_BCMGENET) += genet/ - obj-$(CONFIG_BNX2) += bnx2.o - obj-$(CONFIG_CNIC) += cnic.o diff --git a/target/linux/bmips/patches-5.15/501-net-broadcom-add-BCM6348-enet-controller-driver.patch b/target/linux/bmips/patches-5.15/501-net-broadcom-add-BCM6348-enet-controller-driver.patch deleted file mode 100644 index af09f4dd4f..0000000000 --- a/target/linux/bmips/patches-5.15/501-net-broadcom-add-BCM6348-enet-controller-driver.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 590b60fb08cb1e70fe02d3f407c6b3dbe9ad06ff Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Mon, 1 Mar 2021 07:34:39 +0100 -Subject: [PATCH] net: broadcom: add BCM6348 enetsw controller driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This controller is present on BCM6338, BCM6348 and BCM6358 SoCs. - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/net/ethernet/broadcom/Kconfig | 8 ++++++++ - drivers/net/ethernet/broadcom/Makefile | 1 + - 2 files changed, 9 insertions(+) - ---- a/drivers/net/ethernet/broadcom/Kconfig -+++ b/drivers/net/ethernet/broadcom/Kconfig -@@ -68,6 +68,14 @@ config BCM63XX_ENET - This driver supports the ethernet MACs in the Broadcom 63xx - MIPS chipset family (BCM63XX). - -+config BCM6348_ENET -+ tristate "Broadcom BCM6348 internal mac support" -+ depends on BMIPS_GENERIC || COMPILE_TEST -+ default y -+ help -+ This driver supports Ethernet controller integrated into Broadcom -+ BCM6348 family SoCs. -+ - config BCM6368_ENETSW - tristate "Broadcom BCM6368 internal mac support" - depends on BMIPS_GENERIC || COMPILE_TEST ---- a/drivers/net/ethernet/broadcom/Makefile -+++ b/drivers/net/ethernet/broadcom/Makefile -@@ -6,6 +6,7 @@ - obj-$(CONFIG_B44) += b44.o - obj-$(CONFIG_BCM4908_ENET) += bcm4908_enet.o - obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o -+obj-$(CONFIG_BCM6348_ENET) += bcm6348-enet.o - obj-$(CONFIG_BCM6368_ENETSW) += bcm6368-enetsw.o - obj-$(CONFIG_BCMGENET) += genet/ - obj-$(CONFIG_BNX2) += bnx2.o diff --git a/target/linux/bmips/patches-5.15/502-net-mdio-mux-bcm6368-allow-disabling.patch b/target/linux/bmips/patches-5.15/502-net-mdio-mux-bcm6368-allow-disabling.patch deleted file mode 100644 index 6071bea42d..0000000000 --- a/target/linux/bmips/patches-5.15/502-net-mdio-mux-bcm6368-allow-disabling.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 21145a89c79a22c4fb719cce5a2f4e3373d39756 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 May 2023 18:16:46 +0200 -Subject: [PATCH] net: mdio: mux-bcm6368: allow disabling for bmips -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/net/mdio/Kconfig | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/net/mdio/Kconfig -+++ b/drivers/net/mdio/Kconfig -@@ -219,7 +219,6 @@ config MDIO_BUS_MUX_BCM6368 - tristate "Broadcom BCM6368 MDIO bus multiplexers" - depends on OF && OF_MDIO && (BMIPS_GENERIC || COMPILE_TEST) - select MDIO_BUS_MUX -- default BMIPS_GENERIC - help - This module provides a driver for MDIO bus multiplexers found in - BCM6368 based Broadcom SoCs. This multiplexer connects one of several diff --git a/target/linux/bmips/patches-5.15/600-mips-bmips-add-pci-support.patch b/target/linux/bmips/patches-5.15/600-mips-bmips-add-pci-support.patch deleted file mode 100644 index 2f19d1e489..0000000000 --- a/target/linux/bmips/patches-5.15/600-mips-bmips-add-pci-support.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 7742c1ba191a005a1356ff89b5fe2279d6f0ec4d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 May 2023 18:18:43 +0200 -Subject: [PATCH] mips: bmips: add PCI support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - arch/mips/Kconfig | 1 + - arch/mips/pci/Makefile | 1 + - 2 files changed, 2 insertions(+) - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -276,6 +276,7 @@ config BMIPS_GENERIC - select SYNC_R4K - select COMMON_CLK - select BCM6345_L1_IRQ -+ select HAVE_PCI - select IRQ_MIPS_CPU - select DMA_NONCOHERENT - select SYS_SUPPORTS_32BIT_KERNEL ---- a/arch/mips/pci/Makefile -+++ b/arch/mips/pci/Makefile -@@ -28,6 +28,7 @@ obj-$(CONFIG_PCI_XTALK_BRIDGE) += pci-xt - # These are still pretty much in the old state, watch, go blind. - # - obj-$(CONFIG_ATH79) += fixup-ath79.o -+obj-$(CONFIG_BMIPS_GENERIC) += fixup-bmips.o - obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o - obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o - obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o diff --git a/target/linux/bmips/patches-5.15/601-pci-controllers-add-bcm6328-pcie-support.patch b/target/linux/bmips/patches-5.15/601-pci-controllers-add-bcm6328-pcie-support.patch deleted file mode 100644 index c976430fd5..0000000000 --- a/target/linux/bmips/patches-5.15/601-pci-controllers-add-bcm6328-pcie-support.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 49133041e0a5770decf1a25f575764d13a0d425c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 May 2023 18:20:10 +0200 -Subject: [PATCH] pci: add bcm6328-pcie support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/pci/controller/Kconfig | 5 +++++ - drivers/pci/controller/Makefile | 1 + - 2 files changed, 6 insertions(+) - ---- a/drivers/pci/controller/Kconfig -+++ b/drivers/pci/controller/Kconfig -@@ -3,6 +3,11 @@ - menu "PCI controller drivers" - depends on PCI - -+config PCIE_BCM6328 -+ bool "BCM6328 PCIe controller" -+ depends on BMIPS_GENERIC || COMPILE_TEST -+ depends on OF -+ - config PCI_MVEBU - bool "Marvell EBU PCIe controller" - depends on ARCH_MVEBU || ARCH_DOVE || COMPILE_TEST ---- a/drivers/pci/controller/Makefile -+++ b/drivers/pci/controller/Makefile -@@ -1,4 +1,5 @@ - # SPDX-License-Identifier: GPL-2.0 -+obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o - obj-$(CONFIG_PCIE_CADENCE) += cadence/ - obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o - obj-$(CONFIG_PCI_IXP4XX) += pci-ixp4xx.o diff --git a/target/linux/bmips/patches-5.15/602-pci-controllers-add-bcm6318-pcie-support.patch b/target/linux/bmips/patches-5.15/602-pci-controllers-add-bcm6318-pcie-support.patch deleted file mode 100644 index 1a3ec1db2a..0000000000 --- a/target/linux/bmips/patches-5.15/602-pci-controllers-add-bcm6318-pcie-support.patch +++ /dev/null @@ -1,36 +0,0 @@ -From cc3c30bdc98eabbaa07c64302eb5124a0f4a74f0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 May 2023 18:20:46 +0200 -Subject: [PATCH] pci: add bcm6318-pcie support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/pci/controller/Kconfig | 5 +++++ - drivers/pci/controller/Makefile | 1 + - 2 files changed, 6 insertions(+) - ---- a/drivers/pci/controller/Kconfig -+++ b/drivers/pci/controller/Kconfig -@@ -3,6 +3,11 @@ - menu "PCI controller drivers" - depends on PCI - -+config PCIE_BCM6318 -+ bool "BCM6318 PCIe controller" -+ depends on BMIPS_GENERIC || COMPILE_TEST -+ depends on OF -+ - config PCIE_BCM6328 - bool "BCM6328 PCIe controller" - depends on BMIPS_GENERIC || COMPILE_TEST ---- a/drivers/pci/controller/Makefile -+++ b/drivers/pci/controller/Makefile -@@ -1,4 +1,5 @@ - # SPDX-License-Identifier: GPL-2.0 -+obj-$(CONFIG_PCIE_BCM6318) += pcie-bcm6318.o - obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o - obj-$(CONFIG_PCIE_CADENCE) += cadence/ - obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o diff --git a/target/linux/bmips/patches-5.15/603-pci-controllers-add-bcm6348-pci-support.patch b/target/linux/bmips/patches-5.15/603-pci-controllers-add-bcm6348-pci-support.patch deleted file mode 100644 index 32aeea6a74..0000000000 --- a/target/linux/bmips/patches-5.15/603-pci-controllers-add-bcm6348-pci-support.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 5e7813e5725d79d00e0988472c306490fc48b3e1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 17 May 2023 18:21:19 +0200 -Subject: [PATCH] pci: add bcm6348-pci support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/pci/controller/Kconfig | 5 +++++ - drivers/pci/controller/Makefile | 1 + - 2 files changed, 6 insertions(+) - ---- a/drivers/pci/controller/Kconfig -+++ b/drivers/pci/controller/Kconfig -@@ -3,6 +3,11 @@ - menu "PCI controller drivers" - depends on PCI - -+config PCI_BCM6348 -+ bool "BCM6348 PCI controller" -+ depends on BMIPS_GENERIC || COMPILE_TEST -+ depends on OF -+ - config PCIE_BCM6318 - bool "BCM6318 PCIe controller" - depends on BMIPS_GENERIC || COMPILE_TEST ---- a/drivers/pci/controller/Makefile -+++ b/drivers/pci/controller/Makefile -@@ -1,4 +1,5 @@ - # SPDX-License-Identifier: GPL-2.0 -+obj-$(CONFIG_PCI_BCM6348) += pci-bcm6348.o - obj-$(CONFIG_PCIE_BCM6318) += pcie-bcm6318.o - obj-$(CONFIG_PCIE_BCM6328) += pcie-bcm6328.o - obj-$(CONFIG_PCIE_CADENCE) += cadence/ diff --git a/target/linux/bmips/patches-5.15/700-leds-add-support-for-Sercomm-MSP430-LED-controller.patch b/target/linux/bmips/patches-5.15/700-leds-add-support-for-Sercomm-MSP430-LED-controller.patch deleted file mode 100644 index c6d2df9f8c..0000000000 --- a/target/linux/bmips/patches-5.15/700-leds-add-support-for-Sercomm-MSP430-LED-controller.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 1a5f2263d388016c88d39e141c7eb8085c9313fc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= -Date: Wed, 5 Apr 2023 08:07:00 +0200 -Subject: [PATCH] leds: add support for Sercomm MSP430 LED controller -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Sercomm added an external MSP430G2513 for controlling LEDs through SPI on some -boards. - -Signed-off-by: Álvaro Fernández Rojas ---- - drivers/leds/Kconfig | 9 +++++++++ - drivers/leds/Makefile | 1 + - 2 files changed, 10 insertions(+) - ---- a/drivers/leds/Kconfig -+++ b/drivers/leds/Kconfig -@@ -289,6 +289,15 @@ config LEDS_COBALT_RAQ - help - This option enables support for the Cobalt Raq series LEDs. - -+config LEDS_SERCOMM_MSP430 -+ tristate "LED support for Sercomm MSP430 SPI LED controllers" -+ depends on LEDS_CLASS -+ depends on SPI -+ depends on OF -+ help -+ This option enables support for the Sercomm MSP430G2513 SPI LED -+ controllers. -+ - config LEDS_SUNFIRE - tristate "LED support for SunFire servers." - depends on LEDS_CLASS ---- a/drivers/leds/Makefile -+++ b/drivers/leds/Makefile -@@ -77,6 +77,7 @@ obj-$(CONFIG_LEDS_PWM) += leds-pwm.o - obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o - obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o - obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o -+obj-$(CONFIG_LEDS_SERCOMM_MSP430) += leds-sercomm-msp430.o - obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o - obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o - obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o diff --git a/target/linux/bmips/patches-5.15/800-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch b/target/linux/bmips/patches-5.15/800-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch deleted file mode 100644 index d98d27c6b4..0000000000 --- a/target/linux/bmips/patches-5.15/800-jffs2-work-around-unaligned-accesses-failing-on-bcm6.patch +++ /dev/null @@ -1,26 +0,0 @@ -From ff3409ab17d56450943364ba49a16960e3cdda9b Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -Date: Sun, 6 Apr 2014 22:33:16 +0200 -Subject: [RFC] jffs2: work around unaligned accesses failing on bcm63xx/smp - -Unligned memcpy_fromio randomly fails with an unaligned dst. Work around -it by ensuring we are always doing aligned copies. - -Should fix filename corruption in jffs2 with SMP. - -Signed-off-by: Jonas Gorski ---- - fs/jffs2/nodelist.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/fs/jffs2/nodelist.h -+++ b/fs/jffs2/nodelist.h -@@ -259,7 +259,7 @@ struct jffs2_full_dirent - uint32_t ino; /* == zero for unlink */ - unsigned int nhash; - unsigned char type; -- unsigned char name[]; -+ unsigned char name[] __attribute__((aligned((sizeof(long))))); - }; - - /* From 39ce9338422de3c067d6889d13710ca18108818c Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 16 Jan 2024 13:41:06 +0000 Subject: [PATCH 133/222] layerscape: refresh patches-6.1 Patches no longer cleanly apply after commit c2c741ccce ("generic: 6.1: initial backport of at803x PHY driver cleanup"). Refresh patches to address that. Fixes: c2c741ccce ("generic: 6.1: initial backport of at803x PHY driver cleanup") Signed-off-by: Daniel Golle --- .../patches-6.1/702-phy-Add-2.5G-SGMII-interface-mode.patch | 6 +++--- ...t-phylink-treat-PHY_INTERFACE_MODE_2500SGMII-in-ph.patch | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/layerscape/patches-6.1/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-6.1/702-phy-Add-2.5G-SGMII-interface-mode.patch index 77c9764078..6af915da90 100644 --- a/target/linux/layerscape/patches-6.1/702-phy-Add-2.5G-SGMII-interface-mode.patch +++ b/target/linux/layerscape/patches-6.1/702-phy-Add-2.5G-SGMII-interface-mode.patch @@ -25,7 +25,7 @@ Signed-off-by: Bhaskar Upadhaya case PHY_INTERFACE_MODE_QUSGMII: --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -199,6 +199,7 @@ static int phylink_interface_max_speed(p +@@ -200,6 +200,7 @@ static int phylink_interface_max_speed(p return SPEED_1000; case PHY_INTERFACE_MODE_2500BASEX: @@ -35,7 +35,7 @@ Signed-off-by: Bhaskar Upadhaya case PHY_INTERFACE_MODE_5GBASER: --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -157,6 +157,7 @@ typedef enum { +@@ -159,6 +159,7 @@ typedef enum { PHY_INTERFACE_MODE_10GKR, PHY_INTERFACE_MODE_QUSGMII, PHY_INTERFACE_MODE_1000BASEKX, @@ -43,7 +43,7 @@ Signed-off-by: Bhaskar Upadhaya PHY_INTERFACE_MODE_MAX, } phy_interface_t; -@@ -276,6 +277,8 @@ static inline const char *phy_modes(phy_ +@@ -280,6 +281,8 @@ static inline const char *phy_modes(phy_ return "100base-x"; case PHY_INTERFACE_MODE_QUSGMII: return "qusgmii"; diff --git a/target/linux/layerscape/patches-6.1/704-net-phylink-treat-PHY_INTERFACE_MODE_2500SGMII-in-ph.patch b/target/linux/layerscape/patches-6.1/704-net-phylink-treat-PHY_INTERFACE_MODE_2500SGMII-in-ph.patch index f0d7100945..265756ea70 100644 --- a/target/linux/layerscape/patches-6.1/704-net-phylink-treat-PHY_INTERFACE_MODE_2500SGMII-in-ph.patch +++ b/target/linux/layerscape/patches-6.1/704-net-phylink-treat-PHY_INTERFACE_MODE_2500SGMII-in-ph.patch @@ -32,7 +32,7 @@ Signed-off-by: Ioana Ciornei --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -485,6 +485,7 @@ unsigned long phylink_get_capabilities(p +@@ -487,6 +487,7 @@ unsigned long phylink_get_capabilities(p break; case PHY_INTERFACE_MODE_2500BASEX: From 3df664101a18cf835c97ce5f0fbcc6357a16c101 Mon Sep 17 00:00:00 2001 From: Marty Jones Date: Sun, 24 Dec 2023 19:03:31 -0500 Subject: [PATCH 134/222] bcm27xx-userland: update to latest version This is the last update for bcm27xx-userland as it has been deprecated but funcional up to raspberry pi 5. 96a7334 README: Update to make it clear that most code in this repo is deprecated 3c97f76 userland: dtoverlay: /boot/firmware is a valid path 153a235 Assorted clang static analysis fixes eca070c bcm_host: Update kms/fkms check for pi5 06a7618 dtoverlay: Support bcm2712 as a platform 0489c07 dtoverlay: Add dtoverlay_first/next_subnode a1c7f81 dtoverlay: Support literal assignments of path strings 44a3953 raspivid: Also flush PTS file if flush is enabled cc1ca18 userland: dtoverlay: Use os_prefix if set 9d5250f libfdt: Add null-ptr check for prop-data to resolve clang --analyzer warning 50527c6 mmal: Only include Videocore components if not running on Videocore df245ea tvservice: Update unsupported message to recommend kmsprint de0cfe8 dtoverlay: Fix clang warnings 0182f05 dtoverlay: Fix various compiler warnings 2a6306b dtoverlay: Fix path rebasing and exports d1e92d7 dtoverlay: Add support for string escape sequences b1ee39e gencmd: Add a fallback to mailbox interface if vchiq is not available 54fd97a hello_pi: Fix some build issues Signed-off-by: Marty Jones --- package/utils/bcm27xx-userland/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/utils/bcm27xx-userland/Makefile b/package/utils/bcm27xx-userland/Makefile index 9d7f6dd822..402c3dcd64 100644 --- a/package/utils/bcm27xx-userland/Makefile +++ b/package/utils/bcm27xx-userland/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bcm27xx-userland -PKG_VERSION:=c4fd1b8986c6d6d4ae5cd51e65a8bbeb495dfa4e +PKG_VERSION:=96a7334ae9d5fc9db7ac92e59852377df63f1848 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/raspberrypi/userland/tar.gz/$(PKG_VERSION)? -PKG_HASH:=ab8a5b27c34cf1b97de87b895448a6355229f73b679866b47c51a723273cc8ae +PKG_HASH:=557ee8390de5db1ed90386c1ba0221e7f6f9dd87e858a00a34be3b1f9ede193f PKG_FLAGS:=nonshared From e8f55817015112608155a6463ca2d8f5b4ca37b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 16 Jan 2024 11:58:01 +0100 Subject: [PATCH 135/222] bcm27xx-gpu-fw: update to latest version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit raspberrypi/firmware is about 40G, so getting the full history log isn't an option. There have been multiple improvements and also support for the RPi 5 has been added. Signed-off-by: Álvaro Fernández Rojas --- package/kernel/bcm27xx-gpu-fw/Makefile | 30 +++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/package/kernel/bcm27xx-gpu-fw/Makefile b/package/kernel/bcm27xx-gpu-fw/Makefile index b3323c8b28..048dd0d3a9 100644 --- a/package/kernel/bcm27xx-gpu-fw/Makefile +++ b/package/kernel/bcm27xx-gpu-fw/Makefile @@ -2,8 +2,8 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=bcm27xx-gpu-fw -PKG_VERSION:=2022-05-16 -PKG_RELEASE:=3673be308132de102fdff491d1333d9d0f823557 +PKG_VERSION:=2024-01-11 +PKG_RELEASE:=0968de28716a9b1f106b8492646d0ed0a2800152 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)/rpi-firmware-$(PKG_RELEASE) @@ -26,7 +26,7 @@ define Download/bootcode_bin FILE:=$(RPI_FIRMWARE_FILE)-bootcode.bin URL:=$(RPI_FIRMWARE_URL) URL_FILE:=bootcode.bin - HASH:=69309823da13dc96b89e3d82b44f820e4f84efa79d207adad2c8784559794f03 + HASH:=af603ebd97e7b692c30195563f7b25656eb05d57838cf1a715ebb470d1614ce4 endef $(eval $(call Download,bootcode_bin)) @@ -34,7 +34,7 @@ define Download/fixup_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup.dat - HASH:=921f56c62ad1995addb984b156c869202dc5d46bbe9ebcbd02c20f0def9058e3 + HASH:=c28ea955e672e374016dca61d63afa026490f0473a98115908586ab48e324aeb endef $(eval $(call Download,fixup_dat)) @@ -42,7 +42,7 @@ define Download/fixup_cd_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup_cd.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup_cd.dat - HASH:=83a985aa0d73844786f3b3bf674826c520212f6f72fc6a890f2ebb5f87de5d8c + HASH:=3cf1aef5f596ca106203ed5dac9ad45e85929ec55ce44c813588645e174442ec endef $(eval $(call Download,fixup_cd_dat)) @@ -50,7 +50,7 @@ define Download/fixup_x_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup_x.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup_x.dat - HASH:=8b00b00678adafe01e087240d156dbc87822e745b269be4f282596b69265cd1e + HASH:=56525c8feabde1ab86f36bb09bc55171659b2993f94132cf81ffc4293d62269d endef $(eval $(call Download,fixup_x_dat)) @@ -58,7 +58,7 @@ define Download/fixup4_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup4.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup4.dat - HASH:=ef2b5d2a0a95ca48e00a1ce78b7650ee9e947cc1c588704c8ae30c1623122e2f + HASH:=615f8595801bf52373039f73ad5ad9513f83400d355eb1b2c075c7ae907e927c endef $(eval $(call Download,fixup4_dat)) @@ -66,7 +66,7 @@ define Download/fixup4cd_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup4cd.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup4cd.dat - HASH:=83a985aa0d73844786f3b3bf674826c520212f6f72fc6a890f2ebb5f87de5d8c + HASH:=3cf1aef5f596ca106203ed5dac9ad45e85929ec55ce44c813588645e174442ec endef $(eval $(call Download,fixup4cd_dat)) @@ -74,7 +74,7 @@ define Download/fixup4x_dat FILE:=$(RPI_FIRMWARE_FILE)-fixup4x.dat URL:=$(RPI_FIRMWARE_URL) URL_FILE:=fixup4x.dat - HASH:=a6c4e30ada5a00fe7de83c460638ca824647651bb4a3644b8c65d7ba1d9f2d2b + HASH:=6d27a4b8ecb78cef9e1f03751b4aaec5ce8749d36988f381145a8a41dbf164ae endef $(eval $(call Download,fixup4x_dat)) @@ -82,7 +82,7 @@ define Download/start_elf FILE:=$(RPI_FIRMWARE_FILE)-start.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start.elf - HASH:=5455c148f4b8b04c553809bd22b995ee49ba5279ca3848df8bde6f80a388f7e0 + HASH:=e8348e88522e7a1d0e2b0944ab66d7d8f4f30da98f326e2b3c123522e45f71b2 endef $(eval $(call Download,start_elf)) @@ -90,7 +90,7 @@ define Download/start_cd_elf FILE:=$(RPI_FIRMWARE_FILE)-start_cd.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start_cd.elf - HASH:=168c0a9178d5a3b4bd89ef770826a85b4ea3132560ba3600c212c0cec4c575c6 + HASH:=c9b4de3f12bec7808868b898c49f656b5378ddc315f12ccab83d6519bad51680 endef $(eval $(call Download,start_cd_elf)) @@ -98,7 +98,7 @@ define Download/start_x_elf FILE:=$(RPI_FIRMWARE_FILE)-start_x.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start_x.elf - HASH:=30c6a7f32a25185053ca3ca9e4bcfe932246ed42a1b7c37f8803209f93d86404 + HASH:=0b5c06c109984361eeed0ab14d146f686d8aa8da2025689b887e9cb098636db9 endef $(eval $(call Download,start_x_elf)) @@ -106,7 +106,7 @@ define Download/start4_elf FILE:=$(RPI_FIRMWARE_FILE)-start4.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start4.elf - HASH:=be8bbff41dba2749b7b0e812f0a9d87a9122d18508f7b5ff3cd20f303d15bc07 + HASH:=fedc4ecd72c9d21018e210240dcd2e41a8bb5f936fb5674c3351f2a447a22203 endef $(eval $(call Download,start4_elf)) @@ -114,7 +114,7 @@ define Download/start4cd_elf FILE:=$(RPI_FIRMWARE_FILE)-start4cd.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start4cd.elf - HASH:=000372e9cf6815ade595948dbd6328665f2a535eeee44e74b0ec8e56b6fbbf90 + HASH:=ea22282a77666801378137a651e7e0b17cc186f63cdbdc8b9bb98749cd12b256 endef $(eval $(call Download,start4cd_elf)) @@ -122,7 +122,7 @@ define Download/start4x_elf FILE:=$(RPI_FIRMWARE_FILE)-start4x.elf URL:=$(RPI_FIRMWARE_URL) URL_FILE:=start4x.elf - HASH:=48895858f7936570dfab44c67bdcb0357ac8fcd630162c36ac9ed8f2de85c038 + HASH:=c509e73a9cba7af3223dea885f58294bd04845e822aa3d6278500fa4dcdb112f endef $(eval $(call Download,start4x_elf)) From acf40c022e3d8949c7bb1f9c5212eb91512ae8a9 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Tue, 16 Jan 2024 15:53:16 +0100 Subject: [PATCH 136/222] ipq806x: DTS format fixup for Fortinet FAP-421E Small clanup and fixup for DTS format for Fortinet FAP-421E. Signed-off-by: Christian Marangi --- .../arm/boot/dts/qcom-ipq8064-fap-421e.dts | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-fap-421e.dts b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-fap-421e.dts index d80e7ecf62..1902a2f996 100644 --- a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-fap-421e.dts +++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-fap-421e.dts @@ -2,12 +2,13 @@ #include "qcom-ipq8064-smb208.dtsi" #include +#include / { model = "Fortinet FAP-421E"; compatible = "fortinet,fap-421e", "qcom,ipq8064"; - memory@0 { + memory@42000000 { device_type = "memory"; reg = <0x42000000 0xe000000>; }; @@ -52,42 +53,43 @@ pinctrl-0 = <&led_pins>; pinctrl-names = "default"; - eth1_amber { + eth1-amber { label = "amber:eth1"; gpios = <&qcom_pinmux 27 GPIO_ACTIVE_LOW>; }; - eth1_yellow { + eth1-yellow { label = "yellow:eth1"; gpios = <&qcom_pinmux 26 GPIO_ACTIVE_LOW>; }; - eth2_amber { + eth2-amber { label = "amber:eth2"; gpios = <&qcom_pinmux 29 GPIO_ACTIVE_LOW>; }; - eth2_yellow { + eth2-yellow { label = "yellow:eth2"; gpios = <&qcom_pinmux 28 GPIO_ACTIVE_LOW>; }; - power_amber { - label = "amber:power"; + power-amber { + function = LED_FUNCTION_POWER; + color = ; gpios = <&qcom_pinmux 53 GPIO_ACTIVE_LOW>; }; - led_power_yellow: power_yellow { + led_power_yellow: power-yellow { label = "yellow:power"; gpios = <&qcom_pinmux 58 GPIO_ACTIVE_LOW>; }; - 2g_yellow { + 2g-yellow { label = "yellow:2g"; gpios = <&qcom_pinmux 30 GPIO_ACTIVE_LOW>; }; - 5g_yellow { + 5g-yellow { label = "yellow:5g"; gpios = <&qcom_pinmux 64 GPIO_ACTIVE_LOW>; }; @@ -167,23 +169,23 @@ }; &gsbi7 { - status = "okay"; - qcom,mode = ; + + status = "okay"; }; &gsbi7_serial{ - status = "okay"; - pinctrl-0 = <&uart0_pins>; pinctrl-names = "default"; + + status = "okay"; }; &gsbi5 { - status = "okay"; - qcom,mode = ; + status = "okay"; + spi@1a280000 { status = "okay"; From ede34465de2176229590028fba622d54841ab40c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 16 Jan 2024 19:29:52 +0100 Subject: [PATCH 137/222] mediatek: fix ethernet rx hang issue on MT7981/MT7986 Add patches by Lorenzo/Daniel to use QDMA instead of ADMAv2 Signed-off-by: Felix Fietkau --- ...iatek-split-tx-and-rx-fields-in-mtk_.patch | 599 ++++++++++++++++++ ...iatek-use-QDMA-instead-of-ADMAv2-on-.patch | 123 ++++ ...iatek-split-tx-and-rx-fields-in-mtk_.patch | 599 ++++++++++++++++++ ...iatek-use-QDMA-instead-of-ADMAv2-on-.patch | 123 ++++ 4 files changed, 1444 insertions(+) create mode 100644 target/linux/mediatek/patches-5.15/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch create mode 100644 target/linux/mediatek/patches-5.15/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch create mode 100644 target/linux/mediatek/patches-6.1/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch create mode 100644 target/linux/mediatek/patches-6.1/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch diff --git a/target/linux/mediatek/patches-5.15/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch b/target/linux/mediatek/patches-5.15/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch new file mode 100644 index 0000000000..b0c20ab545 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch @@ -0,0 +1,599 @@ +From: Lorenzo Bianconi +Date: Thu, 2 Nov 2023 16:47:07 +0100 +Subject: [PATCH net-next 1/2] net: ethernet: mediatek: split tx and rx fields + in mtk_soc_data struct + +Split tx and rx fields in mtk_soc_data struct. This is a preliminary +patch to roll back to QDMA for MT7986 SoC in order to fix a hw hang +if the device receives a corrupted packet. + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 210 ++++++++++++-------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 29 +-- + 2 files changed, 139 insertions(+), 100 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1239,7 +1239,7 @@ static int mtk_init_fq_dma(struct mtk_et + eth->scratch_ring = eth->sram_base; + else + eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, +- cnt * soc->txrx.txd_size, ++ cnt * soc->tx.desc_size, + ð->phy_scratch_ring, + GFP_KERNEL); + if (unlikely(!eth->scratch_ring)) +@@ -1255,16 +1255,16 @@ static int mtk_init_fq_dma(struct mtk_et + if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) + return -ENOMEM; + +- phy_ring_tail = eth->phy_scratch_ring + soc->txrx.txd_size * (cnt - 1); ++ phy_ring_tail = eth->phy_scratch_ring + soc->tx.desc_size * (cnt - 1); + + for (i = 0; i < cnt; i++) { + struct mtk_tx_dma_v2 *txd; + +- txd = eth->scratch_ring + i * soc->txrx.txd_size; ++ txd = eth->scratch_ring + i * soc->tx.desc_size; + txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE; + if (i < cnt - 1) + txd->txd2 = eth->phy_scratch_ring + +- (i + 1) * soc->txrx.txd_size; ++ (i + 1) * soc->tx.desc_size; + + txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); + txd->txd4 = 0; +@@ -1511,7 +1511,7 @@ static int mtk_tx_map(struct sk_buff *sk + if (itxd == ring->last_free) + return -ENOMEM; + +- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + memset(itx_buf, 0, sizeof(*itx_buf)); + + txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size, +@@ -1552,7 +1552,7 @@ static int mtk_tx_map(struct sk_buff *sk + + memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); + txd_info.size = min_t(unsigned int, frag_size, +- soc->txrx.dma_max_len); ++ soc->tx.dma_max_len); + txd_info.qid = queue; + txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && + !(frag_size - txd_info.size); +@@ -1565,7 +1565,7 @@ static int mtk_tx_map(struct sk_buff *sk + mtk_tx_set_dma_desc(dev, txd, &txd_info); + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + if (new_desc) + memset(tx_buf, 0, sizeof(*tx_buf)); + tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; +@@ -1608,7 +1608,7 @@ static int mtk_tx_map(struct sk_buff *sk + } else { + int next_idx; + +- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->txrx.txd_size), ++ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_size), + ring->dma_size); + mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0); + } +@@ -1617,7 +1617,7 @@ static int mtk_tx_map(struct sk_buff *sk + + err_dma: + do { +- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + + /* unmap dma */ + mtk_tx_unmap(eth, tx_buf, false); +@@ -1642,7 +1642,7 @@ static int mtk_cal_txd_req(struct mtk_et + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + nfrags += DIV_ROUND_UP(skb_frag_size(frag), +- eth->soc->txrx.dma_max_len); ++ eth->soc->tx.dma_max_len); + } + } else { + nfrags += skb_shinfo(skb)->nr_frags; +@@ -1783,7 +1783,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri + + ring = ð->rx_ring[i]; + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + if (rxd->rxd2 & RX_DMA_DONE) { + ring->calc_idx_update = true; + return ring; +@@ -1951,7 +1951,7 @@ static int mtk_xdp_submit_frame(struct m + } + htxd = txd; + +- tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + htx_buf = tx_buf; + +@@ -1971,7 +1971,7 @@ static int mtk_xdp_submit_frame(struct m + goto unmap; + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + n_desc++; + } +@@ -2008,7 +2008,7 @@ static int mtk_xdp_submit_frame(struct m + } else { + int idx; + +- idx = txd_to_idx(ring, txd, soc->txrx.txd_size); ++ idx = txd_to_idx(ring, txd, soc->tx.desc_size); + mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size), + MT7628_TX_CTX_IDX0); + } +@@ -2020,7 +2020,7 @@ static int mtk_xdp_submit_frame(struct m + unmap: + while (htxd != txd) { + txd_pdma = qdma_to_pdma(ring, htxd); +- tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_size); + mtk_tx_unmap(eth, tx_buf, false); + + htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; +@@ -2148,7 +2148,7 @@ static int mtk_poll_rx(struct napi_struc + goto rx_done; + + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + data = ring->data[idx]; + + if (!mtk_rx_get_desc(eth, &trxd, rxd)) +@@ -2283,7 +2283,7 @@ static int mtk_poll_rx(struct napi_struc + rxdcsum = &trxd.rxd4; + } + +- if (*rxdcsum & eth->soc->txrx.rx_dma_l4_valid) ++ if (*rxdcsum & eth->soc->rx.dma_l4_valid) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb_checksum_none_assert(skb); +@@ -2405,7 +2405,7 @@ static int mtk_poll_tx_qdma(struct mtk_e + break; + + tx_buf = mtk_desc_to_tx_buf(ring, desc, +- eth->soc->txrx.txd_size); ++ eth->soc->tx.desc_size); + if (!tx_buf->data) + break; + +@@ -2453,7 +2453,7 @@ static int mtk_poll_tx_pdma(struct mtk_e + } + mtk_tx_unmap(eth, tx_buf, true); + +- desc = ring->dma + cpu * eth->soc->txrx.txd_size; ++ desc = ring->dma + cpu * eth->soc->tx.desc_size; + ring->last_free = desc; + atomic_inc(&ring->free_count); + +@@ -2542,7 +2542,7 @@ static int mtk_napi_rx(struct napi_struc + do { + int rx_done; + +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, + reg_map->pdma.irq_status); + rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth); + rx_done_total += rx_done; +@@ -2558,10 +2558,10 @@ static int mtk_napi_rx(struct napi_struc + return budget; + + } while (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask); ++ eth->soc->rx.irq_done_mask); + + if (napi_complete_done(napi, rx_done_total)) +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + + return rx_done_total; + } +@@ -2570,7 +2570,7 @@ static int mtk_tx_alloc(struct mtk_eth * + { + const struct mtk_soc_data *soc = eth->soc; + struct mtk_tx_ring *ring = ð->tx_ring; +- int i, sz = soc->txrx.txd_size; ++ int i, sz = soc->tx.desc_size; + struct mtk_tx_dma_v2 *txd; + int ring_size; + u32 ofs, val; +@@ -2693,14 +2693,14 @@ static void mtk_tx_clean(struct mtk_eth + } + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } + + if (ring->dma_pdma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma_pdma, ring->phys_pdma); + ring->dma_pdma = NULL; + } +@@ -2755,15 +2755,15 @@ static int mtk_rx_alloc(struct mtk_eth * + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || + rx_flag != MTK_RX_FLAGS_NORMAL) { + ring->dma = dma_alloc_coherent(eth->dma_dev, +- rx_dma_size * eth->soc->txrx.rxd_size, +- &ring->phys, GFP_KERNEL); ++ rx_dma_size * eth->soc->rx.desc_size, ++ &ring->phys, GFP_KERNEL); + } else { + struct mtk_tx_ring *tx_ring = ð->tx_ring; + + ring->dma = tx_ring->dma + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + ring->phys = tx_ring->phys + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + } + + if (!ring->dma) +@@ -2774,7 +2774,7 @@ static int mtk_rx_alloc(struct mtk_eth * + dma_addr_t dma_addr; + void *data; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (ring->page_pool) { + data = mtk_page_pool_get_buff(ring->page_pool, + &dma_addr, GFP_KERNEL); +@@ -2863,7 +2863,7 @@ static void mtk_rx_clean(struct mtk_eth + if (!ring->data[i]) + continue; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (!rxd->rxd1) + continue; + +@@ -2880,7 +2880,7 @@ static void mtk_rx_clean(struct mtk_eth + + if (!in_sram && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * eth->soc->txrx.rxd_size, ++ ring->dma_size * eth->soc->rx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } +@@ -3243,7 +3243,7 @@ static void mtk_dma_free(struct mtk_eth + netdev_reset_queue(eth->netdev[i]); + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { + dma_free_coherent(eth->dma_dev, +- MTK_QDMA_RING_SIZE * soc->txrx.txd_size, ++ MTK_QDMA_RING_SIZE * soc->tx.desc_size, + eth->scratch_ring, eth->phy_scratch_ring); + eth->scratch_ring = NULL; + eth->phy_scratch_ring = 0; +@@ -3293,7 +3293,7 @@ static irqreturn_t mtk_handle_irq_rx(int + + eth->rx_events++; + if (likely(napi_schedule_prep(ð->rx_napi))) { +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + __napi_schedule(ð->rx_napi); + } + +@@ -3319,9 +3319,9 @@ static irqreturn_t mtk_handle_irq(int ir + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + + if (mtk_r32(eth, reg_map->pdma.irq_mask) & +- eth->soc->txrx.rx_irq_done_mask) { ++ eth->soc->rx.irq_done_mask) { + if (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask) ++ eth->soc->rx.irq_done_mask) + mtk_handle_irq_rx(irq, _eth); + } + if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) { +@@ -3339,10 +3339,10 @@ static void mtk_poll_controller(struct n + struct mtk_eth *eth = mac->hw; + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + mtk_handle_irq_rx(eth->irq[2], dev); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + } + #endif + +@@ -3507,7 +3507,7 @@ static int mtk_open(struct net_device *d + napi_enable(ð->tx_napi); + napi_enable(ð->rx_napi); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, soc->rx.irq_done_mask); + refcount_set(ð->dma_refcnt, 1); + } + else +@@ -3590,7 +3590,7 @@ static int mtk_stop(struct net_device *d + mtk_gdm_config(eth, MTK_GDMA_DROP_ALL); + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + napi_disable(ð->tx_napi); + napi_disable(ð->rx_napi); + +@@ -4066,9 +4066,9 @@ static int mtk_hw_init(struct mtk_eth *e + + /* FE int grouping */ + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->pdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->pdma.int_grp + 4); + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->qdma.int_grp + 4); + mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); + + if (mtk_is_netsys_v3_or_greater(eth)) { +@@ -5165,11 +5165,15 @@ static const struct mtk_soc_data mt2701_ + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5185,11 +5189,15 @@ static const struct mtk_soc_data mt7621_ + .offload_version = 1, + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5207,11 +5215,15 @@ static const struct mtk_soc_data mt7622_ + .hash_offset = 2, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5228,11 +5240,15 @@ static const struct mtk_soc_data mt7623_ + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .disable_pll_modes = true, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5247,11 +5263,15 @@ static const struct mtk_soc_data mt7629_ + .required_pctl = false, + .has_accounting = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5269,11 +5289,15 @@ static const struct mtk_soc_data mt7981_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5291,11 +5315,15 @@ static const struct mtk_soc_data mt7986_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5313,11 +5341,15 @@ static const struct mtk_soc_data mt7988_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5330,11 +5362,15 @@ static const struct mtk_soc_data rt5350_ + .required_clks = MT7628_CLKS_BITMAP, + .required_pctl = false, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID_PDMA, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -326,8 +326,8 @@ + /* QDMA descriptor txd3 */ + #define TX_DMA_OWNER_CPU BIT(31) + #define TX_DMA_LS0 BIT(30) +-#define TX_DMA_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) ++#define TX_DMA_PLEN0(x) (((x) & eth->soc->tx.dma_max_len) << eth->soc->tx.dma_len_offset) ++#define TX_DMA_PLEN1(x) ((x) & eth->soc->tx.dma_max_len) + #define TX_DMA_SWC BIT(14) + #define TX_DMA_PQID GENMASK(3, 0) + #define TX_DMA_ADDR64_MASK GENMASK(3, 0) +@@ -347,8 +347,8 @@ + /* QDMA descriptor rxd2 */ + #define RX_DMA_DONE BIT(31) + #define RX_DMA_LSO BIT(30) +-#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len) ++#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->rx.dma_max_len) << eth->soc->rx.dma_len_offset) ++#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->rx.dma_len_offset) & eth->soc->rx.dma_max_len) + #define RX_DMA_VTAG BIT(15) + #define RX_DMA_ADDR64_MASK GENMASK(3, 0) + #if IS_ENABLED(CONFIG_64BIT) +@@ -1279,10 +1279,9 @@ struct mtk_reg_map { + * @foe_entry_size Foe table entry size. + * @has_accounting Bool indicating support for accounting of + * offloaded flows. +- * @txd_size Tx DMA descriptor size. +- * @rxd_size Rx DMA descriptor size. +- * @rx_irq_done_mask Rx irq done register mask. +- * @rx_dma_l4_valid Rx DMA valid register mask. ++ * @desc_size Tx/Rx DMA descriptor size. ++ * @irq_done_mask Rx irq done register mask. ++ * @dma_l4_valid Rx DMA valid register mask. + * @dma_max_len Max DMA tx/rx buffer length. + * @dma_len_offset Tx/Rx DMA length field offset. + */ +@@ -1300,13 +1299,17 @@ struct mtk_soc_data { + bool has_accounting; + bool disable_pll_modes; + struct { +- u32 txd_size; +- u32 rxd_size; +- u32 rx_irq_done_mask; +- u32 rx_dma_l4_valid; ++ u32 desc_size; + u32 dma_max_len; + u32 dma_len_offset; +- } txrx; ++ } tx; ++ struct { ++ u32 desc_size; ++ u32 irq_done_mask; ++ u32 dma_l4_valid; ++ u32 dma_max_len; ++ u32 dma_len_offset; ++ } rx; + }; + + #define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) diff --git a/target/linux/mediatek/patches-5.15/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch b/target/linux/mediatek/patches-5.15/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch new file mode 100644 index 0000000000..dd191f7afd --- /dev/null +++ b/target/linux/mediatek/patches-5.15/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch @@ -0,0 +1,123 @@ +From: Daniel Golle +Date: Tue, 10 Oct 2023 21:06:43 +0200 +Subject: [PATCH net-next 2/2] net: ethernet: mediatek: use QDMA instead of + ADMAv2 on MT7981 and MT7986 + +ADMA is plagued by RX hangs which can't easily detected and happen upon +receival of a corrupted package. +Use QDMA just like on netsys v1 which is also still present and usable, and +doesn't suffer from that problem. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 46 ++++++++++----------- + 1 file changed, 23 insertions(+), 23 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -108,16 +108,16 @@ static const struct mtk_reg_map mt7986_r + .tx_irq_mask = 0x461c, + .tx_irq_status = 0x4618, + .pdma = { +- .rx_ptr = 0x6100, +- .rx_cnt_cfg = 0x6104, +- .pcrx_ptr = 0x6108, +- .glo_cfg = 0x6204, +- .rst_idx = 0x6208, +- .delay_irq = 0x620c, +- .irq_status = 0x6220, +- .irq_mask = 0x6228, +- .adma_rx_dbg0 = 0x6238, +- .int_grp = 0x6250, ++ .rx_ptr = 0x4100, ++ .rx_cnt_cfg = 0x4104, ++ .pcrx_ptr = 0x4108, ++ .glo_cfg = 0x4204, ++ .rst_idx = 0x4208, ++ .delay_irq = 0x420c, ++ .irq_status = 0x4220, ++ .irq_mask = 0x4228, ++ .adma_rx_dbg0 = 0x4238, ++ .int_grp = 0x4250, + }, + .qdma = { + .qtx_cfg = 0x4400, +@@ -1207,7 +1207,7 @@ static bool mtk_rx_get_desc(struct mtk_e + rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); + rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); + rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); + rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); + } +@@ -2155,7 +2155,7 @@ static int mtk_poll_rx(struct napi_struc + break; + + /* find out which mac the packet come from. values start at 1 */ +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5); + + switch (val) { +@@ -2267,7 +2267,7 @@ static int mtk_poll_rx(struct napi_struc + skb->dev = netdev; + bytes += skb->len; + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); + hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; + if (hash != MTK_RXD5_FOE_ENTRY) +@@ -2809,7 +2809,7 @@ static int mtk_rx_alloc(struct mtk_eth * + + rxd->rxd3 = 0; + rxd->rxd4 = 0; +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = 0; + rxd->rxd6 = 0; + rxd->rxd7 = 0; +@@ -4012,7 +4012,7 @@ static int mtk_hw_init(struct mtk_eth *e + else + mtk_hw_reset(eth); + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + /* Set FE to PDMAv2 if necessary */ + val = mtk_r32(eth, MTK_FE_GLO_MISC); + mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); +@@ -5295,11 +5295,11 @@ static const struct mtk_soc_data mt7981_ + .dma_len_offset = 8, + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma_v2), +- .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, +- .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +- .dma_len_offset = 8, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, + }, + }; + +@@ -5321,11 +5321,11 @@ static const struct mtk_soc_data mt7986_ + .dma_len_offset = 8, + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma_v2), +- .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, +- .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +- .dma_len_offset = 8, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, + }, + }; + diff --git a/target/linux/mediatek/patches-6.1/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch b/target/linux/mediatek/patches-6.1/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch new file mode 100644 index 0000000000..4a624a3ef9 --- /dev/null +++ b/target/linux/mediatek/patches-6.1/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch @@ -0,0 +1,599 @@ +From: Lorenzo Bianconi +Date: Thu, 2 Nov 2023 16:47:07 +0100 +Subject: [PATCH net-next 1/2] net: ethernet: mediatek: split tx and rx fields + in mtk_soc_data struct + +Split tx and rx fields in mtk_soc_data struct. This is a preliminary +patch to roll back to QDMA for MT7986 SoC in order to fix a hw hang +if the device receives a corrupted packet. + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 210 ++++++++++++-------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 29 +-- + 2 files changed, 139 insertions(+), 100 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1238,7 +1238,7 @@ static int mtk_init_fq_dma(struct mtk_et + eth->scratch_ring = eth->sram_base; + else + eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, +- cnt * soc->txrx.txd_size, ++ cnt * soc->tx.desc_size, + ð->phy_scratch_ring, + GFP_KERNEL); + if (unlikely(!eth->scratch_ring)) +@@ -1254,16 +1254,16 @@ static int mtk_init_fq_dma(struct mtk_et + if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) + return -ENOMEM; + +- phy_ring_tail = eth->phy_scratch_ring + soc->txrx.txd_size * (cnt - 1); ++ phy_ring_tail = eth->phy_scratch_ring + soc->tx.desc_size * (cnt - 1); + + for (i = 0; i < cnt; i++) { + struct mtk_tx_dma_v2 *txd; + +- txd = eth->scratch_ring + i * soc->txrx.txd_size; ++ txd = eth->scratch_ring + i * soc->tx.desc_size; + txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE; + if (i < cnt - 1) + txd->txd2 = eth->phy_scratch_ring + +- (i + 1) * soc->txrx.txd_size; ++ (i + 1) * soc->tx.desc_size; + + txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); + txd->txd4 = 0; +@@ -1512,7 +1512,7 @@ static int mtk_tx_map(struct sk_buff *sk + if (itxd == ring->last_free) + return -ENOMEM; + +- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + memset(itx_buf, 0, sizeof(*itx_buf)); + + txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size, +@@ -1553,7 +1553,7 @@ static int mtk_tx_map(struct sk_buff *sk + + memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); + txd_info.size = min_t(unsigned int, frag_size, +- soc->txrx.dma_max_len); ++ soc->tx.dma_max_len); + txd_info.qid = queue; + txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && + !(frag_size - txd_info.size); +@@ -1566,7 +1566,7 @@ static int mtk_tx_map(struct sk_buff *sk + mtk_tx_set_dma_desc(dev, txd, &txd_info); + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + if (new_desc) + memset(tx_buf, 0, sizeof(*tx_buf)); + tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; +@@ -1609,7 +1609,7 @@ static int mtk_tx_map(struct sk_buff *sk + } else { + int next_idx; + +- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->txrx.txd_size), ++ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_size), + ring->dma_size); + mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0); + } +@@ -1618,7 +1618,7 @@ static int mtk_tx_map(struct sk_buff *sk + + err_dma: + do { +- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size); + + /* unmap dma */ + mtk_tx_unmap(eth, tx_buf, NULL, false); +@@ -1643,7 +1643,7 @@ static int mtk_cal_txd_req(struct mtk_et + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + nfrags += DIV_ROUND_UP(skb_frag_size(frag), +- eth->soc->txrx.dma_max_len); ++ eth->soc->tx.dma_max_len); + } + } else { + nfrags += skb_shinfo(skb)->nr_frags; +@@ -1784,7 +1784,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri + + ring = ð->rx_ring[i]; + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + if (rxd->rxd2 & RX_DMA_DONE) { + ring->calc_idx_update = true; + return ring; +@@ -1952,7 +1952,7 @@ static int mtk_xdp_submit_frame(struct m + } + htxd = txd; + +- tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + htx_buf = tx_buf; + +@@ -1971,7 +1971,7 @@ static int mtk_xdp_submit_frame(struct m + goto unmap; + + tx_buf = mtk_desc_to_tx_buf(ring, txd, +- soc->txrx.txd_size); ++ soc->tx.desc_size); + memset(tx_buf, 0, sizeof(*tx_buf)); + n_desc++; + } +@@ -2009,7 +2009,7 @@ static int mtk_xdp_submit_frame(struct m + } else { + int idx; + +- idx = txd_to_idx(ring, txd, soc->txrx.txd_size); ++ idx = txd_to_idx(ring, txd, soc->tx.desc_size); + mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size), + MT7628_TX_CTX_IDX0); + } +@@ -2020,7 +2020,7 @@ static int mtk_xdp_submit_frame(struct m + + unmap: + while (htxd != txd) { +- tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->txrx.txd_size); ++ tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_size); + mtk_tx_unmap(eth, tx_buf, NULL, false); + + htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; +@@ -2151,7 +2151,7 @@ static int mtk_poll_rx(struct napi_struc + goto rx_done; + + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + idx * eth->soc->rx.desc_size; + data = ring->data[idx]; + + if (!mtk_rx_get_desc(eth, &trxd, rxd)) +@@ -2286,7 +2286,7 @@ static int mtk_poll_rx(struct napi_struc + rxdcsum = &trxd.rxd4; + } + +- if (*rxdcsum & eth->soc->txrx.rx_dma_l4_valid) ++ if (*rxdcsum & eth->soc->rx.dma_l4_valid) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb_checksum_none_assert(skb); +@@ -2410,7 +2410,7 @@ static int mtk_poll_tx_qdma(struct mtk_e + break; + + tx_buf = mtk_desc_to_tx_buf(ring, desc, +- eth->soc->txrx.txd_size); ++ eth->soc->tx.desc_size); + if (!tx_buf->data) + break; + +@@ -2461,7 +2461,7 @@ static int mtk_poll_tx_pdma(struct mtk_e + } + mtk_tx_unmap(eth, tx_buf, &bq, true); + +- desc = ring->dma + cpu * eth->soc->txrx.txd_size; ++ desc = ring->dma + cpu * eth->soc->tx.desc_size; + ring->last_free = desc; + atomic_inc(&ring->free_count); + +@@ -2551,7 +2551,7 @@ static int mtk_napi_rx(struct napi_struc + do { + int rx_done; + +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, + reg_map->pdma.irq_status); + rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth); + rx_done_total += rx_done; +@@ -2567,10 +2567,10 @@ static int mtk_napi_rx(struct napi_struc + return budget; + + } while (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask); ++ eth->soc->rx.irq_done_mask); + + if (napi_complete_done(napi, rx_done_total)) +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + + return rx_done_total; + } +@@ -2579,7 +2579,7 @@ static int mtk_tx_alloc(struct mtk_eth * + { + const struct mtk_soc_data *soc = eth->soc; + struct mtk_tx_ring *ring = ð->tx_ring; +- int i, sz = soc->txrx.txd_size; ++ int i, sz = soc->tx.desc_size; + struct mtk_tx_dma_v2 *txd; + int ring_size; + u32 ofs, val; +@@ -2702,14 +2702,14 @@ static void mtk_tx_clean(struct mtk_eth + } + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } + + if (ring->dma_pdma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->txrx.txd_size, ++ ring->dma_size * soc->tx.desc_size, + ring->dma_pdma, ring->phys_pdma); + ring->dma_pdma = NULL; + } +@@ -2764,15 +2764,15 @@ static int mtk_rx_alloc(struct mtk_eth * + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || + rx_flag != MTK_RX_FLAGS_NORMAL) { + ring->dma = dma_alloc_coherent(eth->dma_dev, +- rx_dma_size * eth->soc->txrx.rxd_size, +- &ring->phys, GFP_KERNEL); ++ rx_dma_size * eth->soc->rx.desc_size, ++ &ring->phys, GFP_KERNEL); + } else { + struct mtk_tx_ring *tx_ring = ð->tx_ring; + + ring->dma = tx_ring->dma + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + ring->phys = tx_ring->phys + tx_ring_size * +- eth->soc->txrx.txd_size * (ring_no + 1); ++ eth->soc->tx.desc_size * (ring_no + 1); + } + + if (!ring->dma) +@@ -2783,7 +2783,7 @@ static int mtk_rx_alloc(struct mtk_eth * + dma_addr_t dma_addr; + void *data; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (ring->page_pool) { + data = mtk_page_pool_get_buff(ring->page_pool, + &dma_addr, GFP_KERNEL); +@@ -2874,7 +2874,7 @@ static void mtk_rx_clean(struct mtk_eth + if (!ring->data[i]) + continue; + +- rxd = ring->dma + i * eth->soc->txrx.rxd_size; ++ rxd = ring->dma + i * eth->soc->rx.desc_size; + if (!rxd->rxd1) + continue; + +@@ -2891,7 +2891,7 @@ static void mtk_rx_clean(struct mtk_eth + + if (!in_sram && ring->dma) { + dma_free_coherent(eth->dma_dev, +- ring->dma_size * eth->soc->txrx.rxd_size, ++ ring->dma_size * eth->soc->rx.desc_size, + ring->dma, ring->phys); + ring->dma = NULL; + } +@@ -3254,7 +3254,7 @@ static void mtk_dma_free(struct mtk_eth + netdev_reset_queue(eth->netdev[i]); + if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { + dma_free_coherent(eth->dma_dev, +- MTK_QDMA_RING_SIZE * soc->txrx.txd_size, ++ MTK_QDMA_RING_SIZE * soc->tx.desc_size, + eth->scratch_ring, eth->phy_scratch_ring); + eth->scratch_ring = NULL; + eth->phy_scratch_ring = 0; +@@ -3304,7 +3304,7 @@ static irqreturn_t mtk_handle_irq_rx(int + + eth->rx_events++; + if (likely(napi_schedule_prep(ð->rx_napi))) { +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + __napi_schedule(ð->rx_napi); + } + +@@ -3330,9 +3330,9 @@ static irqreturn_t mtk_handle_irq(int ir + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + + if (mtk_r32(eth, reg_map->pdma.irq_mask) & +- eth->soc->txrx.rx_irq_done_mask) { ++ eth->soc->rx.irq_done_mask) { + if (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->txrx.rx_irq_done_mask) ++ eth->soc->rx.irq_done_mask) + mtk_handle_irq_rx(irq, _eth); + } + if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) { +@@ -3350,10 +3350,10 @@ static void mtk_poll_controller(struct n + struct mtk_eth *eth = mac->hw; + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + mtk_handle_irq_rx(eth->irq[2], dev); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + } + #endif + +@@ -3516,7 +3516,7 @@ static int mtk_open(struct net_device *d + napi_enable(ð->tx_napi); + napi_enable(ð->rx_napi); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_enable(eth, soc->rx.irq_done_mask); + refcount_set(ð->dma_refcnt, 1); + } + else +@@ -3599,7 +3599,7 @@ static int mtk_stop(struct net_device *d + mtk_gdm_config(eth, MTK_GDMA_DROP_ALL); + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); ++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); + napi_disable(ð->tx_napi); + napi_disable(ð->rx_napi); + +@@ -4075,9 +4075,9 @@ static int mtk_hw_init(struct mtk_eth *e + + /* FE int grouping */ + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->pdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->pdma.int_grp + 4); + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp); +- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); ++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->qdma.int_grp + 4); + mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); + + if (mtk_is_netsys_v3_or_greater(eth)) { +@@ -5172,11 +5172,15 @@ static const struct mtk_soc_data mt2701_ + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5192,11 +5196,15 @@ static const struct mtk_soc_data mt7621_ + .offload_version = 1, + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5214,11 +5222,15 @@ static const struct mtk_soc_data mt7622_ + .hash_offset = 2, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5235,11 +5247,15 @@ static const struct mtk_soc_data mt7623_ + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .disable_pll_modes = true, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5254,11 +5270,15 @@ static const struct mtk_soc_data mt7629_ + .required_pctl = false, + .has_accounting = true, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +@@ -5276,11 +5296,15 @@ static const struct mtk_soc_data mt7981_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5298,11 +5322,15 @@ static const struct mtk_soc_data mt7986_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5320,11 +5348,15 @@ static const struct mtk_soc_data mt7988_ + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma_v2), +- .rxd_size = sizeof(struct mtk_rx_dma_v2), +- .rx_irq_done_mask = MTK_RX_DONE_INT_V2, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma_v2), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma_v2), ++ .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, + }, +@@ -5337,11 +5369,15 @@ static const struct mtk_soc_data rt5350_ + .required_clks = MT7628_CLKS_BITMAP, + .required_pctl = false, + .version = 1, +- .txrx = { +- .txd_size = sizeof(struct mtk_tx_dma), +- .rxd_size = sizeof(struct mtk_rx_dma), +- .rx_irq_done_mask = MTK_RX_DONE_INT, +- .rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA, ++ .tx = { ++ .desc_size = sizeof(struct mtk_tx_dma), ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, ++ }, ++ .rx = { ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, ++ .dma_l4_valid = RX_DMA_L4_VALID_PDMA, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + }, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -326,8 +326,8 @@ + /* QDMA descriptor txd3 */ + #define TX_DMA_OWNER_CPU BIT(31) + #define TX_DMA_LS0 BIT(30) +-#define TX_DMA_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len) ++#define TX_DMA_PLEN0(x) (((x) & eth->soc->tx.dma_max_len) << eth->soc->tx.dma_len_offset) ++#define TX_DMA_PLEN1(x) ((x) & eth->soc->tx.dma_max_len) + #define TX_DMA_SWC BIT(14) + #define TX_DMA_PQID GENMASK(3, 0) + #define TX_DMA_ADDR64_MASK GENMASK(3, 0) +@@ -347,8 +347,8 @@ + /* QDMA descriptor rxd2 */ + #define RX_DMA_DONE BIT(31) + #define RX_DMA_LSO BIT(30) +-#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset) +-#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len) ++#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->rx.dma_max_len) << eth->soc->rx.dma_len_offset) ++#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->rx.dma_len_offset) & eth->soc->rx.dma_max_len) + #define RX_DMA_VTAG BIT(15) + #define RX_DMA_ADDR64_MASK GENMASK(3, 0) + #if IS_ENABLED(CONFIG_64BIT) +@@ -1279,10 +1279,9 @@ struct mtk_reg_map { + * @foe_entry_size Foe table entry size. + * @has_accounting Bool indicating support for accounting of + * offloaded flows. +- * @txd_size Tx DMA descriptor size. +- * @rxd_size Rx DMA descriptor size. +- * @rx_irq_done_mask Rx irq done register mask. +- * @rx_dma_l4_valid Rx DMA valid register mask. ++ * @desc_size Tx/Rx DMA descriptor size. ++ * @irq_done_mask Rx irq done register mask. ++ * @dma_l4_valid Rx DMA valid register mask. + * @dma_max_len Max DMA tx/rx buffer length. + * @dma_len_offset Tx/Rx DMA length field offset. + */ +@@ -1300,13 +1299,17 @@ struct mtk_soc_data { + bool has_accounting; + bool disable_pll_modes; + struct { +- u32 txd_size; +- u32 rxd_size; +- u32 rx_irq_done_mask; +- u32 rx_dma_l4_valid; ++ u32 desc_size; + u32 dma_max_len; + u32 dma_len_offset; +- } txrx; ++ } tx; ++ struct { ++ u32 desc_size; ++ u32 irq_done_mask; ++ u32 dma_l4_valid; ++ u32 dma_max_len; ++ u32 dma_len_offset; ++ } rx; + }; + + #define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) diff --git a/target/linux/mediatek/patches-6.1/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch b/target/linux/mediatek/patches-6.1/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch new file mode 100644 index 0000000000..86cdcb5cb0 --- /dev/null +++ b/target/linux/mediatek/patches-6.1/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch @@ -0,0 +1,123 @@ +From: Daniel Golle +Date: Tue, 10 Oct 2023 21:06:43 +0200 +Subject: [PATCH net-next 2/2] net: ethernet: mediatek: use QDMA instead of + ADMAv2 on MT7981 and MT7986 + +ADMA is plagued by RX hangs which can't easily detected and happen upon +receival of a corrupted package. +Use QDMA just like on netsys v1 which is also still present and usable, and +doesn't suffer from that problem. + +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 46 ++++++++++----------- + 1 file changed, 23 insertions(+), 23 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -108,16 +108,16 @@ static const struct mtk_reg_map mt7986_r + .tx_irq_mask = 0x461c, + .tx_irq_status = 0x4618, + .pdma = { +- .rx_ptr = 0x6100, +- .rx_cnt_cfg = 0x6104, +- .pcrx_ptr = 0x6108, +- .glo_cfg = 0x6204, +- .rst_idx = 0x6208, +- .delay_irq = 0x620c, +- .irq_status = 0x6220, +- .irq_mask = 0x6228, +- .adma_rx_dbg0 = 0x6238, +- .int_grp = 0x6250, ++ .rx_ptr = 0x4100, ++ .rx_cnt_cfg = 0x4104, ++ .pcrx_ptr = 0x4108, ++ .glo_cfg = 0x4204, ++ .rst_idx = 0x4208, ++ .delay_irq = 0x420c, ++ .irq_status = 0x4220, ++ .irq_mask = 0x4228, ++ .adma_rx_dbg0 = 0x4238, ++ .int_grp = 0x4250, + }, + .qdma = { + .qtx_cfg = 0x4400, +@@ -1206,7 +1206,7 @@ static bool mtk_rx_get_desc(struct mtk_e + rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); + rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); + rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); + rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); + } +@@ -2158,7 +2158,7 @@ static int mtk_poll_rx(struct napi_struc + break; + + /* find out which mac the packet come from. values start at 1 */ +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5); + + switch (val) { +@@ -2270,7 +2270,7 @@ static int mtk_poll_rx(struct napi_struc + skb->dev = netdev; + bytes += skb->len; + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); + hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; + if (hash != MTK_RXD5_FOE_ENTRY) +@@ -2820,7 +2820,7 @@ static int mtk_rx_alloc(struct mtk_eth * + + rxd->rxd3 = 0; + rxd->rxd4 = 0; +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = 0; + rxd->rxd6 = 0; + rxd->rxd7 = 0; +@@ -4021,7 +4021,7 @@ static int mtk_hw_init(struct mtk_eth *e + else + mtk_hw_reset(eth); + +- if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { + /* Set FE to PDMAv2 if necessary */ + val = mtk_r32(eth, MTK_FE_GLO_MISC); + mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); +@@ -5302,11 +5302,11 @@ static const struct mtk_soc_data mt7981_ + .dma_len_offset = 8, + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma_v2), +- .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, +- .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +- .dma_len_offset = 8, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, + }, + }; + +@@ -5328,11 +5328,11 @@ static const struct mtk_soc_data mt7986_ + .dma_len_offset = 8, + }, + .rx = { +- .desc_size = sizeof(struct mtk_rx_dma_v2), +- .irq_done_mask = MTK_RX_DONE_INT_V2, ++ .desc_size = sizeof(struct mtk_rx_dma), ++ .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, +- .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +- .dma_len_offset = 8, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN, ++ .dma_len_offset = 16, + }, + }; + From a8cf9f860f1a98f7cfe8547710df77f73ec5a3d4 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 16 Jan 2024 22:22:17 +0000 Subject: [PATCH 138/222] uqmi: update to git HEAD c3488b8 uqmi: cancel all requests on SYNC indication reception dfa612e uqmi: improve response detection Signed-off-by: Daniel Golle --- package/network/utils/uqmi/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/utils/uqmi/Makefile b/package/network/utils/uqmi/Makefile index 26b588c7ef..6753e47cdb 100644 --- a/package/network/utils/uqmi/Makefile +++ b/package/network/utils/uqmi/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/uqmi.git -PKG_SOURCE_DATE:=2023-10-29 -PKG_SOURCE_VERSION:=eea292401c388a4eb59c0caf5d00aa046c6059f4 -PKG_MIRROR_HASH:=744f7e2010bd16ca08b03551287a0e1d119e1e6e099f8abf935328d3d1344893 +PKG_SOURCE_DATE:=2024-01-16 +PKG_SOURCE_VERSION:=c3488b831ce6285c8107704156b9b8ed7d59deb3 +PKG_MIRROR_HASH:=3ca47f2ae22bc1adcb05560e6dbea824063fa914670c13f107e7e78f33399779 PKG_MAINTAINER:=Matti Laakso PKG_LICENSE:=GPL-2.0 From 0e6179e50e4d644950e2fbec9b7ab5ab942d019e Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Tue, 16 Jan 2024 19:56:05 +0800 Subject: [PATCH 139/222] ramips: mt7621: convert MT7915 EEPROM to NVMEM format Some MT7915 calibration data consists of two parts. The first part "eeprom" size is 0xe00. The second part "precal" size is 0x19c10. Though some devices may not have precal data, it's better to assume that precal data exists as no users/developers confirm it. On the other hand, some devices definitely do not contain precal data because the EEPROM partition size is smaller than the precal NVMEM cell size. Signed-off-by: Shiji Yang --- .../linux/ramips/dts/mt7621_asus_rt-ax53u.dts | 11 ++++++++++- .../linux/ramips/dts/mt7621_asus_rt-ax54.dts | 11 ++++++++++- .../ramips/dts/mt7621_comfast_cf-e390ax.dts | 7 ++++++- target/linux/ramips/dts/mt7621_cudy_m1800.dts | 13 ++++++++++++- target/linux/ramips/dts/mt7621_cudy_x6.dtsi | 13 ++++++++++++- .../ramips/dts/mt7621_dlink_covr-x1860-a1.dts | 17 ++++++++++++++++- .../ramips/dts/mt7621_dlink_dap-x1860-a1.dts | 11 ++++++++++- .../dts/mt7621_iodata_wn-deax1800gr.dts | 8 ++++++-- .../ramips/dts/mt7621_iptime_ax2004m.dts | 11 ++++++++++- .../ramips/dts/mt7621_mercusys_mr70x-v1.dts | 15 ++++++++++++--- .../linux/ramips/dts/mt7621_netgear_eax12.dts | 17 ++++++++++++++++- .../dts/mt7621_tplink_archer-ax23-v1.dts | 15 ++++++++++++--- .../ramips/dts/mt7621_tplink_eap613-v1.dts | 13 ++++++++++++- .../dts/mt7621_tplink_eap615-wall-v1.dts | 13 ++++++++++++- .../ramips/dts/mt7621_tplink_ex220-v1.dts | 19 ++++++++++++++++--- .../ramips/dts/mt7621_ubnt_unifi-6-lite.dts | 14 ++++++++++---- .../ramips/dts/mt7621_wavlink_wl-wn573hx1.dts | 11 ++++++++++- .../linux/ramips/dts/mt7621_yuncore_ax820.dts | 11 ++++++++++- .../ramips/dts/mt7621_yuncore_fap640.dts | 11 ++++++++++- .../ramips/dts/mt7621_yuncore_fap690.dts | 11 ++++++++++- .../linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi | 19 ++++++++++++++++--- .../linux/ramips/dts/mt7621_zyxel_wsm20.dts | 11 ++++++++++- 22 files changed, 248 insertions(+), 34 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_asus_rt-ax53u.dts b/target/linux/ramips/dts/mt7621_asus_rt-ax53u.dts index d18a503b85..c7d0e1e748 100644 --- a/target/linux/ramips/dts/mt7621_asus_rt-ax53u.dts +++ b/target/linux/ramips/dts/mt7621_asus_rt-ax53u.dts @@ -104,9 +104,17 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + macaddr_factory_4: macaddr@4 { reg = <0x4 0x6>; }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; }; }; @@ -157,7 +165,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_asus_rt-ax54.dts b/target/linux/ramips/dts/mt7621_asus_rt-ax54.dts index 8466cda587..94825f9de3 100644 --- a/target/linux/ramips/dts/mt7621_asus_rt-ax54.dts +++ b/target/linux/ramips/dts/mt7621_asus_rt-ax54.dts @@ -96,9 +96,17 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + macaddr_factory_4: macaddr@4 { reg = <0x4 0x6>; }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; }; }; @@ -130,7 +138,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_comfast_cf-e390ax.dts b/target/linux/ramips/dts/mt7621_comfast_cf-e390ax.dts index ac0c19c022..5730ca04d3 100644 --- a/target/linux/ramips/dts/mt7621_comfast_cf-e390ax.dts +++ b/target/linux/ramips/dts/mt7621_comfast_cf-e390ax.dts @@ -59,7 +59,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; }; @@ -96,6 +97,10 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + macaddr_factory_e000: macaddr@e000 { compatible = "mac-base"; reg = <0xe000 0x6>; diff --git a/target/linux/ramips/dts/mt7621_cudy_m1800.dts b/target/linux/ramips/dts/mt7621_cudy_m1800.dts index 29d6f9e41a..2c9ab5cce6 100644 --- a/target/linux/ramips/dts/mt7621_cudy_m1800.dts +++ b/target/linux/ramips/dts/mt7621_cudy_m1800.dts @@ -80,7 +80,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; mediatek,disable-radar-background; }; }; @@ -116,6 +117,16 @@ label = "factory"; reg = <0x40000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; partition@50000 { diff --git a/target/linux/ramips/dts/mt7621_cudy_x6.dtsi b/target/linux/ramips/dts/mt7621_cudy_x6.dtsi index 4c34f58a4b..8b3baa9f84 100644 --- a/target/linux/ramips/dts/mt7621_cudy_x6.dtsi +++ b/target/linux/ramips/dts/mt7621_cudy_x6.dtsi @@ -79,6 +79,16 @@ label = "factory"; reg = <0x40000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; /* additional partitions in DTS */ @@ -94,7 +104,8 @@ wifi:wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_dlink_covr-x1860-a1.dts b/target/linux/ramips/dts/mt7621_dlink_covr-x1860-a1.dts index c06c5e36ba..7a5fbeeddb 100644 --- a/target/linux/ramips/dts/mt7621_dlink_covr-x1860-a1.dts +++ b/target/linux/ramips/dts/mt7621_dlink_covr-x1860-a1.dts @@ -98,6 +98,20 @@ label = "factory"; reg = <0x100000 0x80000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + }; }; partition@180000 { @@ -155,7 +169,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_dlink_dap-x1860-a1.dts b/target/linux/ramips/dts/mt7621_dlink_dap-x1860-a1.dts index 73f6247b47..82b7c8070e 100644 --- a/target/linux/ramips/dts/mt7621_dlink_dap-x1860-a1.dts +++ b/target/linux/ramips/dts/mt7621_dlink_dap-x1860-a1.dts @@ -134,9 +134,17 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + macaddr_factory_4: macaddr@4 { reg = <0x4 0x6>; }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; }; }; @@ -177,7 +185,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-deax1800gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-deax1800gr.dts index b9b901a6ce..c21f456a74 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-deax1800gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-deax1800gr.dts @@ -137,6 +137,10 @@ reg = <0x4 0x6>; #nvmem-cell-cells = <1>; }; + + precal: precal@e10 { + reg = <0xe10 0x19c10>; + }; }; }; @@ -221,8 +225,8 @@ compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - nvmem-cells = <&eeprom>; - nvmem-cell-names = "eeprom"; + nvmem-cells = <&eeprom>, <&precal>; + nvmem-cell-names = "eeprom", "precal"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts b/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts index ec02679c23..a0df60234e 100644 --- a/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts +++ b/target/linux/ramips/dts/mt7621_iptime_ax2004m.dts @@ -82,11 +82,19 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + macaddr_factory_4: macaddr@4 { compatible = "mac-base"; reg = <0x4 0x6>; #nvmem-cell-cells = <1>; }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; }; }; @@ -170,6 +178,7 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; }; }; diff --git a/target/linux/ramips/dts/mt7621_mercusys_mr70x-v1.dts b/target/linux/ramips/dts/mt7621_mercusys_mr70x-v1.dts index d663dc63b2..9004e5f0fd 100644 --- a/target/linux/ramips/dts/mt7621_mercusys_mr70x-v1.dts +++ b/target/linux/ramips/dts/mt7621_mercusys_mr70x-v1.dts @@ -99,6 +99,16 @@ label = "radio"; reg = <0xff0000 0x010000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; }; }; @@ -112,9 +122,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&radio 0x0>; - nvmem-cells = <&macaddr_config_8 0>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&eeprom_radio_0>, <&macaddr_config_8 0>; + nvmem-cell-names = "eeprom", "mac-address"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_eax12.dts b/target/linux/ramips/dts/mt7621_netgear_eax12.dts index d5ad404be0..d0e0eb247a 100644 --- a/target/linux/ramips/dts/mt7621_netgear_eax12.dts +++ b/target/linux/ramips/dts/mt7621_netgear_eax12.dts @@ -110,6 +110,20 @@ label = "Factory"; reg = <0x100000 0x80000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + }; }; partition@180000 { @@ -171,7 +185,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; }; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts b/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts index 1bc3f7e4f5..4de71d9e42 100644 --- a/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_archer-ax23-v1.dts @@ -132,6 +132,16 @@ label = "radio"; reg = <0xff0000 0x010000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; }; }; @@ -145,9 +155,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&radio 0x0>; - nvmem-cells = <&macaddr_config_8 0>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&eeprom_radio_0>, <&macaddr_config_8 0>; + nvmem-cell-names = "eeprom", "mac-address"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_eap613-v1.dts b/target/linux/ramips/dts/mt7621_tplink_eap613-v1.dts index cf08452c50..6c66401580 100644 --- a/target/linux/ramips/dts/mt7621_tplink_eap613-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_eap613-v1.dts @@ -113,6 +113,16 @@ label = "radio"; reg = <0xff0000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; }; }; @@ -133,7 +143,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&radio 0x0>; + nvmem-cells = <&eeprom_radio_0>; + nvmem-cell-names = "eeprom"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_eap615-wall-v1.dts b/target/linux/ramips/dts/mt7621_tplink_eap615-wall-v1.dts index f9bbd9b392..b856488539 100644 --- a/target/linux/ramips/dts/mt7621_tplink_eap615-wall-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_eap615-wall-v1.dts @@ -133,6 +133,16 @@ label = "radio"; reg = <0xff0000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + }; }; }; }; @@ -153,7 +163,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&radio 0x0>; + nvmem-cells = <&eeprom_radio_0>; + nvmem-cell-names = "eeprom"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_ex220-v1.dts b/target/linux/ramips/dts/mt7621_tplink_ex220-v1.dts index c809cb0c0b..ffefd07d85 100644 --- a/target/linux/ramips/dts/mt7621_tplink_ex220-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_ex220-v1.dts @@ -161,6 +161,20 @@ label = "radio"; reg = <0x90000 0x20000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_radio_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + }; }; partition@b0000 { @@ -186,9 +200,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&radio 0x0>; - nvmem-cells = <&macaddr_rom_file_f100 0>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&eeprom_radio_0>, <&precal_radio_e10>, <&macaddr_rom_file_f100 0>; + nvmem-cell-names = "eeprom", "precal", "mac-address"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_ubnt_unifi-6-lite.dts b/target/linux/ramips/dts/mt7621_ubnt_unifi-6-lite.dts index cd19893e14..d439e124e3 100644 --- a/target/linux/ramips/dts/mt7621_ubnt_unifi-6-lite.dts +++ b/target/linux/ramips/dts/mt7621_ubnt_unifi-6-lite.dts @@ -49,6 +49,14 @@ eeprom_factory_0: eeprom@0 { reg = <0x0 0x400>; }; + + eeprom_factory_20000: eeprom@20000 { + reg = <0x20000 0xe00>; + }; + + precal_factory_20e10: precal@20e10 { + reg = <0x20e10 0x19c10>; + }; }; }; @@ -112,8 +120,6 @@ &wlan_5g { compatible = "mediatek,mt76"; - mediatek,mtd-eeprom = <&factory 0x20000>; - /* This is a workaround. * * Ubiquiti uses a +2 offset in the first octet relative @@ -126,8 +132,8 @@ * mac80211 increases the first octet by two for each VAP, leading * to conflicting MAC addresses for subsequent interfaces. */ - nvmem-cells = <&macaddr_eeprom_6 1>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_eeprom_6 1>, <&eeprom_factory_20000>, <&precal_factory_20e10>; + nvmem-cell-names = "mac-address", "eeprom", "precal"; ieee80211-freq-limit = <5000000 6000000>; diff --git a/target/linux/ramips/dts/mt7621_wavlink_wl-wn573hx1.dts b/target/linux/ramips/dts/mt7621_wavlink_wl-wn573hx1.dts index dd2150c1a6..ec94e30a8c 100644 --- a/target/linux/ramips/dts/mt7621_wavlink_wl-wn573hx1.dts +++ b/target/linux/ramips/dts/mt7621_wavlink_wl-wn573hx1.dts @@ -61,7 +61,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; }; }; @@ -95,6 +96,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + macaddr_factory_3fff4: macaddr@3fff4 { reg = <0x3fff4 0x6>; }; diff --git a/target/linux/ramips/dts/mt7621_yuncore_ax820.dts b/target/linux/ramips/dts/mt7621_yuncore_ax820.dts index bbd546f300..bca9498be8 100644 --- a/target/linux/ramips/dts/mt7621_yuncore_ax820.dts +++ b/target/linux/ramips/dts/mt7621_yuncore_ax820.dts @@ -121,6 +121,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + macaddr_factory_e000: macaddr@e000 { compatible = "mac-base"; reg = <0xe000 0x6>; @@ -146,7 +154,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_yuncore_fap640.dts b/target/linux/ramips/dts/mt7621_yuncore_fap640.dts index ddbeceaff8..c61189c4bc 100644 --- a/target/linux/ramips/dts/mt7621_yuncore_fap640.dts +++ b/target/linux/ramips/dts/mt7621_yuncore_fap640.dts @@ -129,6 +129,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + macaddr_factory_4: macaddr@4 { reg = <0x4 0x6>; }; @@ -156,7 +164,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_yuncore_fap690.dts b/target/linux/ramips/dts/mt7621_yuncore_fap690.dts index ccfb0847aa..caebe0b589 100644 --- a/target/linux/ramips/dts/mt7621_yuncore_fap690.dts +++ b/target/linux/ramips/dts/mt7621_yuncore_fap690.dts @@ -99,9 +99,17 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + macaddr_factory_4: macaddr@4 { reg = <0x4 0x6>; }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; }; }; @@ -122,7 +130,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; diff --git a/target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi b/target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi index 85dbe2d857..6272b178ec 100644 --- a/target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi +++ b/target/linux/ramips/dts/mt7621_zyxel_nwa-ax.dtsi @@ -40,6 +40,20 @@ label = "factory"; reg = <0x100000 0x80000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + }; }; partition@180000 { @@ -118,9 +132,8 @@ wlan_5g: wifi@0,0 { reg = <0x0 0 0 0 0>; compatible = "mediatek,mt76"; - - mediatek,mtd-eeprom = <&factory 0x0>; - + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; /* MAC-Address set in userspace */ }; }; diff --git a/target/linux/ramips/dts/mt7621_zyxel_wsm20.dts b/target/linux/ramips/dts/mt7621_zyxel_wsm20.dts index 0cd1f3274c..a283b55c11 100644 --- a/target/linux/ramips/dts/mt7621_zyxel_wsm20.dts +++ b/target/linux/ramips/dts/mt7621_zyxel_wsm20.dts @@ -112,6 +112,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0xe00>; + }; + + precal_factory_e10: precal@e10 { + reg = <0xe10 0x19c10>; + }; + macaddr_factory_1fdfa: macaddr@1fdfa { reg = <0x1fdfa 0x6>; }; @@ -199,7 +207,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>, <&precal_factory_e10>; + nvmem-cell-names = "eeprom", "precal"; mediatek,disable-radar-background; }; }; From afc390a69f33e9d1273e12e3c1bad4500cc2ccb3 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Tue, 16 Jan 2024 20:21:35 +0800 Subject: [PATCH 140/222] ramips: mt7621: convert Xiaomi devices EEPROM to NVMEM format -+---------------------------+- | Model | NIC | -+---------------------------+- | AC2100 | MT7603 + MT7615 | -+---------------------------+- | MI4A V2 | MT7603 + MT7613 | -+---------------------------+- | Others | MT7603 + MT7612 | -+---------------------------+- Signed-off-by: Shiji Yang --- .../linux/ramips/dts/mt7621_xiaomi_mi-router-3g.dts | 6 ++++-- target/linux/ramips/dts/mt7621_xiaomi_mi-router-4.dts | 6 ++++-- .../ramips/dts/mt7621_xiaomi_mi-router-4a-3g-v2.dtsi | 6 ++++-- .../ramips/dts/mt7621_xiaomi_mi-router-4a-common.dtsi | 8 ++++++++ .../dts/mt7621_xiaomi_mi-router-4a-gigabit-v2.dts | 11 +++++++++-- target/linux/ramips/dts/mt7621_xiaomi_nand_128m.dtsi | 8 ++++++++ .../linux/ramips/dts/mt7621_xiaomi_router-ac2100.dtsi | 11 +++++++++-- 7 files changed, 46 insertions(+), 10 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-3g.dts b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-3g.dts index 763973a193..bd8400c898 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-3g.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-3g.dts @@ -86,7 +86,8 @@ wifi@0,0 { compatible = "pci14c3,7603"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; }; @@ -95,7 +96,8 @@ wifi@0,0 { compatible = "pci14c3,7662"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4.dts b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4.dts index 8340ca5d28..a9b62b1b28 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4.dts @@ -50,7 +50,8 @@ wifi@0,0 { compatible = "pci14c3,7603"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; }; @@ -59,7 +60,8 @@ wifi@0,0 { compatible = "pci14c3,7662"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-3g-v2.dtsi b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-3g-v2.dtsi index d05872337b..8f88eb175d 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-3g-v2.dtsi +++ b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-3g-v2.dtsi @@ -23,12 +23,14 @@ }; &wifi0 { - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; &wifi1 { - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-common.dtsi b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-common.dtsi index 7ce9aea335..7b8c4e8dfd 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-common.dtsi +++ b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-common.dtsi @@ -70,6 +70,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x200>; + }; + macaddr_factory_e000: macaddr@e000 { reg = <0xe000 0x6>; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-gigabit-v2.dts b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-gigabit-v2.dts index 67ff6ea11e..719d430fd8 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-gigabit-v2.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mi-router-4a-gigabit-v2.dts @@ -35,6 +35,11 @@ }; }; +/* override EEPROM size to 0x4da8 for MT7613 */ +&eeprom_factory_8000 { + reg = <0x8000 0x4da8>; +}; + &partitions { partition@180000 { // size changed against to the common dtsi @@ -49,12 +54,14 @@ }; &wifi0 { - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; &wifi1 { - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_nand_128m.dtsi b/target/linux/ramips/dts/mt7621_xiaomi_nand_128m.dtsi index 1dc91d8b47..3a877e9bec 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_nand_128m.dtsi +++ b/target/linux/ramips/dts/mt7621_xiaomi_nand_128m.dtsi @@ -56,6 +56,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x200>; + }; + macaddr_factory_e000: macaddr@e000 { reg = <0xe000 0x6>; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_router-ac2100.dtsi b/target/linux/ramips/dts/mt7621_xiaomi_router-ac2100.dtsi index c7d6c574aa..468f9456bf 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_router-ac2100.dtsi +++ b/target/linux/ramips/dts/mt7621_xiaomi_router-ac2100.dtsi @@ -2,6 +2,11 @@ #include "mt7621_xiaomi_nand_128m.dtsi" +/* override EEPROM size to 0x4da8 for MT7615 */ +&eeprom_factory_8000 { + reg = <0x8000 0x4da8>; +}; + &pcie { status = "okay"; }; @@ -10,7 +15,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; }; @@ -19,7 +25,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; }; From cd9088c6f943b685c5060e2acf772ed479710f20 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Tue, 16 Jan 2024 20:42:59 +0800 Subject: [PATCH 141/222] ramips: mt7621: convert I-O DATA devices EEPROM to NVMEM format -+-------------------------------------------+- | Model | NIC | -+-------------------------------------------+- | WN-DX1167R/WN-AX1167GR2 | MT7615D | -+-------------------------------------------+- | WN-AX2033GR/WN-DX2033GR | MT7603 + MT7615 | -+-------------------------------------------+- Signed-off-by: Shiji Yang --- target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr2.dts | 8 +++++++- target/linux/ramips/dts/mt7621_iodata_wn-ax2033gr.dts | 8 ++++---- target/linux/ramips/dts/mt7621_iodata_wn-dx1167r.dts | 8 +++++++- target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts | 6 ++++-- target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi | 8 ++++++++ 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr2.dts b/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr2.dts index 8e778ce4fe..8936258409 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr2.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr2.dts @@ -7,6 +7,11 @@ model = "I-O DATA WN-AX1167GR2"; }; +/* override EEPROM size to 0x4da8 for MT7615 */ +&eeprom_factory_0 { + reg = <0x0 0x4da8>; +}; + &partitions { partition@6b00000 { label = "Backup"; @@ -19,6 +24,7 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-ax2033gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-ax2033gr.dts index eb6908629a..017d977d44 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-ax2033gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-ax2033gr.dts @@ -19,8 +19,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2483000>; }; }; @@ -29,8 +29,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 5710000>; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-dx1167r.dts b/target/linux/ramips/dts/mt7621_iodata_wn-dx1167r.dts index 4492f43f9f..c8aaa80b54 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-dx1167r.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-dx1167r.dts @@ -7,6 +7,11 @@ model = "I-O DATA WN-DX1167R"; }; +/* override EEPROM size to 0x4da8 for MT7615 */ +&eeprom_factory_0 { + reg = <0x0 0x4da8>; +}; + &partitions { partition@6b00000 { label = "idmkey"; @@ -25,6 +30,7 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts index ce02def7ff..728deeba98 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-dx2033gr.dts @@ -25,7 +25,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2483000>; }; }; @@ -34,7 +35,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 5710000>; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi b/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi index f25d2db9b3..5ed92cf0e7 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi +++ b/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi @@ -86,6 +86,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + macaddr_factory_e000: macaddr@e000 { reg = <0xe000 0x6>; }; From 3158a09bef69d6f63bdcbcb69f9a3fcaad1300cd Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Tue, 16 Jan 2024 20:57:35 +0800 Subject: [PATCH 142/222] ramips: mt7621: convert Ubiquiti devices EEPROM to NVMEM format -+-------------------------+- | Model | NIC | -+-------------------------+- | All | MT7603 + MT7615 | -+-------------------------+- Signed-off-by: Shiji Yang --- .../ramips/dts/mt7621_ubnt_unifi-flexhd.dts | 24 ++++++++++++++----- .../ramips/dts/mt7621_ubnt_unifi-nanohd.dts | 20 ++++++++++++++-- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_ubnt_unifi-flexhd.dts b/target/linux/ramips/dts/mt7621_ubnt_unifi-flexhd.dts index 36df3ef883..d458b91ca6 100644 --- a/target/linux/ramips/dts/mt7621_ubnt_unifi-flexhd.dts +++ b/target/linux/ramips/dts/mt7621_ubnt_unifi-flexhd.dts @@ -61,6 +61,20 @@ label = "factory"; reg = <0x70000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + }; }; eeprom: partition@80000 { @@ -128,22 +142,20 @@ &pcie0 { wifi@0,0 { reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; // On newer devices there is a MediaTek MAC in the above // device EEPROM, so override it with a calculated one. - nvmem-cells = <&macaddr_eeprom_0 1>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&eeprom_factory_0>, <&macaddr_eeprom_0 1>; + nvmem-cell-names = "eeprom", "mac-address"; }; }; &pcie1 { wifi@0,0 { reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; // On newer devices there is a MediaTek MAC in the above // device EEPROM, so override it with a calculated one. - nvmem-cells = <&macaddr_eeprom_0 2>; - nvmem-cell-names = "mac-address"; + nvmem-cells = <&eeprom_factory_8000>, <&macaddr_eeprom_0 2>; + nvmem-cell-names = "eeprom", "mac-address"; }; }; diff --git a/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts b/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts index b4000464f7..d81a23852d 100644 --- a/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts +++ b/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts @@ -36,6 +36,20 @@ label = "factory"; reg = <0x70000 0x10000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + }; }; eeprom: partition@80000 { @@ -86,9 +100,11 @@ }; &wlan_2g { - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; &wlan_5g { - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; }; From 52c3f951f0472127ca4a2f0df4b83e82ce21c9f5 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Tue, 16 Jan 2024 21:03:42 +0800 Subject: [PATCH 143/222] ramips: mt7621: convert Wavlink devices EEPROM to NVMEM format -+------------------------------+- | Model | NIC | -+------------------------------+- | WL-WN531A6 | MT7603 + MT7615 | -+------------------------------+- | WL-WN533A8 | MT7615 *2 | -+------------------------------+- Signed-off-by: Shiji Yang --- .../linux/ramips/dts/mt7621_wavlink_wl-wn533a8.dts | 5 +++++ .../ramips/dts/mt7621_wavlink_wl-wn53xax.dtsi | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_wavlink_wl-wn533a8.dts b/target/linux/ramips/dts/mt7621_wavlink_wl-wn533a8.dts index 9a601d6d18..b5493a137e 100644 --- a/target/linux/ramips/dts/mt7621_wavlink_wl-wn533a8.dts +++ b/target/linux/ramips/dts/mt7621_wavlink_wl-wn533a8.dts @@ -7,6 +7,11 @@ model = "Wavlink WL-WN533A8"; }; +/* override EEPROM size to 0x4da8 for MT7615 */ +&eeprom_factory_0 { + reg = <0x0 0x4da8>; +}; + &wifi0{ ieee80211-freq-limit = <2400000 5490000>; }; diff --git a/target/linux/ramips/dts/mt7621_wavlink_wl-wn53xax.dtsi b/target/linux/ramips/dts/mt7621_wavlink_wl-wn53xax.dtsi index e0db05724e..7df61c4eb3 100644 --- a/target/linux/ramips/dts/mt7621_wavlink_wl-wn53xax.dtsi +++ b/target/linux/ramips/dts/mt7621_wavlink_wl-wn53xax.dtsi @@ -101,6 +101,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + macaddr_factory_e000: macaddr@e000 { reg = <0xe000 0x6>; }; @@ -134,7 +142,8 @@ wifi0: mt76@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; }; @@ -142,7 +151,8 @@ wifi1: mt76@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; }; }; From a6724ba702decab6dfcc9477d632e53fa826f678 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Tue, 16 Jan 2024 21:24:41 +0800 Subject: [PATCH 144/222] ramips: mt7621: convert NETGEAR devices EEPROM to NVMEM format -+------------------------------+- | Model | NIC | -+------------------------------+- | chj series | MT7603 + MT7615 | -+------------------------------+- | bzv series | MT7615 *2 | -+------------------------------+- Signed-off-by: Shiji Yang --- .../ramips/dts/mt7621_netgear_sercomm_bzv.dtsi | 14 ++++++++++++-- .../ramips/dts/mt7621_netgear_sercomm_chj.dtsi | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi index f5cffb4a2a..1ae7fd0f57 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi @@ -147,7 +147,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; }; @@ -156,7 +157,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; }; @@ -348,6 +350,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x4da8>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + macaddr_factory_4: macaddr@4 { compatible = "mac-base"; reg = <0x4 0x6>; diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi index fd73bfcb3e..72ff75cefa 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi @@ -81,7 +81,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <5000000 6000000>; }; }; @@ -90,7 +91,8 @@ wifi@0,0 { compatible = "mediatek,mt76"; reg = <0x0 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; ieee80211-freq-limit = <2400000 2500000>; }; }; @@ -275,6 +277,14 @@ #address-cells = <1>; #size-cells = <1>; + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + macaddr_factory_4: macaddr@4 { compatible = "mac-base"; reg = <0x4 0x6>; From 3f8ed239a64ec63eeb883bd8b0b603f011d40f59 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Tue, 16 Jan 2024 21:41:40 +0800 Subject: [PATCH 145/222] ramips: mt7621: convert Linksys devices EEPROM to NVMEM format -+-----------------------------+- | Model | NIC | -+-----------------------------+- | EA6350 v4 | MT7603 + MT7613 | -+-----------------------------+- | EA7300 v2 | MT7603 + MT7615 | -+-----------------------------+- | Others | MT7615 *2 | -+-----------------------------+- Signed-off-by: Shiji Yang --- .../ramips/dts/mt7621_linksys_ea6350-v4.dts | 5 +++++ .../ramips/dts/mt7621_linksys_ea7300-v2.dts | 5 +++++ .../ramips/dts/mt7621_linksys_ea7xxx.dtsi | 20 +++++++++++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_linksys_ea6350-v4.dts b/target/linux/ramips/dts/mt7621_linksys_ea6350-v4.dts index 71e8dcedbf..35a90ea070 100644 --- a/target/linux/ramips/dts/mt7621_linksys_ea6350-v4.dts +++ b/target/linux/ramips/dts/mt7621_linksys_ea6350-v4.dts @@ -7,6 +7,11 @@ model = "Linksys EA6350 v4"; }; +/* override EEPROM size to 0x400 for MT7603 */ +&eeprom_factory_0 { + reg = <0x0 0x400>; +}; + &gmac1 { phy-handle = <ðphy4>; }; diff --git a/target/linux/ramips/dts/mt7621_linksys_ea7300-v2.dts b/target/linux/ramips/dts/mt7621_linksys_ea7300-v2.dts index 4ee148828a..e3336c1dbb 100644 --- a/target/linux/ramips/dts/mt7621_linksys_ea7300-v2.dts +++ b/target/linux/ramips/dts/mt7621_linksys_ea7300-v2.dts @@ -6,3 +6,8 @@ compatible = "linksys,ea7300-v2", "mediatek,mt7621-soc"; model = "Linksys EA7300 v2"; }; + +/* override EEPROM size to 0x400 for MT7603 */ +&eeprom_factory_0 { + reg = <0x0 0x400>; +}; diff --git a/target/linux/ramips/dts/mt7621_linksys_ea7xxx.dtsi b/target/linux/ramips/dts/mt7621_linksys_ea7xxx.dtsi index 4663d873fe..4980b4fe9b 100644 --- a/target/linux/ramips/dts/mt7621_linksys_ea7xxx.dtsi +++ b/target/linux/ramips/dts/mt7621_linksys_ea7xxx.dtsi @@ -101,6 +101,20 @@ label = "factory"; reg = <0xc0000 0x40000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x4da8>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + }; }; partition@100000 { @@ -165,7 +179,8 @@ mt76@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x0000>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; }; }; @@ -173,7 +188,8 @@ mt76@0,0 { compatible = "mediatek,mt76"; reg = <0x0000 0 0 0 0>; - mediatek,mtd-eeprom = <&factory 0x8000>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; }; }; From e1a6c7213fa1852d8759f4deb1243e79af49ed3e Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 17 Jan 2024 01:48:29 +0000 Subject: [PATCH 146/222] mediatek: refresh patches-6.1 Refresh patches for Linux 6.1 which no longer apply cleanly after adding patches to fix ethernet rx hang issue on MT7981/MT7986. Fixes: ede34465de ("mediatek: fix ethernet rx hang issue on MT7981/MT7986") Signed-off-by: Daniel Golle --- ...iatek-split-tx-and-rx-fields-in-mtk_.patch | 82 +++++++++---------- ...iatek-use-QDMA-instead-of-ADMAv2-on-.patch | 14 ++-- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/target/linux/mediatek/patches-6.1/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch b/target/linux/mediatek/patches-6.1/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch index 4a624a3ef9..df37a61c23 100644 --- a/target/linux/mediatek/patches-6.1/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch +++ b/target/linux/mediatek/patches-6.1/961-net-ethernet-mediatek-split-tx-and-rx-fields-in-mtk_.patch @@ -15,7 +15,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1238,7 +1238,7 @@ static int mtk_init_fq_dma(struct mtk_et +@@ -1239,7 +1239,7 @@ static int mtk_init_fq_dma(struct mtk_et eth->scratch_ring = eth->sram_base; else eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, @@ -24,7 +24,7 @@ Signed-off-by: Lorenzo Bianconi ð->phy_scratch_ring, GFP_KERNEL); if (unlikely(!eth->scratch_ring)) -@@ -1254,16 +1254,16 @@ static int mtk_init_fq_dma(struct mtk_et +@@ -1255,16 +1255,16 @@ static int mtk_init_fq_dma(struct mtk_et if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr))) return -ENOMEM; @@ -44,7 +44,7 @@ Signed-off-by: Lorenzo Bianconi txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); txd->txd4 = 0; -@@ -1512,7 +1512,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1513,7 +1513,7 @@ static int mtk_tx_map(struct sk_buff *sk if (itxd == ring->last_free) return -ENOMEM; @@ -53,7 +53,7 @@ Signed-off-by: Lorenzo Bianconi memset(itx_buf, 0, sizeof(*itx_buf)); txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size, -@@ -1553,7 +1553,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1554,7 +1554,7 @@ static int mtk_tx_map(struct sk_buff *sk memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info)); txd_info.size = min_t(unsigned int, frag_size, @@ -62,7 +62,7 @@ Signed-off-by: Lorenzo Bianconi txd_info.qid = queue; txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 && !(frag_size - txd_info.size); -@@ -1566,7 +1566,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1567,7 +1567,7 @@ static int mtk_tx_map(struct sk_buff *sk mtk_tx_set_dma_desc(dev, txd, &txd_info); tx_buf = mtk_desc_to_tx_buf(ring, txd, @@ -71,7 +71,7 @@ Signed-off-by: Lorenzo Bianconi if (new_desc) memset(tx_buf, 0, sizeof(*tx_buf)); tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; -@@ -1609,7 +1609,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1610,7 +1610,7 @@ static int mtk_tx_map(struct sk_buff *sk } else { int next_idx; @@ -80,7 +80,7 @@ Signed-off-by: Lorenzo Bianconi ring->dma_size); mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0); } -@@ -1618,7 +1618,7 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -1619,7 +1619,7 @@ static int mtk_tx_map(struct sk_buff *sk err_dma: do { @@ -89,7 +89,7 @@ Signed-off-by: Lorenzo Bianconi /* unmap dma */ mtk_tx_unmap(eth, tx_buf, NULL, false); -@@ -1643,7 +1643,7 @@ static int mtk_cal_txd_req(struct mtk_et +@@ -1644,7 +1644,7 @@ static int mtk_cal_txd_req(struct mtk_et for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { frag = &skb_shinfo(skb)->frags[i]; nfrags += DIV_ROUND_UP(skb_frag_size(frag), @@ -98,7 +98,7 @@ Signed-off-by: Lorenzo Bianconi } } else { nfrags += skb_shinfo(skb)->nr_frags; -@@ -1784,7 +1784,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri +@@ -1785,7 +1785,7 @@ static struct mtk_rx_ring *mtk_get_rx_ri ring = ð->rx_ring[i]; idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); @@ -107,7 +107,7 @@ Signed-off-by: Lorenzo Bianconi if (rxd->rxd2 & RX_DMA_DONE) { ring->calc_idx_update = true; return ring; -@@ -1952,7 +1952,7 @@ static int mtk_xdp_submit_frame(struct m +@@ -1953,7 +1953,7 @@ static int mtk_xdp_submit_frame(struct m } htxd = txd; @@ -116,7 +116,7 @@ Signed-off-by: Lorenzo Bianconi memset(tx_buf, 0, sizeof(*tx_buf)); htx_buf = tx_buf; -@@ -1971,7 +1971,7 @@ static int mtk_xdp_submit_frame(struct m +@@ -1972,7 +1972,7 @@ static int mtk_xdp_submit_frame(struct m goto unmap; tx_buf = mtk_desc_to_tx_buf(ring, txd, @@ -125,7 +125,7 @@ Signed-off-by: Lorenzo Bianconi memset(tx_buf, 0, sizeof(*tx_buf)); n_desc++; } -@@ -2009,7 +2009,7 @@ static int mtk_xdp_submit_frame(struct m +@@ -2010,7 +2010,7 @@ static int mtk_xdp_submit_frame(struct m } else { int idx; @@ -134,7 +134,7 @@ Signed-off-by: Lorenzo Bianconi mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size), MT7628_TX_CTX_IDX0); } -@@ -2020,7 +2020,7 @@ static int mtk_xdp_submit_frame(struct m +@@ -2021,7 +2021,7 @@ static int mtk_xdp_submit_frame(struct m unmap: while (htxd != txd) { @@ -143,7 +143,7 @@ Signed-off-by: Lorenzo Bianconi mtk_tx_unmap(eth, tx_buf, NULL, false); htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; -@@ -2151,7 +2151,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -2152,7 +2152,7 @@ static int mtk_poll_rx(struct napi_struc goto rx_done; idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); @@ -152,7 +152,7 @@ Signed-off-by: Lorenzo Bianconi data = ring->data[idx]; if (!mtk_rx_get_desc(eth, &trxd, rxd)) -@@ -2286,7 +2286,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -2287,7 +2287,7 @@ static int mtk_poll_rx(struct napi_struc rxdcsum = &trxd.rxd4; } @@ -161,7 +161,7 @@ Signed-off-by: Lorenzo Bianconi skb->ip_summed = CHECKSUM_UNNECESSARY; else skb_checksum_none_assert(skb); -@@ -2410,7 +2410,7 @@ static int mtk_poll_tx_qdma(struct mtk_e +@@ -2411,7 +2411,7 @@ static int mtk_poll_tx_qdma(struct mtk_e break; tx_buf = mtk_desc_to_tx_buf(ring, desc, @@ -170,7 +170,7 @@ Signed-off-by: Lorenzo Bianconi if (!tx_buf->data) break; -@@ -2461,7 +2461,7 @@ static int mtk_poll_tx_pdma(struct mtk_e +@@ -2462,7 +2462,7 @@ static int mtk_poll_tx_pdma(struct mtk_e } mtk_tx_unmap(eth, tx_buf, &bq, true); @@ -179,7 +179,7 @@ Signed-off-by: Lorenzo Bianconi ring->last_free = desc; atomic_inc(&ring->free_count); -@@ -2551,7 +2551,7 @@ static int mtk_napi_rx(struct napi_struc +@@ -2552,7 +2552,7 @@ static int mtk_napi_rx(struct napi_struc do { int rx_done; @@ -188,7 +188,7 @@ Signed-off-by: Lorenzo Bianconi reg_map->pdma.irq_status); rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth); rx_done_total += rx_done; -@@ -2567,10 +2567,10 @@ static int mtk_napi_rx(struct napi_struc +@@ -2568,10 +2568,10 @@ static int mtk_napi_rx(struct napi_struc return budget; } while (mtk_r32(eth, reg_map->pdma.irq_status) & @@ -201,7 +201,7 @@ Signed-off-by: Lorenzo Bianconi return rx_done_total; } -@@ -2579,7 +2579,7 @@ static int mtk_tx_alloc(struct mtk_eth * +@@ -2580,7 +2580,7 @@ static int mtk_tx_alloc(struct mtk_eth * { const struct mtk_soc_data *soc = eth->soc; struct mtk_tx_ring *ring = ð->tx_ring; @@ -210,7 +210,7 @@ Signed-off-by: Lorenzo Bianconi struct mtk_tx_dma_v2 *txd; int ring_size; u32 ofs, val; -@@ -2702,14 +2702,14 @@ static void mtk_tx_clean(struct mtk_eth +@@ -2703,14 +2703,14 @@ static void mtk_tx_clean(struct mtk_eth } if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { dma_free_coherent(eth->dma_dev, @@ -227,7 +227,7 @@ Signed-off-by: Lorenzo Bianconi ring->dma_pdma, ring->phys_pdma); ring->dma_pdma = NULL; } -@@ -2764,15 +2764,15 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2765,15 +2765,15 @@ static int mtk_rx_alloc(struct mtk_eth * if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || rx_flag != MTK_RX_FLAGS_NORMAL) { ring->dma = dma_alloc_coherent(eth->dma_dev, @@ -247,7 +247,7 @@ Signed-off-by: Lorenzo Bianconi } if (!ring->dma) -@@ -2783,7 +2783,7 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2784,7 +2784,7 @@ static int mtk_rx_alloc(struct mtk_eth * dma_addr_t dma_addr; void *data; @@ -256,7 +256,7 @@ Signed-off-by: Lorenzo Bianconi if (ring->page_pool) { data = mtk_page_pool_get_buff(ring->page_pool, &dma_addr, GFP_KERNEL); -@@ -2874,7 +2874,7 @@ static void mtk_rx_clean(struct mtk_eth +@@ -2875,7 +2875,7 @@ static void mtk_rx_clean(struct mtk_eth if (!ring->data[i]) continue; @@ -265,7 +265,7 @@ Signed-off-by: Lorenzo Bianconi if (!rxd->rxd1) continue; -@@ -2891,7 +2891,7 @@ static void mtk_rx_clean(struct mtk_eth +@@ -2892,7 +2892,7 @@ static void mtk_rx_clean(struct mtk_eth if (!in_sram && ring->dma) { dma_free_coherent(eth->dma_dev, @@ -274,7 +274,7 @@ Signed-off-by: Lorenzo Bianconi ring->dma, ring->phys); ring->dma = NULL; } -@@ -3254,7 +3254,7 @@ static void mtk_dma_free(struct mtk_eth +@@ -3255,7 +3255,7 @@ static void mtk_dma_free(struct mtk_eth netdev_reset_queue(eth->netdev[i]); if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { dma_free_coherent(eth->dma_dev, @@ -283,7 +283,7 @@ Signed-off-by: Lorenzo Bianconi eth->scratch_ring, eth->phy_scratch_ring); eth->scratch_ring = NULL; eth->phy_scratch_ring = 0; -@@ -3304,7 +3304,7 @@ static irqreturn_t mtk_handle_irq_rx(int +@@ -3305,7 +3305,7 @@ static irqreturn_t mtk_handle_irq_rx(int eth->rx_events++; if (likely(napi_schedule_prep(ð->rx_napi))) { @@ -292,7 +292,7 @@ Signed-off-by: Lorenzo Bianconi __napi_schedule(ð->rx_napi); } -@@ -3330,9 +3330,9 @@ static irqreturn_t mtk_handle_irq(int ir +@@ -3331,9 +3331,9 @@ static irqreturn_t mtk_handle_irq(int ir const struct mtk_reg_map *reg_map = eth->soc->reg_map; if (mtk_r32(eth, reg_map->pdma.irq_mask) & @@ -304,7 +304,7 @@ Signed-off-by: Lorenzo Bianconi mtk_handle_irq_rx(irq, _eth); } if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) { -@@ -3350,10 +3350,10 @@ static void mtk_poll_controller(struct n +@@ -3351,10 +3351,10 @@ static void mtk_poll_controller(struct n struct mtk_eth *eth = mac->hw; mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); @@ -317,7 +317,7 @@ Signed-off-by: Lorenzo Bianconi } #endif -@@ -3516,7 +3516,7 @@ static int mtk_open(struct net_device *d +@@ -3517,7 +3517,7 @@ static int mtk_open(struct net_device *d napi_enable(ð->tx_napi); napi_enable(ð->rx_napi); mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); @@ -326,7 +326,7 @@ Signed-off-by: Lorenzo Bianconi refcount_set(ð->dma_refcnt, 1); } else -@@ -3599,7 +3599,7 @@ static int mtk_stop(struct net_device *d +@@ -3600,7 +3600,7 @@ static int mtk_stop(struct net_device *d mtk_gdm_config(eth, MTK_GDMA_DROP_ALL); mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); @@ -335,7 +335,7 @@ Signed-off-by: Lorenzo Bianconi napi_disable(ð->tx_napi); napi_disable(ð->rx_napi); -@@ -4075,9 +4075,9 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -4076,9 +4076,9 @@ static int mtk_hw_init(struct mtk_eth *e /* FE int grouping */ mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp); @@ -347,7 +347,7 @@ Signed-off-by: Lorenzo Bianconi mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); if (mtk_is_netsys_v3_or_greater(eth)) { -@@ -5172,11 +5172,15 @@ static const struct mtk_soc_data mt2701_ +@@ -5173,11 +5173,15 @@ static const struct mtk_soc_data mt2701_ .required_clks = MT7623_CLKS_BITMAP, .required_pctl = true, .version = 1, @@ -368,7 +368,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5192,11 +5196,15 @@ static const struct mtk_soc_data mt7621_ +@@ -5193,11 +5197,15 @@ static const struct mtk_soc_data mt7621_ .offload_version = 1, .hash_offset = 2, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, @@ -389,7 +389,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5214,11 +5222,15 @@ static const struct mtk_soc_data mt7622_ +@@ -5215,11 +5223,15 @@ static const struct mtk_soc_data mt7622_ .hash_offset = 2, .has_accounting = true, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, @@ -410,7 +410,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5235,11 +5247,15 @@ static const struct mtk_soc_data mt7623_ +@@ -5236,11 +5248,15 @@ static const struct mtk_soc_data mt7623_ .hash_offset = 2, .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, .disable_pll_modes = true, @@ -431,7 +431,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5254,11 +5270,15 @@ static const struct mtk_soc_data mt7629_ +@@ -5255,11 +5271,15 @@ static const struct mtk_soc_data mt7629_ .required_pctl = false, .has_accounting = true, .version = 1, @@ -452,7 +452,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN, .dma_len_offset = 16, }, -@@ -5276,11 +5296,15 @@ static const struct mtk_soc_data mt7981_ +@@ -5277,11 +5297,15 @@ static const struct mtk_soc_data mt7981_ .hash_offset = 4, .has_accounting = true, .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, @@ -473,7 +473,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = 8, }, -@@ -5298,11 +5322,15 @@ static const struct mtk_soc_data mt7986_ +@@ -5299,11 +5323,15 @@ static const struct mtk_soc_data mt7986_ .hash_offset = 4, .has_accounting = true, .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, @@ -494,7 +494,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = 8, }, -@@ -5320,11 +5348,15 @@ static const struct mtk_soc_data mt7988_ +@@ -5321,11 +5349,15 @@ static const struct mtk_soc_data mt7988_ .hash_offset = 4, .has_accounting = true, .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, @@ -515,7 +515,7 @@ Signed-off-by: Lorenzo Bianconi .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, .dma_len_offset = 8, }, -@@ -5337,11 +5369,15 @@ static const struct mtk_soc_data rt5350_ +@@ -5338,11 +5370,15 @@ static const struct mtk_soc_data rt5350_ .required_clks = MT7628_CLKS_BITMAP, .required_pctl = false, .version = 1, diff --git a/target/linux/mediatek/patches-6.1/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch b/target/linux/mediatek/patches-6.1/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch index 86cdcb5cb0..66c28eaaaa 100644 --- a/target/linux/mediatek/patches-6.1/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch +++ b/target/linux/mediatek/patches-6.1/962-net-ethernet-mediatek-use-QDMA-instead-of-ADMAv2-on-.patch @@ -44,7 +44,7 @@ Signed-off-by: Daniel Golle }, .qdma = { .qtx_cfg = 0x4400, -@@ -1206,7 +1206,7 @@ static bool mtk_rx_get_desc(struct mtk_e +@@ -1207,7 +1207,7 @@ static bool mtk_rx_get_desc(struct mtk_e rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); @@ -53,7 +53,7 @@ Signed-off-by: Daniel Golle rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); } -@@ -2158,7 +2158,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -2159,7 +2159,7 @@ static int mtk_poll_rx(struct napi_struc break; /* find out which mac the packet come from. values start at 1 */ @@ -62,7 +62,7 @@ Signed-off-by: Daniel Golle u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5); switch (val) { -@@ -2270,7 +2270,7 @@ static int mtk_poll_rx(struct napi_struc +@@ -2271,7 +2271,7 @@ static int mtk_poll_rx(struct napi_struc skb->dev = netdev; bytes += skb->len; @@ -71,7 +71,7 @@ Signed-off-by: Daniel Golle reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; if (hash != MTK_RXD5_FOE_ENTRY) -@@ -2820,7 +2820,7 @@ static int mtk_rx_alloc(struct mtk_eth * +@@ -2821,7 +2821,7 @@ static int mtk_rx_alloc(struct mtk_eth * rxd->rxd3 = 0; rxd->rxd4 = 0; @@ -80,7 +80,7 @@ Signed-off-by: Daniel Golle rxd->rxd5 = 0; rxd->rxd6 = 0; rxd->rxd7 = 0; -@@ -4021,7 +4021,7 @@ static int mtk_hw_init(struct mtk_eth *e +@@ -4022,7 +4022,7 @@ static int mtk_hw_init(struct mtk_eth *e else mtk_hw_reset(eth); @@ -89,7 +89,7 @@ Signed-off-by: Daniel Golle /* Set FE to PDMAv2 if necessary */ val = mtk_r32(eth, MTK_FE_GLO_MISC); mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); -@@ -5302,11 +5302,11 @@ static const struct mtk_soc_data mt7981_ +@@ -5303,11 +5303,11 @@ static const struct mtk_soc_data mt7981_ .dma_len_offset = 8, }, .rx = { @@ -105,7 +105,7 @@ Signed-off-by: Daniel Golle }, }; -@@ -5328,11 +5328,11 @@ static const struct mtk_soc_data mt7986_ +@@ -5329,11 +5329,11 @@ static const struct mtk_soc_data mt7986_ .dma_len_offset = 8, }, .rx = { From 038b0cb4f1ac08803d601cea695c659c10629196 Mon Sep 17 00:00:00 2001 From: Chen Minqiang Date: Tue, 16 Jan 2024 17:20:04 +0800 Subject: [PATCH 147/222] kernel: ksmbd: only v2 leases handle the directory This backport a fix for ksmbd. Refer: https://github.com/namjaejeon/ksmbd/issues/469 Signed-off-by: Chen Minqiang --- ...-only-v2-leases-handle-the-directory.patch | 32 +++++++++++++++++++ ...-only-v2-leases-handle-the-directory.patch | 32 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 target/linux/generic/pending-5.15/540-ksmbd-only-v2-leases-handle-the-directory.patch create mode 100644 target/linux/generic/pending-6.1/540-ksmbd-only-v2-leases-handle-the-directory.patch diff --git a/target/linux/generic/pending-5.15/540-ksmbd-only-v2-leases-handle-the-directory.patch b/target/linux/generic/pending-5.15/540-ksmbd-only-v2-leases-handle-the-directory.patch new file mode 100644 index 0000000000..1bc0e72418 --- /dev/null +++ b/target/linux/generic/pending-5.15/540-ksmbd-only-v2-leases-handle-the-directory.patch @@ -0,0 +1,32 @@ +From cb1d41b99e4afa062f904339666fae2578559718 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Mon, 15 Jan 2024 10:24:54 +0900 +Subject: [PATCH] ksmbd: only v2 leases handle the directory + +When smb2 leases is disable, ksmbd can send oplock break notification +and cause wait oplock break ack timeout. It may appear like hang when +accessing a directory. This patch make only v2 leases handle the +directory. + +Cc: stable@vger.kernel.org +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +--- + fs/ksmbd/oplock.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/ksmbd/oplock.c ++++ b/fs/ksmbd/oplock.c +@@ -1191,6 +1191,12 @@ int smb_grant_oplock(struct ksmbd_work * + bool prev_op_has_lease; + __le32 prev_op_state = 0; + ++ /* Only v2 leases handle the directory */ ++ if (S_ISDIR(file_inode(fp->filp)->i_mode)) { ++ if (!lctx || lctx->version != 2) ++ return 0; ++ } ++ + opinfo = alloc_opinfo(work, pid, tid); + if (!opinfo) + return -ENOMEM; diff --git a/target/linux/generic/pending-6.1/540-ksmbd-only-v2-leases-handle-the-directory.patch b/target/linux/generic/pending-6.1/540-ksmbd-only-v2-leases-handle-the-directory.patch new file mode 100644 index 0000000000..b565fbd5b9 --- /dev/null +++ b/target/linux/generic/pending-6.1/540-ksmbd-only-v2-leases-handle-the-directory.patch @@ -0,0 +1,32 @@ +From 86b7307af26834415e1ba8597319a8b64846346f Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Mon, 15 Jan 2024 10:24:54 +0900 +Subject: [PATCH] ksmbd: only v2 leases handle the directory + +When smb2 leases is disable, ksmbd can send oplock break notification +and cause wait oplock break ack timeout. It may appear like hang when +accessing a directory. This patch make only v2 leases handle the +directory. + +Cc: stable@vger.kernel.org +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +--- + fs/smb/server/oplock.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -1191,6 +1191,12 @@ int smb_grant_oplock(struct ksmbd_work * + bool prev_op_has_lease; + __le32 prev_op_state = 0; + ++ /* Only v2 leases handle the directory */ ++ if (S_ISDIR(file_inode(fp->filp)->i_mode)) { ++ if (!lctx || lctx->version != 2) ++ return 0; ++ } ++ + opinfo = alloc_opinfo(work, pid, tid); + if (!opinfo) + return -ENOMEM; From 389135501565a6544775e0c75828a11e536e64a2 Mon Sep 17 00:00:00 2001 From: John Audia Date: Mon, 15 Jan 2024 15:25:53 -0500 Subject: [PATCH 148/222] kernel: bump 5.15 to 5.15.147 Changelog: https://cdn.kernel.org/pub/linux/kernel/v5.x/ChangeLog-5.15.147 Manually rebased: generic/backport-5.15/005-v5.17-01-Kbuild-use-Wdeclaration-after-statement.patch All other patches automatically rebased. Build system: x86_64 Build-tested: ramips/tplink_archer-a6-v3 Run-tested: ramips/tplink_archer-a6-v3 Signed-off-by: John Audia --- include/kernel-5.15 | 4 ++-- ...-net-usb-ax88179_178a-add-TSO-feature.patch | 10 +++++----- .../hack-5.15/901-debloat_sock_diag.patch | 2 +- .../generic/hack-5.15/902-debloat_proc.patch | 2 +- ...ing-with-source-address-failed-policy.patch | 18 +++++++++--------- ...bles-ignore-EOPNOTSUPP-on-flowtable-d.patch | 2 +- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/kernel-5.15 b/include/kernel-5.15 index f8ecac5742..5cc07434b2 100644 --- a/include/kernel-5.15 +++ b/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .146 -LINUX_KERNEL_HASH-5.15.146 = 5a807a5fa2a80ada957d8079681dfb5cc196ec26f43244d1c8a4fd7af592d192 +LINUX_VERSION-5.15 = .147 +LINUX_KERNEL_HASH-5.15.147 = 56c1e65625d201db431efda7a3816e7b424071e7cb0245b2ba594d15b1fdfcd4 diff --git a/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch b/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch index 598fa05e9b..698e524c35 100644 --- a/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch +++ b/target/linux/generic/backport-5.15/797-v5.17-net-usb-ax88179_178a-add-TSO-feature.patch @@ -18,7 +18,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c -@@ -1363,11 +1363,12 @@ static int ax88179_bind(struct usbnet *d +@@ -1333,11 +1333,12 @@ static int ax88179_bind(struct usbnet *d dev->mii.phy_id = 0x03; dev->mii.supports_gmii = 1; @@ -33,9 +33,9 @@ Signed-off-by: David S. Miller + + netif_set_gso_max_size(dev->net, 16384); - /* Enable checksum offload */ - *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | -@@ -1573,17 +1574,19 @@ ax88179_tx_fixup(struct usbnet *dev, str + ax88179_reset(dev); + +@@ -1507,17 +1508,19 @@ ax88179_tx_fixup(struct usbnet *dev, str { u32 tx_hdr1, tx_hdr2; int frame_size = dev->maxpacket; @@ -57,7 +57,7 @@ Signed-off-by: David S. Miller if ((skb_header_cloned(skb) || headroom < 0) && pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) { dev_kfree_skb_any(skb); -@@ -1594,6 +1597,8 @@ ax88179_tx_fixup(struct usbnet *dev, str +@@ -1528,6 +1531,8 @@ ax88179_tx_fixup(struct usbnet *dev, str put_unaligned_le32(tx_hdr1, ptr); put_unaligned_le32(tx_hdr2, ptr + 4); diff --git a/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch b/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch index 11f4f556e8..ab4d636956 100644 --- a/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-5.15/901-debloat_sock_diag.patch @@ -77,7 +77,7 @@ Signed-off-by: Felix Fietkau INDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *, u32)); INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, -@@ -1987,9 +2001,11 @@ static void __sk_free(struct sock *sk) +@@ -1994,9 +2008,11 @@ static void __sk_free(struct sock *sk) if (likely(sk->sk_net_refcnt)) sock_inuse_add(sock_net(sk), -1); diff --git a/target/linux/generic/hack-5.15/902-debloat_proc.patch b/target/linux/generic/hack-5.15/902-debloat_proc.patch index 768d3e1f0c..dcdad4ca69 100644 --- a/target/linux/generic/hack-5.15/902-debloat_proc.patch +++ b/target/linux/generic/hack-5.15/902-debloat_proc.patch @@ -330,7 +330,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -3881,6 +3881,8 @@ static __net_initdata struct pernet_oper +@@ -3889,6 +3889,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { diff --git a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index 7aaac96531..071a2ed3e5 100644 --- a/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-5.15/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -157,7 +157,7 @@ Signed-off-by: Jonas Gorski case RTN_THROW: case RTN_UNREACHABLE: default: -@@ -4560,6 +4579,17 @@ static int ip6_pkt_prohibit_out(struct n +@@ -4557,6 +4576,17 @@ static int ip6_pkt_prohibit_out(struct n return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); } @@ -175,7 +175,7 @@ Signed-off-by: Jonas Gorski /* * Allocate a dst for local (unicast / anycast) address. */ -@@ -5047,7 +5077,8 @@ static int rtm_to_fib6_config(struct sk_ +@@ -5044,7 +5074,8 @@ static int rtm_to_fib6_config(struct sk_ if (rtm->rtm_type == RTN_UNREACHABLE || rtm->rtm_type == RTN_BLACKHOLE || rtm->rtm_type == RTN_PROHIBIT || @@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -6301,6 +6332,8 @@ static int ip6_route_dev_notify(struct n +@@ -6298,6 +6329,8 @@ static int ip6_route_dev_notify(struct n #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.ip6_prohibit_entry->dst.dev = dev; net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); @@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); #endif -@@ -6312,6 +6345,7 @@ static int ip6_route_dev_notify(struct n +@@ -6309,6 +6342,7 @@ static int ip6_route_dev_notify(struct n in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); #ifdef CONFIG_IPV6_MULTIPLE_TABLES in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); @@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); #endif } -@@ -6503,6 +6537,8 @@ static int __net_init ip6_route_net_init +@@ -6500,6 +6534,8 @@ static int __net_init ip6_route_net_init #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.fib6_has_custom_rules = false; @@ -211,7 +211,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, sizeof(*net->ipv6.ip6_prohibit_entry), GFP_KERNEL); -@@ -6513,11 +6549,21 @@ static int __net_init ip6_route_net_init +@@ -6510,11 +6546,21 @@ static int __net_init ip6_route_net_init ip6_template_metrics, true); INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->rt6i_uncached); @@ -234,7 +234,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ip6_template_metrics, true); -@@ -6544,6 +6590,8 @@ out: +@@ -6541,6 +6587,8 @@ out: return ret; #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -243,7 +243,7 @@ Signed-off-by: Jonas Gorski out_ip6_prohibit_entry: kfree(net->ipv6.ip6_prohibit_entry); out_ip6_null_entry: -@@ -6563,6 +6611,7 @@ static void __net_exit ip6_route_net_exi +@@ -6560,6 +6608,7 @@ static void __net_exit ip6_route_net_exi kfree(net->ipv6.ip6_null_entry); #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); @@ -251,7 +251,7 @@ Signed-off-by: Jonas Gorski kfree(net->ipv6.ip6_blk_hole_entry); #endif dst_entries_destroy(&net->ipv6.ip6_dst_ops); -@@ -6646,6 +6695,9 @@ void __init ip6_route_init_special_entri +@@ -6643,6 +6692,9 @@ void __init ip6_route_init_special_entri init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); diff --git a/target/linux/generic/pending-5.15/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch b/target/linux/generic/pending-5.15/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch index 723af24770..d2ca7c7b53 100644 --- a/target/linux/generic/pending-5.15/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch +++ b/target/linux/generic/pending-5.15/701-netfilter-nf_tables-ignore-EOPNOTSUPP-on-flowtable-d.patch @@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c -@@ -7709,7 +7709,7 @@ static int nft_register_flowtable_net_ho +@@ -7736,7 +7736,7 @@ static int nft_register_flowtable_net_ho err = flowtable->data.type->setup(&flowtable->data, hook->ops.dev, FLOW_BLOCK_BIND); From f75de11de0407d724544f973908d693f9b78ede9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Thu, 18 Jan 2024 08:57:43 +0100 Subject: [PATCH 149/222] bmips: dts: remove unneeded cferom alias MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is no longer needed after nvmem-layout changes. Same as 6f328dfe19 for NAND devices. Signed-off-by: Álvaro Fernández Rojas --- target/linux/bmips/dts/bcm63167-sercomm-h500-s.dtsi | 2 +- target/linux/bmips/dts/bcm63168-comtrend-vr-3032u.dts | 2 +- target/linux/bmips/dts/bcm63168-sercomm-shg2500.dts | 2 +- target/linux/bmips/dts/bcm63169-comtrend-vg-8050.dts | 2 +- target/linux/bmips/dts/bcm6328-sercomm-ad1018.dts | 2 +- target/linux/bmips/dts/bcm6362-huawei-hg253s-v2.dts | 2 +- target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/target/linux/bmips/dts/bcm63167-sercomm-h500-s.dtsi b/target/linux/bmips/dts/bcm63167-sercomm-h500-s.dtsi index 4e4431f27c..a389187d8d 100644 --- a/target/linux/bmips/dts/bcm63167-sercomm-h500-s.dtsi +++ b/target/linux/bmips/dts/bcm63167-sercomm-h500-s.dtsi @@ -183,7 +183,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm63168-comtrend-vr-3032u.dts b/target/linux/bmips/dts/bcm63168-comtrend-vr-3032u.dts index d4520661a5..3f830f058e 100644 --- a/target/linux/bmips/dts/bcm63168-comtrend-vr-3032u.dts +++ b/target/linux/bmips/dts/bcm63168-comtrend-vr-3032u.dts @@ -166,7 +166,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm63168-sercomm-shg2500.dts b/target/linux/bmips/dts/bcm63168-sercomm-shg2500.dts index bfa9835b26..3c79d38bfb 100644 --- a/target/linux/bmips/dts/bcm63168-sercomm-shg2500.dts +++ b/target/linux/bmips/dts/bcm63168-sercomm-shg2500.dts @@ -191,7 +191,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm63169-comtrend-vg-8050.dts b/target/linux/bmips/dts/bcm63169-comtrend-vg-8050.dts index be7f90fbd9..b0576748d3 100644 --- a/target/linux/bmips/dts/bcm63169-comtrend-vg-8050.dts +++ b/target/linux/bmips/dts/bcm63169-comtrend-vg-8050.dts @@ -181,7 +181,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6328-sercomm-ad1018.dts b/target/linux/bmips/dts/bcm6328-sercomm-ad1018.dts index aefa72235f..438f1d5fec 100644 --- a/target/linux/bmips/dts/bcm6328-sercomm-ad1018.dts +++ b/target/linux/bmips/dts/bcm6328-sercomm-ad1018.dts @@ -187,7 +187,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6362-huawei-hg253s-v2.dts b/target/linux/bmips/dts/bcm6362-huawei-hg253s-v2.dts index 47be99133d..32682b2610 100644 --- a/target/linux/bmips/dts/bcm6362-huawei-hg253s-v2.dts +++ b/target/linux/bmips/dts/bcm6362-huawei-hg253s-v2.dts @@ -160,7 +160,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0020000>; read-only; diff --git a/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts b/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts index 53a1c0c01f..f7182b78da 100644 --- a/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts +++ b/target/linux/bmips/dts/bcm6362-netgear-dgnd3700-v2.dts @@ -212,7 +212,7 @@ #address-cells = <1>; #size-cells = <1>; - cferom: partition@0 { + partition@0 { label = "cferom"; reg = <0x0000000 0x0004000>; read-only; From e57eb9f28e7ba383796df8cae1b3ca39804f6326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 16 Jan 2024 14:52:05 +0100 Subject: [PATCH 150/222] bcm27xx-utils: add new package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The raspberypi/userland repository has been deprecated and the RPi tools have been moved to the raspberrypi/utils repository. https://github.com/raspberrypi/userland/commit/96a7334ae9d5fc9db7ac92e59852377df63f1848 Signed-off-by: Álvaro Fernández Rojas --- package/utils/bcm27xx-utils/Makefile | 63 +++++ .../0001-raspinfo-adapt-to-OpenWrt.patch | 255 ++++++++++++++++++ 2 files changed, 318 insertions(+) create mode 100644 package/utils/bcm27xx-utils/Makefile create mode 100644 package/utils/bcm27xx-utils/patches/0001-raspinfo-adapt-to-OpenWrt.patch diff --git a/package/utils/bcm27xx-utils/Makefile b/package/utils/bcm27xx-utils/Makefile new file mode 100644 index 0000000000..ca8c3969c6 --- /dev/null +++ b/package/utils/bcm27xx-utils/Makefile @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0-only + +include $(TOPDIR)/rules.mk + +PKG_NAME:=bcm27xx-utils +PKG_VERSION:=2024-01-15 +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/raspberrypi/utils.git +PKG_SOURCE_VERSION:=32602f565c6cb854d1f2643b51a022991cea2b1b +PKG_MIRROR_HASH:=efbfa0f1aabbe9ecb347c3a27629fb757f67ff283c8d3b1ee7376ddc6925127b + +PKG_FLAGS:=nonshared + +PKG_LICENSE:=BSD-3-Clause +PKG_LICENSE_FILES:=LICENCE + +CMAKE_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/bcm27xx-utils + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=@TARGET_bcm27xx +libfdt + TITLE:=BCM27xx scripts and simple applications + PROVIDES:=bcm27xx-userland +endef + +define Package/bcm27xx-utils/description + BCM27xx scripts and simple applications. + Replaces bcm27xx-userland scripts and applications. +endef + +define Package/bcm27xx-utils/install + $(INSTALL_DIR) $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dtmerge $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dtoverlay $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dtparam $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/eepdump $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/eepflash.sh $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/eepmake $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/otpset $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/overlaycheck $(1)/usr/bin + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/bin/overlaycheck_exclusions.txt $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ovmerge $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/pinctrl $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/raspinfo $(1)/usr/bin + + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/vcgencmd $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/vclog $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/vcmailbox $(1)/usr/bin +endef + +$(eval $(call BuildPackage,bcm27xx-utils)) diff --git a/package/utils/bcm27xx-utils/patches/0001-raspinfo-adapt-to-OpenWrt.patch b/package/utils/bcm27xx-utils/patches/0001-raspinfo-adapt-to-OpenWrt.patch new file mode 100644 index 0000000000..9dd6d99626 --- /dev/null +++ b/package/utils/bcm27xx-utils/patches/0001-raspinfo-adapt-to-OpenWrt.patch @@ -0,0 +1,255 @@ +From 0db3fb3119eda8c2360454c2a01f84602a879c38 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= +Date: Tue, 16 Jan 2024 15:32:12 +0100 +Subject: [PATCH] raspinfo: adapt to OpenWrt +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Álvaro Fernández Rojas +--- + raspinfo/raspinfo | 186 ++++------------------------------------------ + 1 file changed, 13 insertions(+), 173 deletions(-) + +--- a/raspinfo/raspinfo ++++ b/raspinfo/raspinfo +@@ -1,4 +1,4 @@ +-#!/bin/bash ++#!/bin/sh + + # Some of the regex's used in sed + # Catch basic IP6 address "s/\([0-9a-fA-F]\{1,4\}:\)\{7,7\}[0-9a-fA-F]\{1,4\}/y.y.y.y.y.y.y.y/g" +@@ -6,147 +6,6 @@ + # IP4 d.d.d.d decimal "s/\([0-9]\{1,3\}\.\)\{3,3\}[0-9]\{1,3\}/x.x.x.x/g" + # mac address "s/\([0-9a-fA-F]\{2,2\}\:\)\{5,5\}[0-9a-fA-F]\{2,2\}/m.m.m.m/g" + +- +-display_info_drm() { +- # If running X then can use xrandr, otherwise +- # dump the /sys/class entries for the displays +- if command -v xrandr > /dev/null && +- DISPLAY=${DISPLAY:-:0} xrandr --listmonitors &>/dev/null; +- then +- echo "Running (F)KMS and X" +- echo +- +- DISPLAY=${DISPLAY:-:0} xrandr --verbose +- else +- echo "Running (F)KMS, console" +- echo +- +- for card in /sys/class/drm/card[0-9]-*; +- do +- echo $card +- +- # if kmsprint isn't installed print basic mode info +- if ! command -v kmsprint > /dev/null; then +- if [ -f $card/modes ]; +- then +- cat $card/modes +- else +- echo "No modes found" +- fi +- fi +- +- if [ -f $card/edid ]; +- then +- base64 $card/edid +- else +- echo "No EDID found" +- fi +- echo +- done +- fi +- +- # kmsprint is more useful, but not always installed +- echo +- if command -v kmsprint > /dev/null; then +- kmsprint +- echo +- kmsprint -m +- else +- echo "kmsprint is not installed. Install with: sudo apt install kms++-utils" +- fi +- +- echo +- +- # dump the /sys/class entries for the displays +- cardfound=0 +- for card in `seq 0 9`; +- do +- if sudo test -f "/sys/kernel/debug/dri/${card}/state"; +- then +- for hdmi in 0 1; +- do +- if sudo test -f "/sys/kernel/debug/dri/${card}/hdmi${hdmi}_regs"; +- then +- echo "HDMI${hdmi}: $(sudo cat /sys/kernel/debug/dri/$card/hdmi${hdmi}_regs | grep HOTPLUG)" +- fi +- done +- echo +- echo "/sys/kernel/debug/dri/$card/state:" +- sudo cat "/sys/kernel/debug/dri/$card/state" +- echo +- cardfound=1 +- fi +- done +- if [ "$cardfound" == "0" ]; +- then +- echo "kms state not found" +- fi +- echo +- +-} +- +-display_info_legacy() { +- # Legacy mode +- echo "Running Legacy framebuffer" +- echo +- +- for card in `seq 0 9`; +- do +- F="/dev/fb${card}" +- if test -e $F; +- then +- echo Framebuffer: $F +- fbset -s -fb $F +- fi +- done +- +- disps=`tvservice -l | awk '/Display Number/{print substr($3,1,1)}'` +- +- tmp=$(mktemp) +- +- for display in $disps +- do +- echo +- echo "Display: " $display +- +- tvservice -v $display -s +- tvservice -v $display -n +- tvservice -v $display -m CEA +- tvservice -v $display -m DMT +- +- echo +- tvservice -v $display -d $tmp > /dev/null +- base64 $tmp +- done +- +- rm $tmp +-} +- +-display_info() { +- # Check if we are running a KMS/DRM system +- +- if [ -d "/dev/dri" ]; +- then +- display_info_drm +- else +- display_info_legacy +- fi +-} +- +-audio_info() { +- aplay -l +- echo +- aplay -L +- echo +- systemctl --user status pipewire.socket pipewire.service pulseaudio.service pulseaudio.socket +- echo +- if command -v pactl > /dev/null; then +- pactl info +- else +- echo pactl not installed +- fi +-} +- + OUT=raspinfo.txt + + rm -f $OUT +@@ -163,8 +22,6 @@ echo + cat /etc/os-release | head -4 + echo + +-cat /etc/rpi-issue +-echo + uname -a + + cat /proc/cpuinfo | tail -3 +@@ -190,17 +47,6 @@ echo + cat /proc/swaps + + echo +-echo "Package version information" +-echo "---------------------------" +- +-apt-cache policy raspberrypi-ui-mods | head -2 +-apt-cache policy raspberrypi-sys-mods | head -2 +-apt-cache policy openbox | head -2 +-apt-cache policy lxpanel | head -2 +-apt-cache policy pcmanfm | head -2 +-apt-cache policy rpd-plym-splash | head -2 +- +-echo + echo "Networking Information" + echo "----------------------" + echo +@@ -212,21 +58,11 @@ echo "USB Information" + echo "---------------" + echo + +-lsusb -t +- +-echo +-echo "Display Information" +-echo "-------------------" +-echo +- +-display_info +- +-echo +-echo "Audio Information" +-echo "-------------------" +-echo +- +-audio_info ++if command -v lsusb > /dev/null; then ++ lsusb -t ++else ++ echo usbutils not installed ++fi + + echo + echo "config.txt" +@@ -250,7 +86,7 @@ echo "-----------------" + echo + + if command -v pinctrl > /dev/null; then +- sudo pinctrl 2>&1 ++ pinctrl 2>&1 + elif command -v raspi-gpio > /dev/null; then + raspi-gpio get 2>&1 + else +@@ -263,9 +99,9 @@ echo "------------------" + echo + + if command -v vcdbg > /dev/null; then +- sudo vcdbg log msg 2>&1 ++ vcdbg log msg 2>&1 + elif command -v vclog > /dev/null; then +- sudo vclog --msg 2>&1 ++ vclog --msg 2>&1 + else + echo "vcdbg not found" + fi +@@ -284,5 +120,9 @@ echo + echo "EEPROM" + echo "------" + echo +-sudo rpi-eeprom-update ++if command -v rpi-eeprom-update > /dev/null; then ++ rpi-eeprom-update ++else ++ echo bcm27xx-eeprom not installed ++fi + fi From 189838517e88dc5b519433949c945959d17b89f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Wed, 17 Jan 2024 10:39:37 +0100 Subject: [PATCH 151/222] bcm27xx: config: update documentation links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation links have changed and are no longer valid. Signed-off-by: Álvaro Fernández Rojas --- target/linux/bcm27xx/image/config.txt | 2 +- target/linux/bcm27xx/image/distroconfig.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/bcm27xx/image/config.txt b/target/linux/bcm27xx/image/config.txt index f8ca1bf2d4..db35d72ab7 100644 --- a/target/linux/bcm27xx/image/config.txt +++ b/target/linux/bcm27xx/image/config.txt @@ -4,7 +4,7 @@ ################################################################################ # For overclocking and various other settings, see: -# https://www.raspberrypi.org/documentation/configuration/config-txt/README.md +# https://www.raspberrypi.com/documentation/computers/config_txt.html ################################################################################ # OpenWrt config diff --git a/target/linux/bcm27xx/image/distroconfig.txt b/target/linux/bcm27xx/image/distroconfig.txt index 103c5d2e82..b09e5b8466 100644 --- a/target/linux/bcm27xx/image/distroconfig.txt +++ b/target/linux/bcm27xx/image/distroconfig.txt @@ -5,7 +5,7 @@ # Restore PL011 (ttyAMA0) to GPIOs 14 & 15, instead of Mini UART (ttyS0). # Mini UART is disabled by default unless "enable_uart=1" is specified, # which changes the core frequency to a fixed value and impacts performance. -# See https://www.raspberrypi.org/documentation/configuration/uart.md +# See https://www.raspberrypi.com/documentation/computers/configuration.html#mini-uart-and-cpu-core-frequency [pi0w] dtoverlay=disable-bt [pi3] From 90644fb2d004112c3d877abd94cd5528d7587ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Thu, 18 Jan 2024 10:50:45 +0100 Subject: [PATCH 152/222] bcm27xx-utils: update to latest version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes build with GCC 13. Disable LTO to fix build with CONFIG_USE_LTO. Changelog: e65f5ec eeptools: eepdump: init type before calling eepio_atom_start Signed-off-by: Álvaro Fernández Rojas --- package/utils/bcm27xx-utils/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package/utils/bcm27xx-utils/Makefile b/package/utils/bcm27xx-utils/Makefile index ca8c3969c6..ec41b70c30 100644 --- a/package/utils/bcm27xx-utils/Makefile +++ b/package/utils/bcm27xx-utils/Makefile @@ -3,15 +3,16 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bcm27xx-utils -PKG_VERSION:=2024-01-15 +PKG_VERSION:=2024-01-18 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/raspberrypi/utils.git -PKG_SOURCE_VERSION:=32602f565c6cb854d1f2643b51a022991cea2b1b -PKG_MIRROR_HASH:=efbfa0f1aabbe9ecb347c3a27629fb757f67ff283c8d3b1ee7376ddc6925127b +PKG_SOURCE_VERSION:=e65f5ec102e74218cda7da9fdc8b1caa0fd1127d +PKG_MIRROR_HASH:=14f4aa1a8115240d702251bc399b53cbfa0928813f70a73ca27b22da94b696d2 PKG_FLAGS:=nonshared +PKG_BUILD_FLAGS:=no-lto PKG_LICENSE:=BSD-3-Clause PKG_LICENSE_FILES:=LICENCE From 56d7887917102877ed2f03414f7ed812a29d6b39 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Thu, 18 Jan 2024 22:47:17 +0100 Subject: [PATCH 153/222] hostapd: ACS: Fix typo in bw_40 frequency array [Upstream Backport] The range for the 5 GHz channel 118 was encoded with an incorrect channel number. Fixes: ed8e13decc71 (ACS: Extract bw40/80/160 freqs out of acs_usable_bwXXX_chan()) Signed-off-by: Michael Lee Signed-off-by: David Bauer --- ...CS-Fix-typo-in-bw_40-frequency-array.patch | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 package/network/services/hostapd/patches/993-2023-10-28-ACS-Fix-typo-in-bw_40-frequency-array.patch diff --git a/package/network/services/hostapd/patches/993-2023-10-28-ACS-Fix-typo-in-bw_40-frequency-array.patch b/package/network/services/hostapd/patches/993-2023-10-28-ACS-Fix-typo-in-bw_40-frequency-array.patch new file mode 100644 index 0000000000..948c51b196 --- /dev/null +++ b/package/network/services/hostapd/patches/993-2023-10-28-ACS-Fix-typo-in-bw_40-frequency-array.patch @@ -0,0 +1,25 @@ +From 7a733993211ad46cf3032038c1e7e6bdc2322336 Mon Sep 17 00:00:00 2001 +From: Michael-CY Lee +Date: Tue, 5 Sep 2023 09:43:25 +0800 +Subject: [PATCH] ACS: Fix typo in bw_40 frequency array + +The range for the 5 GHz channel 118 was encoded with an incorrect +channel number. + +Fixes: ed8e13decc71 (ACS: Extract bw40/80/160 freqs out of acs_usable_bwXXX_chan()) +Signed-off-by: Michael Lee +--- + src/ap/acs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/src/ap/acs.c ++++ b/src/ap/acs.c +@@ -256,7 +256,7 @@ struct bw_item { + static const struct bw_item bw_40[] = { + { 5180, 5200, 38 }, { 5220, 5240, 46 }, { 5260, 5280, 54 }, + { 5300, 5320, 62 }, { 5500, 5520, 102 }, { 5540, 5560, 110 }, +- { 5580, 5600, 110 }, { 5620, 5640, 126}, { 5660, 5680, 134 }, ++ { 5580, 5600, 118 }, { 5620, 5640, 126 }, { 5660, 5680, 134 }, + { 5700, 5720, 142 }, { 5745, 5765, 151 }, { 5785, 5805, 159 }, + { 5825, 5845, 167 }, { 5865, 5885, 175 }, + { 5955, 5975, 3 }, { 5995, 6015, 11 }, { 6035, 6055, 19 }, From a28cedbdab96be9bee39bb70098a1508c0252a8a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 18 Jan 2024 20:53:04 +0100 Subject: [PATCH 154/222] mt76: update to Git HEAD (2024-01-18) 83e3947e2c52 linux-firmware: update firmware for MT7922 WiFi device ddaa8cb6e81a linux-firmware: update firmware for MT7921 WiFi device f83b1601cc10 linux-firmware: update firmware for MT7922 WiFi device 61d334ab0f33 linux-firmware: add firmware for MT7925 a7836e4c8a60 wifi: mt76: disable HW AMSDU when using fixed rate a8571ebbcd95 wifi: mt76: check txs format before getting skb by pid 3d5890e2cab3 wifi: mt76: mt7915: fix error recovery with WED enabled 703c26d01197 wifi: mt76: mt7915: add locking for accessing mapped registers f77188160441 wifi: mt76: mt7915: update mt798x_wmac_adie_patch_7976 Signed-off-by: Felix Fietkau --- package/kernel/mt76/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index 65f6ca1e8e..1fea3bd0e9 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2023-12-18 -PKG_SOURCE_VERSION:=bebd9cffc2aeb2cecb40aadbb8c6eab3bdf7971b -PKG_MIRROR_HASH:=580261755bc3f251b8bc5f7f610274693c067432187570694d2f2ccab0edb62b +PKG_SOURCE_DATE:=2024-01-18 +PKG_SOURCE_VERSION:=f77188160441d5f77f08dd517632ae3f60c653b0 +PKG_MIRROR_HASH:=133a5e44624fe1933c893ee0b8ac75a847753f3490c26518c2ed9798f9ef53e0 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 From 2c5b3bee38eb0d76f5afe90f9969b73e19d28685 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 19 Jan 2024 14:48:05 +0100 Subject: [PATCH 155/222] mediatek: fix WED + wifi reset The WLAN + WED reset sequence relies on being able to receive interrupts from the card, in order to synchronize individual steps with the firmware. When WED is stopped, leave interrupts running and rely on the driver turning off unwanted ones. WED DMA also needs to be disabled before resetting. Signed-off-by: Felix Fietkau --- ...ernet-mtk_eth_soc-fix-WED-wifi-reset.patch | 49 +++++++++++++++++++ ...ernet-mtk_eth_soc-fix-WED-wifi-reset.patch | 49 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 target/linux/mediatek/patches-5.15/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch create mode 100644 target/linux/mediatek/patches-6.1/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch diff --git a/target/linux/mediatek/patches-5.15/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch b/target/linux/mediatek/patches-5.15/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch new file mode 100644 index 0000000000..11b52d07ab --- /dev/null +++ b/target/linux/mediatek/patches-5.15/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch @@ -0,0 +1,49 @@ +From: Felix Fietkau +Date: Thu, 18 Jan 2024 12:51:32 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix WED + wifi reset + +The WLAN + WED reset sequence relies on being able to receive interrupts from +the card, in order to synchronize individual steps with the firmware. +When WED is stopped, leave interrupts running and rely on the driver turning +off unwanted ones. +WED DMA also needs to be disabled before resetting. + +Fixes: f78cd9c783e0 ("net: ethernet: mtk_wed: update mtk_wed_stop") +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -1071,13 +1071,13 @@ mtk_wed_dma_disable(struct mtk_wed_devic + static void + mtk_wed_stop(struct mtk_wed_device *dev) + { ++ mtk_wed_dma_disable(dev); + mtk_wed_set_ext_int(dev, false); + + wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0); + wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0); + wdma_w32(dev, MTK_WDMA_INT_MASK, 0); + wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); +- wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); + + if (!mtk_wed_get_rx_capa(dev)) + return; +@@ -1090,7 +1090,6 @@ static void + mtk_wed_deinit(struct mtk_wed_device *dev) + { + mtk_wed_stop(dev); +- mtk_wed_dma_disable(dev); + + wed_clr(dev, MTK_WED_CTRL, + MTK_WED_CTRL_WDMA_INT_AGENT_EN | +@@ -2621,9 +2620,6 @@ mtk_wed_irq_get(struct mtk_wed_device *d + static void + mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask) + { +- if (!dev->running) +- return; +- + mtk_wed_set_ext_int(dev, !!mask); + wed_w32(dev, MTK_WED_INT_MASK, mask); + } diff --git a/target/linux/mediatek/patches-6.1/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch b/target/linux/mediatek/patches-6.1/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch new file mode 100644 index 0000000000..11b52d07ab --- /dev/null +++ b/target/linux/mediatek/patches-6.1/963-net-ethernet-mtk_eth_soc-fix-WED-wifi-reset.patch @@ -0,0 +1,49 @@ +From: Felix Fietkau +Date: Thu, 18 Jan 2024 12:51:32 +0100 +Subject: [PATCH] net: ethernet: mtk_eth_soc: fix WED + wifi reset + +The WLAN + WED reset sequence relies on being able to receive interrupts from +the card, in order to synchronize individual steps with the firmware. +When WED is stopped, leave interrupts running and rely on the driver turning +off unwanted ones. +WED DMA also needs to be disabled before resetting. + +Fixes: f78cd9c783e0 ("net: ethernet: mtk_wed: update mtk_wed_stop") +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/ethernet/mediatek/mtk_wed.c ++++ b/drivers/net/ethernet/mediatek/mtk_wed.c +@@ -1071,13 +1071,13 @@ mtk_wed_dma_disable(struct mtk_wed_devic + static void + mtk_wed_stop(struct mtk_wed_device *dev) + { ++ mtk_wed_dma_disable(dev); + mtk_wed_set_ext_int(dev, false); + + wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0); + wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0); + wdma_w32(dev, MTK_WDMA_INT_MASK, 0); + wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); +- wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); + + if (!mtk_wed_get_rx_capa(dev)) + return; +@@ -1090,7 +1090,6 @@ static void + mtk_wed_deinit(struct mtk_wed_device *dev) + { + mtk_wed_stop(dev); +- mtk_wed_dma_disable(dev); + + wed_clr(dev, MTK_WED_CTRL, + MTK_WED_CTRL_WDMA_INT_AGENT_EN | +@@ -2621,9 +2620,6 @@ mtk_wed_irq_get(struct mtk_wed_device *d + static void + mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask) + { +- if (!dev->running) +- return; +- + mtk_wed_set_ext_int(dev, !!mask); + wed_w32(dev, MTK_WED_INT_MASK, mask); + } From ff413129f93f3b2f5aff178ff811f280103257cc Mon Sep 17 00:00:00 2001 From: John Audia Date: Wed, 10 Jan 2024 15:54:42 -0500 Subject: [PATCH 156/222] kernel: bump 6.1 to 6.1.72 Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.1.72 Manually rebased: generic/hack-6.1/650-netfilter-add-xt_FLOWOFFLOAD-target.patch All other patches automatically rebased. Build system: x86/64 Build-tested: x86/64/AMD Cezanne Run-tested: x86/64/AMD Cezanne Signed-off-by: John Audia --- include/kernel-6.1 | 4 +-- ...a2-eth-don-t-use-ENOTSUPP-error-code.patch | 2 +- ...sorb-phylink_start-call-into-dpaa2_m.patch | 4 +-- ...sign-priv-mac-after-dpaa2_mac_connec.patch | 6 ++--- ...nnect-to-MAC-before-requesting-the-e.patch | 10 +++---- ...rialize-changes-to-priv-mac-with-a-m.patch | 26 +++++++++---------- ...c-move-rtnl_lock-only-around-phylink.patch | 6 ++--- .../900-unaligned_access_hacks.patch | 2 +- ...111-MMC-added-alternative-MMC-driver.patch | 6 ++--- ...Better-coalescing-parameter-defaults.patch | 4 +-- ...t-Workaround-2-for-Pi4-Ethernet-fail.patch | 2 +- ...7-Support-for-the-Sony-IMX477-sensor.patch | 2 +- ...9-Support-for-the-Sony-IMX519-sensor.patch | 2 +- ...vicetree-Add-documentation-for-imx37.patch | 2 +- ...et-bcmgenet-Reset-RBUF-on-first-open.patch | 8 +++--- ...do-single-sector-reads-during-recove.patch | 2 +- ...et-bcmgenet-Add-eee-module-parameter.patch | 2 +- ...a-i2c-Add-IMX708-CMOS-sensor-binding.patch | 2 +- ...a-i2c-Add-IMX296-CMOS-sensor-binding.patch | 2 +- ...edia-i2c-IMX296-camera-sensor-driver.patch | 2 +- ...-bindings-Convert-imx290.txt-to-YAML.patch | 2 +- ...a-i2c-Replace-IMX708-sensor-binding-.patch | 2 +- ...cs-add-driver-for-MediaTek-SGMII-PCS.patch | 2 +- ...t7530-introduce-separate-MDIO-driver.patch | 2 +- ...ntroduce-driver-for-MT7988-built-in-.patch | 2 +- ...or-Motorcomm-yt8521-gigabit-ethernet.patch | 2 +- ...-netfilter-add-xt_FLOWOFFLOAD-target.patch | 6 ++--- .../hack-6.1/901-debloat_sock_diag.patch | 2 +- .../generic/hack-6.1/902-debloat_proc.patch | 2 +- ...ow_offload-handle-netdevice-events-f.patch | 6 ++--- ...introduce-the-Qualcomm-IPQESS-driver.patch | 2 +- ...dsa-add-out-of-band-tagging-protocol.patch | 2 +- ...er-for-MediaTek-SoC-built-in-GE-PHYs.patch | 2 +- 33 files changed, 65 insertions(+), 65 deletions(-) diff --git a/include/kernel-6.1 b/include/kernel-6.1 index c52b94712f..836cecf7de 100644 --- a/include/kernel-6.1 +++ b/include/kernel-6.1 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.1 = .71 -LINUX_KERNEL_HASH-6.1.71 = 2df774dd53f9ffd4e57ebf804cf597709295df6a304fe261d25220a134b7f041 +LINUX_VERSION-6.1 = .72 +LINUX_KERNEL_HASH-6.1.72 = 98dce69077c35cffca799dcdbbd32a02242aad6b0950eb931936bb2ef69f0926 diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0001-net-dpaa2-eth-don-t-use-ENOTSUPP-error-code.patch b/target/linux/armsr/patches-6.1/701-v6.2-0001-net-dpaa2-eth-don-t-use-ENOTSUPP-error-code.patch index 2c70b44f4b..ec72f91d0f 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0001-net-dpaa2-eth-don-t-use-ENOTSUPP-error-code.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0001-net-dpaa2-eth-don-t-use-ENOTSUPP-error-code.patch @@ -22,7 +22,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -3611,7 +3611,7 @@ static int dpaa2_eth_setup_dpni(struct f +@@ -3614,7 +3614,7 @@ static int dpaa2_eth_setup_dpni(struct f dev_err(dev, "DPNI version %u.%u not supported, need >= %u.%u\n", priv->dpni_ver_major, priv->dpni_ver_minor, DPNI_VER_MAJOR, DPNI_VER_MINOR); diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0003-net-dpaa2-mac-absorb-phylink_start-call-into-dpaa2_m.patch b/target/linux/armsr/patches-6.1/701-v6.2-0003-net-dpaa2-mac-absorb-phylink_start-call-into-dpaa2_m.patch index c47598749c..af5ff2aea6 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0003-net-dpaa2-mac-absorb-phylink_start-call-into-dpaa2_m.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0003-net-dpaa2-mac-absorb-phylink_start-call-into-dpaa2_m.patch @@ -21,7 +21,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -2080,10 +2080,8 @@ static int dpaa2_eth_open(struct net_dev +@@ -2083,10 +2083,8 @@ static int dpaa2_eth_open(struct net_dev goto enable_err; } @@ -33,7 +33,7 @@ Signed-off-by: Paolo Abeni return 0; -@@ -2157,7 +2155,6 @@ static int dpaa2_eth_stop(struct net_dev +@@ -2160,7 +2158,6 @@ static int dpaa2_eth_stop(struct net_dev int retries = 10; if (dpaa2_eth_is_type_phy(priv)) { diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0005-net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch b/target/linux/armsr/patches-6.1/701-v6.2-0005-net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch index 45f07decc9..c31a470182 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0005-net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0005-net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch @@ -49,7 +49,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -4441,9 +4441,8 @@ static int dpaa2_eth_connect_mac(struct +@@ -4444,9 +4444,8 @@ static int dpaa2_eth_connect_mac(struct err = dpaa2_mac_open(mac); if (err) goto err_free_mac; @@ -60,7 +60,7 @@ Signed-off-by: Paolo Abeni err = dpaa2_mac_connect(mac); if (err && err != -EPROBE_DEFER) netdev_err(priv->net_dev, "Error connecting to the MAC endpoint: %pe", -@@ -4452,11 +4451,12 @@ static int dpaa2_eth_connect_mac(struct +@@ -4455,11 +4454,12 @@ static int dpaa2_eth_connect_mac(struct goto err_close_mac; } @@ -74,7 +74,7 @@ Signed-off-by: Paolo Abeni err_free_mac: kfree(mac); return err; -@@ -4464,15 +4464,18 @@ err_free_mac: +@@ -4467,15 +4467,18 @@ err_free_mac: static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) { diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0009-net-dpaa2-eth-connect-to-MAC-before-requesting-the-e.patch b/target/linux/armsr/patches-6.1/701-v6.2-0009-net-dpaa2-eth-connect-to-MAC-before-requesting-the-e.patch index 7c394c55db..4e39e9a0ac 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0009-net-dpaa2-eth-connect-to-MAC-before-requesting-the-e.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0009-net-dpaa2-eth-connect-to-MAC-before-requesting-the-e.patch @@ -33,7 +33,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -4708,6 +4708,10 @@ static int dpaa2_eth_probe(struct fsl_mc +@@ -4711,6 +4711,10 @@ static int dpaa2_eth_probe(struct fsl_mc } #endif @@ -44,7 +44,7 @@ Signed-off-by: Paolo Abeni err = dpaa2_eth_setup_irqs(dpni_dev); if (err) { netdev_warn(net_dev, "Failed to set link interrupt, fall back to polling\n"); -@@ -4720,10 +4724,6 @@ static int dpaa2_eth_probe(struct fsl_mc +@@ -4723,10 +4727,6 @@ static int dpaa2_eth_probe(struct fsl_mc priv->do_link_poll = true; } @@ -55,7 +55,7 @@ Signed-off-by: Paolo Abeni err = dpaa2_eth_dl_alloc(priv); if (err) goto err_dl_register; -@@ -4759,13 +4759,13 @@ err_dl_port_add: +@@ -4762,13 +4762,13 @@ err_dl_port_add: err_dl_trap_register: dpaa2_eth_dl_free(priv); err_dl_register: @@ -71,7 +71,7 @@ Signed-off-by: Paolo Abeni dpaa2_eth_free_rings(priv); err_alloc_rings: err_csum: -@@ -4813,9 +4813,6 @@ static int dpaa2_eth_remove(struct fsl_m +@@ -4816,9 +4816,6 @@ static int dpaa2_eth_remove(struct fsl_m #endif unregister_netdev(net_dev); @@ -81,7 +81,7 @@ Signed-off-by: Paolo Abeni dpaa2_eth_dl_port_del(priv); dpaa2_eth_dl_traps_unregister(priv); -@@ -4826,6 +4823,9 @@ static int dpaa2_eth_remove(struct fsl_m +@@ -4829,6 +4826,9 @@ static int dpaa2_eth_remove(struct fsl_m else fsl_mc_free_irqs(ls_dev); diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0010-net-dpaa2-eth-serialize-changes-to-priv-mac-with-a-m.patch b/target/linux/armsr/patches-6.1/701-v6.2-0010-net-dpaa2-eth-serialize-changes-to-priv-mac-with-a-m.patch index 28ffe2288c..9b068ce8f5 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0010-net-dpaa2-eth-serialize-changes-to-priv-mac-with-a-m.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0010-net-dpaa2-eth-serialize-changes-to-priv-mac-with-a-m.patch @@ -41,7 +41,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -2018,8 +2018,11 @@ static int dpaa2_eth_link_state_update(s +@@ -2021,8 +2021,11 @@ static int dpaa2_eth_link_state_update(s /* When we manage the MAC/PHY using phylink there is no need * to manually update the netif_carrier. @@ -54,7 +54,7 @@ Signed-off-by: Paolo Abeni goto out; /* Chech link state; speed / duplex changes are not treated yet */ -@@ -2058,6 +2061,8 @@ static int dpaa2_eth_open(struct net_dev +@@ -2061,6 +2064,8 @@ static int dpaa2_eth_open(struct net_dev priv->dpbp_dev->obj_desc.id, priv->bpid); } @@ -63,7 +63,7 @@ Signed-off-by: Paolo Abeni if (!dpaa2_eth_is_type_phy(priv)) { /* We'll only start the txqs when the link is actually ready; * make sure we don't race against the link up notification, -@@ -2076,6 +2081,7 @@ static int dpaa2_eth_open(struct net_dev +@@ -2079,6 +2084,7 @@ static int dpaa2_eth_open(struct net_dev err = dpni_enable(priv->mc_io, 0, priv->mc_token); if (err < 0) { @@ -71,7 +71,7 @@ Signed-off-by: Paolo Abeni netdev_err(net_dev, "dpni_enable() failed\n"); goto enable_err; } -@@ -2083,6 +2089,8 @@ static int dpaa2_eth_open(struct net_dev +@@ -2086,6 +2092,8 @@ static int dpaa2_eth_open(struct net_dev if (dpaa2_eth_is_type_phy(priv)) dpaa2_mac_start(priv->mac); @@ -80,7 +80,7 @@ Signed-off-by: Paolo Abeni return 0; enable_err: -@@ -2154,6 +2162,8 @@ static int dpaa2_eth_stop(struct net_dev +@@ -2157,6 +2165,8 @@ static int dpaa2_eth_stop(struct net_dev int dpni_enabled = 0; int retries = 10; @@ -89,7 +89,7 @@ Signed-off-by: Paolo Abeni if (dpaa2_eth_is_type_phy(priv)) { dpaa2_mac_stop(priv->mac); } else { -@@ -2161,6 +2171,8 @@ static int dpaa2_eth_stop(struct net_dev +@@ -2164,6 +2174,8 @@ static int dpaa2_eth_stop(struct net_dev netif_carrier_off(net_dev); } @@ -98,7 +98,7 @@ Signed-off-by: Paolo Abeni /* On dpni_disable(), the MC firmware will: * - stop MAC Rx and wait for all Rx frames to be enqueued to software * - cut off WRIOP dequeues from egress FQs and wait until transmission -@@ -2486,12 +2498,20 @@ static int dpaa2_eth_ts_ioctl(struct net +@@ -2489,12 +2501,20 @@ static int dpaa2_eth_ts_ioctl(struct net static int dpaa2_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct dpaa2_eth_priv *priv = netdev_priv(dev); @@ -121,7 +121,7 @@ Signed-off-by: Paolo Abeni return -EOPNOTSUPP; } -@@ -4451,7 +4471,9 @@ static int dpaa2_eth_connect_mac(struct +@@ -4454,7 +4474,9 @@ static int dpaa2_eth_connect_mac(struct goto err_close_mac; } @@ -131,7 +131,7 @@ Signed-off-by: Paolo Abeni return 0; -@@ -4464,9 +4486,12 @@ err_free_mac: +@@ -4467,9 +4489,12 @@ err_free_mac: static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) { @@ -145,7 +145,7 @@ Signed-off-by: Paolo Abeni if (!mac) return; -@@ -4485,6 +4510,7 @@ static irqreturn_t dpni_irq0_handler_thr +@@ -4488,6 +4513,7 @@ static irqreturn_t dpni_irq0_handler_thr struct fsl_mc_device *dpni_dev = to_fsl_mc_device(dev); struct net_device *net_dev = dev_get_drvdata(dev); struct dpaa2_eth_priv *priv = netdev_priv(net_dev); @@ -153,7 +153,7 @@ Signed-off-by: Paolo Abeni int err; err = dpni_get_irq_status(dpni_dev->mc_io, 0, dpni_dev->mc_handle, -@@ -4502,7 +4528,12 @@ static irqreturn_t dpni_irq0_handler_thr +@@ -4505,7 +4531,12 @@ static irqreturn_t dpni_irq0_handler_thr dpaa2_eth_update_tx_fqids(priv); rtnl_lock(); @@ -167,7 +167,7 @@ Signed-off-by: Paolo Abeni dpaa2_eth_disconnect_mac(priv); else dpaa2_eth_connect_mac(priv); -@@ -4603,6 +4634,8 @@ static int dpaa2_eth_probe(struct fsl_mc +@@ -4606,6 +4637,8 @@ static int dpaa2_eth_probe(struct fsl_mc priv = netdev_priv(net_dev); priv->net_dev = net_dev; @@ -305,7 +305,7 @@ Signed-off-by: Paolo Abeni if (pause->autoneg) return -EOPNOTSUPP; -@@ -309,8 +341,12 @@ static void dpaa2_eth_get_ethtool_stats( +@@ -307,8 +339,12 @@ static void dpaa2_eth_get_ethtool_stats( } *(data + i++) = buf_cnt; diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0012-net-dpaa2-mac-move-rtnl_lock-only-around-phylink.patch b/target/linux/armsr/patches-6.1/701-v6.2-0012-net-dpaa2-mac-move-rtnl_lock-only-around-phylink.patch index f72f9e3a43..521c9d4a54 100644 --- a/target/linux/armsr/patches-6.1/701-v6.2-0012-net-dpaa2-mac-move-rtnl_lock-only-around-phylink.patch +++ b/target/linux/armsr/patches-6.1/701-v6.2-0012-net-dpaa2-mac-move-rtnl_lock-only-around-phylink.patch @@ -34,7 +34,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c -@@ -4527,7 +4527,6 @@ static irqreturn_t dpni_irq0_handler_thr +@@ -4530,7 +4530,6 @@ static irqreturn_t dpni_irq0_handler_thr dpaa2_eth_set_mac_addr(netdev_priv(net_dev)); dpaa2_eth_update_tx_fqids(priv); @@ -42,7 +42,7 @@ Signed-off-by: Paolo Abeni /* We can avoid locking because the "endpoint changed" IRQ * handler is the only one who changes priv->mac at runtime, * so we are not racing with anyone. -@@ -4537,7 +4536,6 @@ static irqreturn_t dpni_irq0_handler_thr +@@ -4540,7 +4539,6 @@ static irqreturn_t dpni_irq0_handler_thr dpaa2_eth_disconnect_mac(priv); else dpaa2_eth_connect_mac(priv); @@ -50,7 +50,7 @@ Signed-off-by: Paolo Abeni } return IRQ_HANDLED; -@@ -4856,9 +4854,7 @@ static int dpaa2_eth_remove(struct fsl_m +@@ -4859,9 +4857,7 @@ static int dpaa2_eth_remove(struct fsl_m else fsl_mc_free_irqs(ls_dev); diff --git a/target/linux/ath79/patches-6.1/900-unaligned_access_hacks.patch b/target/linux/ath79/patches-6.1/900-unaligned_access_hacks.patch index 1a2d4426ab..2235c28fd9 100644 --- a/target/linux/ath79/patches-6.1/900-unaligned_access_hacks.patch +++ b/target/linux/ath79/patches-6.1/900-unaligned_access_hacks.patch @@ -336,7 +336,7 @@ SVN-Revision: 35130 #endif /* _LINUX_TYPES_H */ --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c -@@ -1494,8 +1494,8 @@ struct sk_buff *inet_gro_receive(struct +@@ -1512,8 +1512,8 @@ struct sk_buff *inet_gro_receive(struct if (unlikely(ip_fast_csum((u8 *)iph, 5))) goto out; diff --git a/target/linux/bcm27xx/patches-6.1/950-0111-MMC-added-alternative-MMC-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0111-MMC-added-alternative-MMC-driver.patch index a74b2cd62f..09402fbc35 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0111-MMC-added-alternative-MMC-driver.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0111-MMC-added-alternative-MMC-driver.patch @@ -266,7 +266,7 @@ Signed-off-by: Phil Elwell static inline int mmc_blk_part_switch(struct mmc_card *card, unsigned int part_type); static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, -@@ -2998,6 +3005,8 @@ static int mmc_blk_probe(struct mmc_card +@@ -3000,6 +3007,8 @@ static int mmc_blk_probe(struct mmc_card { struct mmc_blk_data *md; int ret = 0; @@ -275,7 +275,7 @@ Signed-off-by: Phil Elwell /* * Check that the card supports the command class(es) we need. -@@ -3005,7 +3014,16 @@ static int mmc_blk_probe(struct mmc_card +@@ -3007,7 +3016,16 @@ static int mmc_blk_probe(struct mmc_card if (!(card->csd.cmdclass & CCC_BLOCK_READ)) return -ENODEV; @@ -293,7 +293,7 @@ Signed-off-by: Phil Elwell card->complete_wq = alloc_workqueue("mmc_complete", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); -@@ -3020,6 +3038,17 @@ static int mmc_blk_probe(struct mmc_card +@@ -3022,6 +3040,17 @@ static int mmc_blk_probe(struct mmc_card goto out_free; } diff --git a/target/linux/bcm27xx/patches-6.1/950-0179-bcmgenet-Better-coalescing-parameter-defaults.patch b/target/linux/bcm27xx/patches-6.1/950-0179-bcmgenet-Better-coalescing-parameter-defaults.patch index 4fc97de544..b805f1df30 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0179-bcmgenet-Better-coalescing-parameter-defaults.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0179-bcmgenet-Better-coalescing-parameter-defaults.patch @@ -18,7 +18,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c -@@ -2657,7 +2657,7 @@ static void bcmgenet_init_tx_ring(struct +@@ -2659,7 +2659,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX); bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX); @@ -27,7 +27,7 @@ Signed-off-by: Phil Elwell /* Disable rate control for now */ bcmgenet_tdma_ring_writel(priv, index, flow_period_val, TDMA_FLOW_PERIOD); -@@ -4138,9 +4138,12 @@ static int bcmgenet_probe(struct platfor +@@ -4140,9 +4140,12 @@ static int bcmgenet_probe(struct platfor netif_set_real_num_rx_queues(priv->dev, priv->hw_params->rx_queues + 1); /* Set default coalescing parameters */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0189-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch b/target/linux/bcm27xx/patches-6.1/950-0189-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch index ba1baac7d0..da60efe07f 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0189-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0189-net-bcmgenet-Workaround-2-for-Pi4-Ethernet-fail.patch @@ -37,7 +37,7 @@ Signed-off-by: Phil Elwell static inline void bcmgenet_writel(u32 value, void __iomem *offset) { -@@ -2488,6 +2491,11 @@ static void reset_umac(struct bcmgenet_p +@@ -2490,6 +2493,11 @@ static void reset_umac(struct bcmgenet_p bcmgenet_rbuf_ctrl_set(priv, 0); udelay(10); diff --git a/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch b/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch index dc2e539f3a..89d7b4eea9 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0195-media-i2c-imx477-Support-for-the-Sony-IMX477-sensor.patch @@ -343,7 +343,7 @@ Signed-off-by: Naushir Patuck +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19279,6 +19279,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19281,6 +19281,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml F: drivers/media/i2c/imx412.c diff --git a/target/linux/bcm27xx/patches-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch b/target/linux/bcm27xx/patches-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch index 8ba6f7e5fc..a7cf1bb1f2 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0196-media-i2c-imx519-Support-for-the-Sony-IMX519-sensor.patch @@ -177,7 +177,7 @@ Signed-off-by: Phil Elwell +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19287,6 +19287,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19289,6 +19289,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/imx477.yaml F: drivers/media/i2c/imx477.c diff --git a/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch b/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch index e564af578e..03628b3e9f 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0197-Documentation-devicetree-Add-documentation-for-imx37.patch @@ -132,7 +132,7 @@ Signed-off-by: David Plowman +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19284,6 +19284,7 @@ M: Raspberry Pi Kernel Maintenance --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c -@@ -3304,7 +3304,7 @@ static void bcmgenet_get_hw_addr(struct +@@ -3306,7 +3306,7 @@ static void bcmgenet_get_hw_addr(struct } /* Returns a reusable dma control register value */ @@ -33,7 +33,7 @@ Signed-off-by: Phil Elwell { unsigned int i; u32 reg; -@@ -3329,6 +3329,14 @@ static u32 bcmgenet_dma_disable(struct b +@@ -3331,6 +3331,14 @@ static u32 bcmgenet_dma_disable(struct b udelay(10); bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH); @@ -48,7 +48,7 @@ Signed-off-by: Phil Elwell return dma_ctrl; } -@@ -3392,8 +3400,8 @@ static int bcmgenet_open(struct net_devi +@@ -3394,8 +3402,8 @@ static int bcmgenet_open(struct net_devi bcmgenet_set_hw_addr(priv, dev->dev_addr); @@ -59,7 +59,7 @@ Signed-off-by: Phil Elwell /* Reinitialize TDMA and RDMA and SW housekeeping */ ret = bcmgenet_init_dma(priv); -@@ -4267,7 +4275,7 @@ static int bcmgenet_resume(struct device +@@ -4269,7 +4277,7 @@ static int bcmgenet_resume(struct device bcmgenet_hfb_create_rxnfc_filter(priv, rule); /* Disable RX/TX DMA and flush TX queues */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0418-mmc-block-Don-t-do-single-sector-reads-during-recove.patch b/target/linux/bcm27xx/patches-6.1/950-0418-mmc-block-Don-t-do-single-sector-reads-during-recove.patch index de9378f79a..0335f00198 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0418-mmc-block-Don-t-do-single-sector-reads-during-recove.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0418-mmc-block-Don-t-do-single-sector-reads-during-recove.patch @@ -23,7 +23,7 @@ Signed-off-by: Jonathan Bell --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c -@@ -1928,7 +1928,7 @@ static void mmc_blk_mq_rw_recovery(struc +@@ -1930,7 +1930,7 @@ static void mmc_blk_mq_rw_recovery(struc return; } diff --git a/target/linux/bcm27xx/patches-6.1/950-0513-net-bcmgenet-Add-eee-module-parameter.patch b/target/linux/bcm27xx/patches-6.1/950-0513-net-bcmgenet-Add-eee-module-parameter.patch index a145f6c48f..cd9820fc9d 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0513-net-bcmgenet-Add-eee-module-parameter.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0513-net-bcmgenet-Add-eee-module-parameter.patch @@ -26,7 +26,7 @@ Signed-off-by: Phil Elwell static inline void bcmgenet_writel(u32 value, void __iomem *offset) { -@@ -3438,6 +3441,17 @@ static int bcmgenet_open(struct net_devi +@@ -3440,6 +3443,17 @@ static int bcmgenet_open(struct net_devi bcmgenet_phy_pause_set(dev, priv->rx_pause, priv->tx_pause); diff --git a/target/linux/bcm27xx/patches-6.1/950-0528-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch b/target/linux/bcm27xx/patches-6.1/950-0528-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch index 2e6188af4b..6e51500140 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0528-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0528-dtbindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch @@ -138,7 +138,7 @@ Signed-off-by: Dave Stevenson +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19328,6 +19328,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19330,6 +19330,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/imx519.yaml F: drivers/media/i2c/imx519.c diff --git a/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch b/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch index cfdeef78ab..4d6227a378 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0593-dt-bindings-media-i2c-Add-IMX296-CMOS-sensor-binding.patch @@ -128,7 +128,7 @@ Signed-off-by: Sakari Ailus +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19270,6 +19270,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -19272,6 +19272,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/imx290.txt F: drivers/media/i2c/imx290.c diff --git a/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch index 94ddb850c3..de983ddb15 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0594-media-i2c-IMX296-camera-sensor-driver.patch @@ -23,7 +23,7 @@ Signed-off-by: Sakari Ailus --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19277,6 +19277,7 @@ L: linux-media@vger.kernel.org +@@ -19279,6 +19279,7 @@ L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/sony,imx296.yaml diff --git a/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch b/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch index 14a8a4a029..374069eca5 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0649-media-dt-bindings-Convert-imx290.txt-to-YAML.patch @@ -219,7 +219,7 @@ Signed-off-by: Sakari Ailus +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19267,7 +19267,7 @@ M: Manivannan Sadhasivam +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -19342,7 +19342,7 @@ M: Raspberry Pi Kernel Maintenance --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -12926,6 +12926,14 @@ L: netdev@vger.kernel.org +@@ -12928,6 +12928,14 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/mediatek/ diff --git a/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch b/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch index b75710ba57..d203711884 100644 --- a/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch +++ b/target/linux/generic/backport-6.1/790-v6.4-0010-net-dsa-mt7530-introduce-separate-MDIO-driver.patch @@ -25,7 +25,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -13060,6 +13060,7 @@ M: Landen Chao L: netdev@vger.kernel.org S: Maintained diff --git a/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch b/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch index 934af995cd..63bf0e77fa 100644 --- a/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch +++ b/target/linux/generic/backport-6.1/790-v6.4-0012-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch @@ -28,7 +28,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -13058,9 +13058,11 @@ MEDIATEK SWITCH DRIVER +@@ -13060,9 +13060,11 @@ MEDIATEK SWITCH DRIVER M: Sean Wang M: Landen Chao M: DENG Qingfang diff --git a/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch b/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch index 06dddffcaa..4cdd67cdcc 100644 --- a/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch +++ b/target/linux/generic/backport-6.1/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch @@ -21,7 +21,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -13962,6 +13962,7 @@ F: include/uapi/linux/meye.h +@@ -13964,6 +13964,7 @@ F: include/uapi/linux/meye.h MOTORCOMM PHY DRIVER M: Peter Geis diff --git a/target/linux/generic/hack-6.1/650-netfilter-add-xt_FLOWOFFLOAD-target.patch b/target/linux/generic/hack-6.1/650-netfilter-add-xt_FLOWOFFLOAD-target.patch index 386291bfe8..9ff45a414e 100644 --- a/target/linux/generic/hack-6.1/650-netfilter-add-xt_FLOWOFFLOAD-target.patch +++ b/target/linux/generic/hack-6.1/650-netfilter-add-xt_FLOWOFFLOAD-target.patch @@ -654,7 +654,7 @@ Signed-off-by: Felix Fietkau +}; + +static int nf_flow_rule_route_inet(struct net *net, -+ const struct flow_offload *flow, ++ struct flow_offload *flow, + enum flow_offload_tuple_dir dir, + struct nf_flow_rule *flow_rule) +{ @@ -755,7 +755,7 @@ Signed-off-by: Felix Fietkau void (*iter)(struct nf_flowtable *flowtable, struct flow_offload *flow, void *data), void *data) -@@ -436,6 +434,7 @@ static void nf_flow_offload_gc_step(stru +@@ -443,6 +441,7 @@ static void nf_flow_offload_gc_step(stru nf_flow_offload_stats(flow_table, flow); } } @@ -785,7 +785,7 @@ Signed-off-by: Felix Fietkau +#endif /* _XT_FLOWOFFLOAD_H */ --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h -@@ -280,6 +280,11 @@ void nf_flow_table_free(struct nf_flowta +@@ -293,6 +293,11 @@ void nf_flow_table_free(struct nf_flowta void flow_offload_teardown(struct flow_offload *flow); diff --git a/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch b/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch index b4403e82c8..ffa6e8ac60 100644 --- a/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-6.1/901-debloat_sock_diag.patch @@ -79,7 +79,7 @@ Signed-off-by: Felix Fietkau INDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *, u32)); INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, -@@ -2180,9 +2194,11 @@ static void __sk_free(struct sock *sk) +@@ -2187,9 +2201,11 @@ static void __sk_free(struct sock *sk) if (likely(sk->sk_net_refcnt)) sock_inuse_add(sock_net(sk), -1); diff --git a/target/linux/generic/hack-6.1/902-debloat_proc.patch b/target/linux/generic/hack-6.1/902-debloat_proc.patch index a5db9b21c1..0d844994aa 100644 --- a/target/linux/generic/hack-6.1/902-debloat_proc.patch +++ b/target/linux/generic/hack-6.1/902-debloat_proc.patch @@ -330,7 +330,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -4105,6 +4105,8 @@ static __net_initdata struct pernet_oper +@@ -4113,6 +4113,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { diff --git a/target/linux/generic/pending-6.1/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/pending-6.1/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch index 6050db3f5b..47c742cff0 100644 --- a/target/linux/generic/pending-6.1/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch +++ b/target/linux/generic/pending-6.1/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch @@ -10,7 +10,7 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c -@@ -659,6 +659,23 @@ static struct pernet_operations nf_flow_ +@@ -666,6 +666,23 @@ static struct pernet_operations nf_flow_ .exit_batch = nf_flow_table_pernet_exit, }; @@ -34,7 +34,7 @@ Signed-off-by: Pablo Neira Ayuso static int __init nf_flow_table_module_init(void) { int ret; -@@ -671,8 +688,14 @@ static int __init nf_flow_table_module_i +@@ -678,8 +695,14 @@ static int __init nf_flow_table_module_i if (ret) goto out_offload; @@ -49,7 +49,7 @@ Signed-off-by: Pablo Neira Ayuso out_offload: unregister_pernet_subsys(&nf_flow_table_net_ops); return ret; -@@ -680,6 +703,7 @@ out_offload: +@@ -687,6 +710,7 @@ out_offload: static void __exit nf_flow_table_module_exit(void) { diff --git a/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch b/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch index ccc56d115e..a3d8bf0488 100644 --- a/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch +++ b/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch @@ -32,7 +32,7 @@ Signed-off-by: Maxime Chevallier --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -17064,6 +17064,13 @@ L: netdev@vger.kernel.org +@@ -17066,6 +17066,13 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/qualcomm/emac/ diff --git a/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch b/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch index ecf1a05896..7961c9978b 100644 --- a/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch +++ b/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch @@ -64,7 +64,7 @@ Signed-off-by: Maxime Chevallier --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -17070,6 +17070,7 @@ L: netdev@vger.kernel.org +@@ -17072,6 +17072,7 @@ L: netdev@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/net/qcom,ipq4019-ess-edma.yaml F: drivers/net/ethernet/qualcomm/ipqess/ diff --git a/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch b/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch index 389b2e4c99..f4e972f658 100644 --- a/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch +++ b/target/linux/mediatek/patches-6.1/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch @@ -24,7 +24,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -12934,6 +12934,15 @@ S: Maintained +@@ -12936,6 +12936,15 @@ S: Maintained F: drivers/net/pcs/pcs-mtk-lynxi.c F: include/linux/pcs/pcs-mtk-lynxi.h From cc022082e97de93ca40b212e0f163a0e04c77608 Mon Sep 17 00:00:00 2001 From: John Audia Date: Mon, 15 Jan 2024 14:39:17 -0500 Subject: [PATCH 157/222] kernel: bump 6.1 to 6.1.73 Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.1.73 Patch automatically rebased. Build system: x86/64 Build-tested: x86/64/AMD Cezanne, filogic/xiaomi_redmi-router-ax6000-ubootmod Run-tested: x86/64/AMD Cezanne, filogic/xiaomi_redmi-router-ax6000-ubootmod Signed-off-by: John Audia --- include/kernel-6.1 | 4 ++-- ...ing-with-source-address-failed-policy.patch | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/kernel-6.1 b/include/kernel-6.1 index 836cecf7de..fde32f3ca3 100644 --- a/include/kernel-6.1 +++ b/include/kernel-6.1 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.1 = .72 -LINUX_KERNEL_HASH-6.1.72 = 98dce69077c35cffca799dcdbbd32a02242aad6b0950eb931936bb2ef69f0926 +LINUX_VERSION-6.1 = .73 +LINUX_KERNEL_HASH-6.1.73 = 6cad48706bf1cde342613dca2a2cd6dd4f79f88f9e4d356263564e4b2a5d7e87 diff --git a/target/linux/generic/pending-6.1/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-6.1/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index 003a0f20ac..72e8de2f1d 100644 --- a/target/linux/generic/pending-6.1/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-6.1/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -157,7 +157,7 @@ Signed-off-by: Jonas Gorski case RTN_THROW: case RTN_UNREACHABLE: default: -@@ -4543,6 +4562,17 @@ static int ip6_pkt_prohibit_out(struct n +@@ -4540,6 +4559,17 @@ static int ip6_pkt_prohibit_out(struct n return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); } @@ -175,7 +175,7 @@ Signed-off-by: Jonas Gorski /* * Allocate a dst for local (unicast / anycast) address. */ -@@ -5036,7 +5066,8 @@ static int rtm_to_fib6_config(struct sk_ +@@ -5033,7 +5063,8 @@ static int rtm_to_fib6_config(struct sk_ if (rtm->rtm_type == RTN_UNREACHABLE || rtm->rtm_type == RTN_BLACKHOLE || rtm->rtm_type == RTN_PROHIBIT || @@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -6290,6 +6321,8 @@ static int ip6_route_dev_notify(struct n +@@ -6287,6 +6318,8 @@ static int ip6_route_dev_notify(struct n #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.ip6_prohibit_entry->dst.dev = dev; net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); @@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); #endif -@@ -6301,6 +6334,7 @@ static int ip6_route_dev_notify(struct n +@@ -6298,6 +6331,7 @@ static int ip6_route_dev_notify(struct n in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); #ifdef CONFIG_IPV6_MULTIPLE_TABLES in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); @@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); #endif } -@@ -6492,6 +6526,8 @@ static int __net_init ip6_route_net_init +@@ -6489,6 +6523,8 @@ static int __net_init ip6_route_net_init #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.fib6_has_custom_rules = false; @@ -211,7 +211,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, sizeof(*net->ipv6.ip6_prohibit_entry), GFP_KERNEL); -@@ -6502,11 +6538,21 @@ static int __net_init ip6_route_net_init +@@ -6499,11 +6535,21 @@ static int __net_init ip6_route_net_init ip6_template_metrics, true); INIT_LIST_HEAD(&net->ipv6.ip6_prohibit_entry->rt6i_uncached); @@ -234,7 +234,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ip6_template_metrics, true); -@@ -6533,6 +6579,8 @@ out: +@@ -6530,6 +6576,8 @@ out: return ret; #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -243,7 +243,7 @@ Signed-off-by: Jonas Gorski out_ip6_prohibit_entry: kfree(net->ipv6.ip6_prohibit_entry); out_ip6_null_entry: -@@ -6552,6 +6600,7 @@ static void __net_exit ip6_route_net_exi +@@ -6549,6 +6597,7 @@ static void __net_exit ip6_route_net_exi kfree(net->ipv6.ip6_null_entry); #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); @@ -251,7 +251,7 @@ Signed-off-by: Jonas Gorski kfree(net->ipv6.ip6_blk_hole_entry); #endif dst_entries_destroy(&net->ipv6.ip6_dst_ops); -@@ -6635,6 +6684,9 @@ void __init ip6_route_init_special_entri +@@ -6632,6 +6681,9 @@ void __init ip6_route_init_special_entri init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); From 869f8b21e755e752e6e0bbec1750810751c54b72 Mon Sep 17 00:00:00 2001 From: Cedric DOURLENT Date: Fri, 12 Jan 2024 09:23:46 +0100 Subject: [PATCH 158/222] build: add option for building with stack-protector-all The GCC option -fstack-protector-all is a security feature used to protect against stack-smashing attacks. This option enhances the stack-smashing protection provided by -fstack-protector-strong. -fstack-protector-all option applies stack protection to all functions, regardless of their characteristics. While this offers the most comprehensive protection against stack-smashing attacks, it can significantly impact the performance of the program because every function call includes additional checks for stack integrity. This option can incur a performance penalty because of the extra checks added to every function call, but it significantly enhances security, making it harder for attackers to exploit buffer overflows to execute arbitrary code. It's particularly useful in scenarios where security is paramount and performance trade-offs are acceptable. Signed-off-by: Cedric DOURLENT --- config/Config-build.in | 2 ++ include/hardening.mk | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/config/Config-build.in b/config/Config-build.in index ebfce8add4..24c2bcf130 100644 --- a/config/Config-build.in +++ b/config/Config-build.in @@ -293,6 +293,8 @@ menu "Global build settings" bool "Regular" config PKG_CC_STACKPROTECTOR_STRONG bool "Strong" + config PKG_CC_STACKPROTECTOR_ALL + bool "All" endchoice choice diff --git a/include/hardening.mk b/include/hardening.mk index 6acd862f5c..4a8874261b 100644 --- a/include/hardening.mk +++ b/include/hardening.mk @@ -36,6 +36,11 @@ ifdef CONFIG_PKG_CC_STACKPROTECTOR_STRONG TARGET_CFLAGS += -fstack-protector-strong endif endif +ifdef CONFIG_PKG_CC_STACKPROTECTOR_ALL + ifeq ($(strip $(PKG_SSP)),1) + TARGET_CFLAGS += -fstack-protector-all + endif +endif ifdef CONFIG_PKG_FORTIFY_SOURCE_1 ifeq ($(strip $(PKG_FORTIFY_SOURCE)),1) TARGET_CFLAGS += -D_FORTIFY_SOURCE=1 From 34fd41a99784b5d0f281d3c7053ec27f0dedca39 Mon Sep 17 00:00:00 2001 From: Cedric DOURLENT Date: Thu, 18 Jan 2024 10:17:21 +0100 Subject: [PATCH 159/222] toolchain: glibc: add --enable-stack-protector=all option for glibc Add missing configurition for glibc based on CONFIG_PKG_CC_STACKPROTECTOR_ALL Signed-off-by: Cedric DOURLENT --- toolchain/glibc/common.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/toolchain/glibc/common.mk b/toolchain/glibc/common.mk index 18413cd271..6b237f5478 100644 --- a/toolchain/glibc/common.mk +++ b/toolchain/glibc/common.mk @@ -64,6 +64,7 @@ GLIBC_CONFIGURE:= \ --$(if $(CONFIG_SOFT_FLOAT),without,with)-fp \ $(if $(CONFIG_PKG_CC_STACKPROTECTOR_REGULAR),--enable-stack-protector=yes) \ $(if $(CONFIG_PKG_CC_STACKPROTECTOR_STRONG),--enable-stack-protector=strong) \ + $(if $(CONFIG_PKG_CC_STACKPROTECTOR_ALL),--enable-stack-protector=all) \ $(if $(CONFIG_PKG_RELRO_FULL),--enable-bind-now) \ --enable-kernel=5.15.0 From 4d49ce1bde84fdd83f0e9df5ec9c43f4ff2a0a9a Mon Sep 17 00:00:00 2001 From: Justin Klaassen Date: Sat, 13 Jan 2024 20:28:57 +0000 Subject: [PATCH 160/222] rockchip: fix boot from non-MMC devices Booting from non-MMC devices on Rockchip targets without this change results in a boot failure: Model: FriendlyElec NanoPi R5S Net: eth0: ethernet@fe2a0000 Hit any key to stop autoboot: 0 ** Booting bootflow 'nvme#0.blk#1.bootdev.part_1' with script ** No partition table - mmc 0 ** ** No partition table - mmc 0 ** Couldn't find partition mmc 0:1 Can't set block device Wrong Image Type for bootm command ERROR -91: Protocol wrong type for socket: can't get kernel image! Boot failed (err=1) This change fixes the default boot script for Rockchip targets to support booting from non-MMC devices such as NVMe or USB drives. Some targets with only a boot rom (e.g. NanoPi R5S) may require u-boot to be installed on the eMMC or a MicroSD card in order to boot from non-MMC devices. Fixes: #14420 Reviewed-by: Tianling Shen Signed-off-by: Justin Klaassen --- target/linux/rockchip/image/Makefile | 2 +- .../rockchip/image/{mmc.bootscript => default.bootscript} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename target/linux/rockchip/image/{mmc.bootscript => default.bootscript} (80%) diff --git a/target/linux/rockchip/image/Makefile b/target/linux/rockchip/image/Makefile index d34948f6ae..5de053bdb6 100644 --- a/target/linux/rockchip/image/Makefile +++ b/target/linux/rockchip/image/Makefile @@ -21,7 +21,7 @@ endef define Build/boot-script # Make an U-boot image and copy it to the boot partition - mkimage -A arm -O linux -T script -C none -a 0 -e 0 -d $(if $(1),$(1),mmc).bootscript $@.boot/boot.scr + mkimage -A arm -O linux -T script -C none -a 0 -e 0 -d $(if $(1),$(1),default).bootscript $@.boot/boot.scr endef define Build/pine64-img diff --git a/target/linux/rockchip/image/mmc.bootscript b/target/linux/rockchip/image/default.bootscript similarity index 80% rename from target/linux/rockchip/image/mmc.bootscript rename to target/linux/rockchip/image/default.bootscript index 60b59e1b6b..e9de14ff7a 100644 --- a/target/linux/rockchip/image/mmc.bootscript +++ b/target/linux/rockchip/image/default.bootscript @@ -1,4 +1,4 @@ -part uuid mmc ${devnum}:2 uuid +part uuid ${devtype} ${devnum}:2 uuid if test $stdout = 'serial@fe660000' ; then serial_addr=',0xfe660000'; @@ -10,6 +10,6 @@ fi; setenv bootargs "console=ttyS2,1500000 console=tty1 earlycon=uart8250,mmio32${serial_addr} swiotlb=1 root=PARTUUID=${uuid} rw rootwait"; -load mmc ${devnum}:1 ${kernel_addr_r} kernel.img +load ${devtype} ${devnum}:1 ${kernel_addr_r} kernel.img bootm ${kernel_addr_r} From 6fa4fbbc5293886aa6bae6e0cac4b99a4c472fc4 Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Wed, 1 Nov 2023 14:44:50 +0800 Subject: [PATCH 161/222] uboot-mediatek: add support for JDCloud RE-CP-03 The vendor U-Boot has enabled signature verification, so add a custom U-Boot build for OpenWrt. Signed-off-by: Tianling Shen --- package/boot/uboot-mediatek/Makefile | 13 + .../patches/440-add-jdcloud_re-cp-03.patch | 324 ++++++++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 package/boot/uboot-mediatek/patches/440-add-jdcloud_re-cp-03.patch diff --git a/package/boot/uboot-mediatek/Makefile b/package/boot/uboot-mediatek/Makefile index 37fb68be22..8c0419f90c 100644 --- a/package/boot/uboot-mediatek/Makefile +++ b/package/boot/uboot-mediatek/Makefile @@ -419,6 +419,18 @@ define U-Boot/mt7986_glinet_gl-mt6000 DEPENDS:=+trusted-firmware-a-mt7986-emmc-ddr4 endef +define U-Boot/mt7986_jdcloud_re-cp-03 + NAME:=JDCloud RE-CP-03 + BUILD_SUBTARGET:=filogic + BUILD_DEVICES:=jdcloud_re-cp-03 + UBOOT_CONFIG:=mt7986a_jdcloud_re-cp-03 + UBOOT_IMAGE:=u-boot.fip + BL2_BOOTDEV:=emmc + BL2_SOC:=mt7986 + BL2_DDRTYPE:=ddr4 + DEPENDS:=+trusted-firmware-a-mt7986-emmc-ddr4 +endef + define U-Boot/mt7986_tplink_tl-xdr4288 NAME:=TP-LINK TL-XDR4288 BUILD_SUBTARGET:=filogic @@ -575,6 +587,7 @@ UBOOT_TARGETS := \ mt7986_bananapi_bpi-r3-snand \ mt7986_bananapi_bpi-r3-nor \ mt7986_glinet_gl-mt6000 \ + mt7986_jdcloud_re-cp-03 \ mt7986_tplink_tl-xdr4288 \ mt7986_tplink_tl-xdr6086 \ mt7986_tplink_tl-xdr6088 \ diff --git a/package/boot/uboot-mediatek/patches/440-add-jdcloud_re-cp-03.patch b/package/boot/uboot-mediatek/patches/440-add-jdcloud_re-cp-03.patch new file mode 100644 index 0000000000..e0f3a6e235 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/440-add-jdcloud_re-cp-03.patch @@ -0,0 +1,324 @@ +--- /dev/null ++++ b/configs/mt7986a_jdcloud_re-cp-03_defconfig +@@ -0,0 +1,112 @@ ++CONFIG_ARM=y ++CONFIG_SYS_HAS_NONCACHED_MEMORY=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_ENV_SIZE=0x40000 ++CONFIG_ENV_OFFSET=0x400000 ++CONFIG_DEFAULT_DEVICE_TREE="mt7986a-jdcloud_re-cp-03" ++CONFIG_SYS_PROMPT="MT7986> " ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_TARGET_MT7986=y ++CONFIG_PRE_CON_BUF_ADDR=0x4007EF00 ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_ENV_OFFSET_REDUND=0x440000 ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_DEBUG_UART=y ++CONFIG_FIT=y ++CONFIG_BOOTDELAY=30 ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_DEFAULT_FDT_FILE="mediatek/mt7986a-jdcloud_re-cp-03.dtb" ++CONFIG_LOGLEVEL=7 ++CONFIG_PRE_CONSOLE_BUFFER=y ++CONFIG_LOG=y ++CONFIG_BOARD_LATE_INIT=y ++CONFIG_HUSH_PARSER=y ++CONFIG_CMD_CPU=y ++CONFIG_CMD_LICENSE=y ++CONFIG_CMD_BOOTMENU=y ++CONFIG_CMD_ASKENV=y ++CONFIG_CMD_ERASEENV=y ++CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_STRINGS=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_PWM=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_LINK_LOCAL=y ++CONFIG_CMD_PXE=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_PSTORE=y ++CONFIG_CMD_PSTORE_MEM_ADDR=0x42ff0000 ++CONFIG_CMD_UUID=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_EXT4=y ++CONFIG_CMD_FAT=y ++CONFIG_CMD_FS_GENERIC=y ++CONFIG_CMD_FS_UUID=y ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_SYS_REDUNDAND_ENVIRONMENT=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_USE_DEFAULT_ENV_FILE=y ++CONFIG_DEFAULT_ENV_FILE="jdcloud_re-cp-03_env" ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_VERSION_VARIABLE=y ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_NETCONSOLE=y ++CONFIG_USE_IPADDR=y ++CONFIG_IPADDR="192.168.1.1" ++CONFIG_USE_SERVERIP=y ++CONFIG_SERVERIP="192.168.1.254" ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_BUTTON=y ++CONFIG_BUTTON_GPIO=y ++CONFIG_CLK=y ++CONFIG_GPIO_HOG=y ++CONFIG_LED=y ++CONFIG_LED_BLINK=y ++CONFIG_LED_GPIO=y ++CONFIG_SUPPORT_EMMC_BOOT=y ++CONFIG_MMC_HS200_SUPPORT=y ++CONFIG_MMC_MTK=y ++CONFIG_PHY_FIXED=y ++CONFIG_DM_MDIO=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PHY=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7622=y ++CONFIG_PINCTRL_MT7986=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_DM_PWM=y ++CONFIG_PWM_MTK=y ++CONFIG_RAM=y ++CONFIG_SCSI=y ++CONFIG_DM_SCSI=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_ZSTD=y ++CONFIG_HEXDUMP=y ++CONFIG_LMB_MAX_REGIONS=64 +--- /dev/null ++++ b/arch/arm/dts/mt7986a-jdcloud_re-cp-03.dts +@@ -0,0 +1,148 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++/dts-v1/; ++#include ++#include "mt7986.dtsi" ++#include ++ ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ model = "JDCloud RE-CP-03"; ++ compatible = "mediatek,mt7986", "mediatek,mt7986-rfb"; ++ ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x40000000>; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ button-joylink { ++ label = "joylink"; ++ linux,code = ; ++ gpios = <&gpio 10 GPIO_ACTIVE_LOW>; ++ }; ++ ++ button-reset { ++ label = "reset"; ++ linux,code = ; ++ gpios = <&gpio 9 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ led-0 { ++ label = "blue:status"; ++ gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ ++ led-1 { ++ label = "red:status"; ++ gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led-2 { ++ label = "green:status"; ++ gpios = <&gpio 12 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ }; ++ }; ++ ++ reg_1p8v: regulator-1p8v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ reg_3p3v: regulator-3p3v { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "2500base-x"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <2500>; ++ full-duplex; ++ }; ++}; ++ ++&mmc0 { ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ cap-mmc-hw-reset; ++ max-frequency = <200000000>; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_default>; ++ vmmc-supply = <®_3p3v>; ++ vqmmc-supply = <®_1p8v>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ mmc0_pins_default: mmc0default { ++ mux { ++ function = "flash"; ++ groups = "emmc_51"; ++ }; ++ ++ conf-cmd-dat { ++ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", ++ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", ++ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; ++ input-enable; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-clk { ++ pins = "EMMC_CK"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ ++ conf-dsl { ++ pins = "EMMC_DSL"; ++ bias-pull-down = ; ++ }; ++ ++ conf-rst { ++ pins = "EMMC_RSTB"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; +--- /dev/null ++++ b/jdcloud_re-cp-03_env +@@ -0,0 +1,55 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x46000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootargs=root=/dev/mmcblk0p65 ++bootcmd=if pstore check ; then run boot_recovery ; else run boot_emmc ; fi ++bootconf=config-1 ++bootdelay=0 ++bootfile=openwrt-mediatek-filogic-jdcloud_re-cp-03-initramfs-recovery.itb ++bootfile_bl2=openwrt-mediatek-filogic-jdcloud_re-cp-03-preloader.bin ++bootfile_fip=openwrt-mediatek-filogic-jdcloud_re-cp-03-bl31-uboot.fip ++bootfile_upg=openwrt-mediatek-filogic-jdcloud_re-cp-03-squashfs-sysupgrade.itb ++bootled_pwr=red:status ++bootled_rec=blue:status ++bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60 ++bootmenu_default=0 ++bootmenu_delay=0 ++bootmenu_title= ( ( ( OpenWrt ) ) ) ++bootmenu_0=Initialize environment.=run _firstboot ++bootmenu_0d=Run default boot command.=run boot_default ++bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return ++bootmenu_2=Boot production system from eMMC.=run boot_production ; run bootmenu_confirm_return ++bootmenu_3=Boot recovery system from eMMC.=run boot_recovery ; run bootmenu_confirm_return ++bootmenu_4=Load production system via TFTP then write to eMMC.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_5=Load recovery system via TFTP then write to eMMC.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_recovery ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_6=Load BL31+U-Boot FIP via TFTP then write to eMMC.=run boot_tftp_write_fip ; run bootmenu_confirm_return ++bootmenu_7=Load BL2 preloader via TFTP then write to eMMC.=run boot_tftp_write_bl2 ; run bootmenu_confirm_return ++bootmenu_8=Reboot.=reset ++bootmenu_9=Reset all settings to factory defaults.=run reset_factory ; reset ++boot_first=if button reset ; then led $bootled_rec on ; run boot_tftp_recovery ; setenv flag_recover 1 ; run boot_default ; fi ; bootmenu ++boot_default=if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_forever ++boot_production=led $bootled_pwr on ; run emmc_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off ++boot_recovery=led $bootled_rec on ; run emmc_read_recovery && bootm $loadaddr#$bootconf ; led $bootled_rec off ++boot_emmc=run boot_production ; run boot_recovery ++boot_tftp_forever=led $bootled_rec on ; while true ; do run boot_tftp_recovery ; sleep 1 ; done ++boot_tftp_production=tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run emmc_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_recovery=tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run emmc_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run emmc_write_fip ++boot_tftp_write_bl2=tftpboot $loadaddr $bootfile_bl2 && run emmc_write_bl2 ++boot_tftp=tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++mmc_write_vol=imszb $loadaddr image_size && test 0x$image_size -le 0x$part_size && mmc erase 0x$part_addr 0x$image_size && mmc write $loadaddr 0x$part_addr 0x$image_size ++mmc_read_vol=mmc read $loadaddr $part_addr 0x100 && imszb $loadaddr image_size && test 0x$image_size -le 0x$part_size && mmc read $loadaddr 0x$part_addr 0x$image_size && setexpr filesize $image_size * 0x200 ++part_default=production ++part_recovery=recovery ++reset_factory=eraseenv && reset ++emmc_read_production=part start mmc 0 $part_default part_addr && part size mmc 0 $part_default part_size && run mmc_read_vol ++emmc_read_recovery=part start mmc 0 $part_recovery part_addr && part size mmc 0 $part_recovery part_size && run mmc_read_vol ++emmc_write_bl2=mmc partconf 0 1 1 1 && mmc erase 0x0 0x400 && mmc write $fileaddr 0x0 0x400 ; mmc partconf 0 1 1 0 ++emmc_write_fip=mmc erase 0x3400 0x2000 && mmc write $fileaddr 0x3400 0x2000 && mmc erase 0x2000 0x800 ++emmc_write_production=part start mmc 0 $part_default part_addr && part size mmc 0 $part_default part_size && run mmc_write_vol ++emmc_write_recovery=part start mmc 0 $part_recovery part_addr && part size mmc 0 $part_recovery part_size && run mmc_write_vol ++_init_env=setenv _init_env ; setenv _create_env ; saveenv ; saveenv ++_firstboot=setenv _firstboot ; run _switch_to_menu ; run _init_env ; run boot_first ++_switch_to_menu=setenv _switch_to_menu ; setenv bootdelay 3 ; setenv bootmenu_delay 3 ; setenv bootmenu_0 $bootmenu_0d ; setenv bootmenu_0d ; run _bootmenu_update_title ++_bootmenu_update_title=setenv _bootmenu_update_title ; setenv bootmenu_title "$bootmenu_title $ver" From c0c3234e17207a9287a08757fc1752490144a1cd Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Wed, 1 Nov 2023 14:46:15 +0800 Subject: [PATCH 162/222] mediatek: add support for JDCloud RE-CP-03 Hardware specification: SoC: MediaTek MT7986A 4x A53 Flash: 128GB eMMC RAM: 1GB DDR4 Ethernet: 4x 1GbE, 1x 2.5GbE (RTL8221B) Switch: MediaTek MT7531AE WiFi: MediaTek MT7976C Button: Reset, Joylink Power: DC 12V 2A Flash instructions: 1. Download and flash the vendor migration firmware via webUI: https://firmware.download.immortalwrt.eu.org/cnsztl/mediatek/filogic/openwrt-mediatek-mt7986-jdcloud_re-cp-03-vendor-migration.bin (Default address is 192.168.68.1, user root, no password) 2. After device has booted up, write new GPT table: dd if=openwrt-mediatek-filogic-jdcloud_re-cp-03-gpt.bin of=/dev/mmcblk0 bs=512 seek=0 count=34 conv=fsync 3. Erase and write new BL2: echo 0 > /sys/block/mmcblk0boot0/force_ro dd if=/dev/zero of=/dev/mmcblk0boot0 bs=512 count=8192 conv=fsync dd if=openwrt-mediatek-filogic-jdcloud_re-cp-03-preloader.bin of=/dev/mmcblk0boot0 bs=512 conv=fsync 4. Erase and write new FIP: dd if=/dev/zero of=/dev/mmcblk0 bs=512 seek=13312 count=8192 conv=fsync dd if=openwrt-mediatek-filogic-jdcloud_re-cp-03-bl31-uboot.fip of=/dev/mmcblk0 bs=512 seek=13312 conv=fsync 5. Set static IP on your PC: IP 192.168.1.254/24, GW 192.168.1.1 6. Serve OpenWrt initramfs image using TFTP server. 7. Cut off the power and re-engage, wait for TFTP recovery to complete. 8. After OpenWrt has booted, perform sysupgrade. 9. Additionally, if you want to have eMMC recovery boot feature: (Don't worry! You will always have TFTP recovery boot feature.) dd if=openwrt-mediatek-filogic-jdcloud_re-cp-03-initramfs-recovery.itb of=/dev/mmcblk0p4 bs=512 conv=fsync Signed-off-by: Tianling Shen --- .../uboot-envtools/files/mediatek_filogic | 5 + .../mediatek/dts/mt7986a-jdcloud-re-cp-03.dts | 294 ++++++++++++++++++ .../filogic/base-files/etc/board.d/02_network | 6 + .../etc/hotplug.d/firmware/11-mt76-caldata | 3 +- .../etc/hotplug.d/ieee80211/11_fix_wifi_mac | 3 + .../base-files/lib/upgrade/platform.sh | 5 + target/linux/mediatek/image/filogic.mk | 26 ++ 7 files changed, 341 insertions(+), 1 deletion(-) create mode 100644 target/linux/mediatek/dts/mt7986a-jdcloud-re-cp-03.dts diff --git a/package/boot/uboot-envtools/files/mediatek_filogic b/package/boot/uboot-envtools/files/mediatek_filogic index 1e7b42b634..cae761b4f9 100644 --- a/package/boot/uboot-envtools/files/mediatek_filogic +++ b/package/boot/uboot-envtools/files/mediatek_filogic @@ -87,6 +87,11 @@ glinet,gl-mt6000) glinet,gl-mt3000) ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x80000" "0x20000" ;; +jdcloud,re-cp-03) + local envdev=$(find_mmc_part "ubootenv" "mmcblk0") + ubootenv_add_uci_config "$envdev" "0x0" "0x40000" "0x40000" "1" + ubootenv_add_uci_config "$envdev" "0x40000" "0x40000" "0x40000" "1" + ;; mercusys,mr90x-v1|\ routerich,ax3000) local envdev=/dev/mtd$(find_mtd_index "u-boot-env") diff --git a/target/linux/mediatek/dts/mt7986a-jdcloud-re-cp-03.dts b/target/linux/mediatek/dts/mt7986a-jdcloud-re-cp-03.dts new file mode 100644 index 0000000000..b62c2f4215 --- /dev/null +++ b/target/linux/mediatek/dts/mt7986a-jdcloud-re-cp-03.dts @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (C) 2023 Tianling Shen + */ + +/dts-v1/; +#include +#include +#include + +#include "mt7986a.dtsi" + +/ { + model = "JDCloud RE-CP-03"; + compatible = "jdcloud,re-cp-03", "mediatek,mt7986a"; + + aliases { + led-boot = &red_led; + led-failsafe = &red_led; + led-running = &green_led; + led-upgrade = &green_led; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@40000000 { + reg = <0 0x40000000 0 0x40000000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-joylink { + label = "joylink"; + linux,code = ; + gpios = <&pio 10 GPIO_ACTIVE_LOW>; + }; + + button-reset { + label = "reset"; + linux,code = ; + gpios = <&pio 9 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + led-0 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 7 GPIO_ACTIVE_HIGH>; + }; + + red_led: led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 11 GPIO_ACTIVE_HIGH>; + }; + + green_led: led-2 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&pio 12 GPIO_ACTIVE_LOW>; + }; + }; + + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&crypto { + status = "okay"; +}; + +ð { + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "2500base-x"; + phy-handle = <&phy6>; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + }; +}; + +&mdio { + phy6: phy@6 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <6>; + + reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <50000>; + realtek,aldps-enable; + }; + + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 5 GPIO_ACTIVE_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&mmc0 { + bus-width = <8>; + cap-mmc-highspeed; + hs400-ds-delay = <0x14014>; + max-frequency = <200000000>; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + no-sd; + no-sdio; + non-removable; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + vmmc-supply = <®_3p3v>; + vqmmc-supply = <®_1p8v>; + status = "okay"; +}; + +&pio { + mmc0_pins_default: mmc0-pins-default { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + }; + + mmc0_pins_uhs: mmc0-uhs-pins { + mux { + function = "emmc"; + groups = "emmc_51"; + }; + conf-cmd-dat { + pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2", + "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5", + "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD"; + input-enable; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + conf-clk { + pins = "EMMC_CK"; + drive-strength = <6>; + mediatek,pull-down-adv = <2>; + }; + conf-ds { + pins = "EMMC_DSL"; + mediatek,pull-down-adv = <2>; + }; + conf-rst { + pins = "EMMC_RSTB"; + drive-strength = <4>; + mediatek,pull-up-adv = <1>; + }; + }; + + wf_2g_5g_pins: wf-2g-5g-pins { + mux { + function = "wifi"; + groups = "wf_2g", "wf_5g"; + }; + conf { + pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4", + "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6", + "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10", + "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1", + "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0", + "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8", + "WF1_TOP_CLK", "WF1_TOP_DATA"; + drive-strength = <4>; + }; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + label = "lan1"; + }; + + port@2 { + reg = <2>; + label = "lan2"; + }; + + port@3 { + reg = <3>; + label = "lan3"; + }; + + port@4 { + reg = <4>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&trng { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi { + pinctrl-names = "default"; + pinctrl-0 = <&wf_2g_5g_pins>; + status = "okay"; +}; diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network index b86c376d74..47e7be971e 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network @@ -24,6 +24,7 @@ mediatek_setup_interfaces() ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" wan ;; asus,tuf-ax4200|\ + jdcloud,re-cp-03|\ mediatek,mt7981-rfb|\ zbtlink,zbt-z8102ax) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" eth1 @@ -135,6 +136,11 @@ mediatek_setup_macs() lan_mac=$(macaddr_add "$wan_mac" 1) label_mac=$wan_mac ;; + jdcloud,re-cp-03) + wan_mac=$(mmc_get_mac_binary factory 0x2a) + lan_mac=$(mmc_get_mac_binary factory 0x24) + label_mac=$lan_mac + ;; mercusys,mr90x-v1) label_mac=$(get_mac_binary "/tmp/tp_data/default-mac" 0) lan_mac=$label_mac diff --git a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata index cbbf1871a5..22ab26608f 100644 --- a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata +++ b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/firmware/11-mt76-caldata @@ -72,7 +72,8 @@ case "$FIRMWARE" in CI_UBIPART="UBI_DEV" caldata_extract_ubi "Factory" 0x0 0x1000 ;; - glinet,gl-mt6000) + glinet,gl-mt6000|\ + jdcloud,re-cp-03) caldata_extract_mmc "factory" 0x0 0x1000 ;; esac diff --git a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac index d9e0335b67..937d39066c 100644 --- a/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac +++ b/target/linux/mediatek/filogic/base-files/etc/hotplug.d/ieee80211/11_fix_wifi_mac @@ -80,6 +80,9 @@ case "$board" in # addresses on multiple VIFs with the other radio. Use label mac to set LA bit. [ "$PHYNBR" = "1" ] && macaddr_setbit_la $(get_mac_label) > /sys${DEVPATH}/macaddress ;; + jdcloud,re-cp-03) + [ "$PHYNBR" = "1" ] && mmc_get_mac_binary factory 0xa > /sys${DEVPATH}/macaddress + ;; mercusys,mr90x-v1) addr=$(get_mac_binary "/tmp/tp_data/default-mac" 0) [ "$PHYNBR" = "0" ] && echo "$addr" > /sys${DEVPATH}/macaddress diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index 517f4520e1..97c09f35a8 100755 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -134,6 +134,10 @@ platform_do_upgrade() { CI_KERNPART="fit" nand_do_upgrade "$1" ;; + jdcloud,re-cp-03) + CI_KERNPART="production" + emmc_do_upgrade "$1" + ;; mercusys,mr90x-v1) CI_UBIPART="ubi0" nand_do_upgrade "$1" @@ -200,6 +204,7 @@ platform_copy_config() { acer,predator-w6|\ glinet,gl-mt2500|\ glinet,gl-mt6000|\ + jdcloud,re-cp-03|\ ubnt,unifi-6-plus) emmc_copy_config ;; diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index d0c9907635..8a8879ca32 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -450,6 +450,32 @@ define Device/jcg_q30-pro endef TARGET_DEVICES += jcg_q30-pro +define Device/jdcloud_re-cp-03 + DEVICE_VENDOR := JDCloud + DEVICE_MODEL := RE-CP-03 + DEVICE_DTS := mt7986a-jdcloud-re-cp-03 + DEVICE_DTS_DIR := ../dts + DEVICE_DTC_FLAGS := --pad 4096 + DEVICE_DTS_LOADADDR := 0x43f00000 + DEVICE_PACKAGES := kmod-mt7986-firmware mt7986-wo-firmware \ + e2fsprogs f2fsck mkf2fs + KERNEL_LOADADDR := 0x44000000 + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + IMAGES := sysupgrade.itb + IMAGE_SIZE := $$(shell expr 64 + $$(CONFIG_TARGET_ROOTFS_PARTSIZE))m + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | \ + pad-rootfs | append-metadata + ARTIFACTS :=gpt.bin preloader.bin bl31-uboot.fip + ARTIFACT/gpt.bin := mt798x-gpt emmc + ARTIFACT/preloader.bin := mt7986-bl2 emmc-ddr4 + ARTIFACT/bl31-uboot.fip := mt7986-bl31-uboot jdcloud_re-cp-03 +endef +TARGET_DEVICES += jdcloud_re-cp-03 + define Device/mediatek_mt7981-rfb DEVICE_VENDOR := MediaTek DEVICE_MODEL := MT7981 rfb From ced3fbcda18e200315cb077f7e2b362ae52ee065 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Fri, 19 Jan 2024 21:45:19 +0100 Subject: [PATCH 163/222] ubox: update to Git HEAD (2024-01-15) 11cb29e15d68 kmodloader: remove unneeded uname() call 811ca6c2234a kmodloader: fix memory leak in scan_loaded_modules() 8c95fc7039cb kmodloader: support loadable module parameters in modinfo 4ffc29e4041c kmodloader: add basic support for builtin modules ba3908351232 kmodloader: add modinfo support for builtin modules c006dccecb6f kmodloader: cleanup duplicated mmap() code Signed-off-by: Christian Marangi --- package/system/ubox/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/system/ubox/Makefile b/package/system/ubox/Makefile index ed55617cfa..42987f536b 100644 --- a/package/system/ubox/Makefile +++ b/package/system/ubox/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/ubox.git -PKG_SOURCE_DATE:=2023-11-30 -PKG_SOURCE_VERSION:=c08709cceb554cba02c935d1442f6a042fe6b2a8 -PKG_MIRROR_HASH:=719ae701546df7c5972352d778a980cbc9f48623dda86443398698837124818b +PKG_SOURCE_DATE:=2024-01-15 +PKG_SOURCE_VERSION:=c006dccecb6f1cf694c9fb9efc6727cbd2ab9ae4 +PKG_MIRROR_HASH:=7919d8d6f06fa50342eec805902d17c61d1224d9d35c392d3c5c36fc782a5c75 CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 From 86e3016896f43fdcd1ee34a8aafe92b2dab9367e Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Thu, 18 Jan 2024 16:25:34 +0100 Subject: [PATCH 164/222] busybox: enable sha hash for /etc/shadow It appears `md5` is no longer state of the art. Let's switch it to something slightly newer to increase security. Suggested-by: abnoeh Signed-off-by: Paul Spooren --- package/utils/busybox/Config-defaults.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/utils/busybox/Config-defaults.in b/package/utils/busybox/Config-defaults.in index b3c3f9a0b2..5ae8dd5622 100644 --- a/package/utils/busybox/Config-defaults.in +++ b/package/utils/busybox/Config-defaults.in @@ -1333,7 +1333,7 @@ config BUSYBOX_DEFAULT_USE_BB_CRYPT default n config BUSYBOX_DEFAULT_USE_BB_CRYPT_SHA bool - default n + default y config BUSYBOX_DEFAULT_ADD_SHELL bool default n From 10180295b817abb3efdc9db3fb4bb62d585fad7a Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Fri, 19 Jan 2024 11:49:27 +0100 Subject: [PATCH 165/222] busybox: switch to sha256 for passwd Right now sha256 is considered more secure than md5, use it to harden against password decryption. Signed-off-by: Paul Spooren --- package/utils/busybox/Config-defaults.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/utils/busybox/Config-defaults.in b/package/utils/busybox/Config-defaults.in index 5ae8dd5622..515bea3d1d 100644 --- a/package/utils/busybox/Config-defaults.in +++ b/package/utils/busybox/Config-defaults.in @@ -1366,7 +1366,7 @@ config BUSYBOX_DEFAULT_CHPASSWD default n config BUSYBOX_DEFAULT_FEATURE_DEFAULT_PASSWD_ALGO string - default "md5" + default "sha256" config BUSYBOX_DEFAULT_CRYPTPW bool default n From f1a447bdb5f25a61402f513e68a216a1ae8c7c97 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 20 Jan 2024 00:08:42 +0100 Subject: [PATCH 166/222] uboot-bcm53xx: bump to 2024.01 Bump the U-Boot version used for BCM53xx to the 2024.01 version that includes all the needed patches upstream, so we can get rid of those in the process. Signed-off-by: Linus Walleij --- package/boot/uboot-bcm53xx/Makefile | 4 +- ...0001-nand-brcmnand-add-iproc-support.patch | 199 ------ ...nand_base-Handle-algorithm-selection.patch | 80 --- ...t-device-tree-for-Broadcom-Northstar.patch | 659 ------------------ ...port-for-the-Broadcom-Northstar-SoCs.patch | 66 -- ...ard-Add-new-Broadcom-Northstar-board.patch | 372 ---------- 6 files changed, 2 insertions(+), 1378 deletions(-) delete mode 100644 package/boot/uboot-bcm53xx/patches/0001-nand-brcmnand-add-iproc-support.patch delete mode 100644 package/boot/uboot-bcm53xx/patches/0002-mtd-rawnand-nand_base-Handle-algorithm-selection.patch delete mode 100644 package/boot/uboot-bcm53xx/patches/0003-arm-dts-Import-device-tree-for-Broadcom-Northstar.patch delete mode 100644 package/boot/uboot-bcm53xx/patches/0004-arm-Add-support-for-the-Broadcom-Northstar-SoCs.patch delete mode 100644 package/boot/uboot-bcm53xx/patches/0005-board-Add-new-Broadcom-Northstar-board.patch diff --git a/package/boot/uboot-bcm53xx/Makefile b/package/boot/uboot-bcm53xx/Makefile index ab80b9608a..f1c026e25b 100644 --- a/package/boot/uboot-bcm53xx/Makefile +++ b/package/boot/uboot-bcm53xx/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk -PKG_VERSION:=2023.04 -PKG_HASH:=e31cac91545ff41b71cec5d8c22afd695645cd6e2a442ccdacacd60534069341 +PKG_VERSION:=2024.01 +PKG_HASH:=b99611f1ed237bf3541bdc8434b68c96a6e05967061f992443cb30aabebef5b3 PKG_RELEASE:=$(AUTORELEASE) include $(INCLUDE_DIR)/u-boot.mk diff --git a/package/boot/uboot-bcm53xx/patches/0001-nand-brcmnand-add-iproc-support.patch b/package/boot/uboot-bcm53xx/patches/0001-nand-brcmnand-add-iproc-support.patch deleted file mode 100644 index fe6f4d944a..0000000000 --- a/package/boot/uboot-bcm53xx/patches/0001-nand-brcmnand-add-iproc-support.patch +++ /dev/null @@ -1,199 +0,0 @@ -From 854dc4b790ce1291326d52b8405ebe771bff2edd Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Wed, 8 Mar 2023 22:42:31 +0100 -Subject: [PATCH 1/5] nand: brcmnand: add iproc support - -Add support for the iproc Broadcom NAND controller, -used in Northstar SoCs for example. Based on the Linux -driver. - -Cc: Philippe Reynes -Cc: Dario Binacchi -Reviewed-by: Michael Trimarchi -Signed-off-by: Linus Walleij -Acked-by: William Zhang -Link: https://lore.kernel.org/all/20230308214231.378013-1-linus.walleij@linaro.org/ -Signed-off-by: Dario Binacchi ---- - drivers/mtd/nand/raw/Kconfig | 7 + - drivers/mtd/nand/raw/brcmnand/Makefile | 1 + - drivers/mtd/nand/raw/brcmnand/iproc_nand.c | 148 +++++++++++++++++++++ - 3 files changed, 156 insertions(+) - create mode 100644 drivers/mtd/nand/raw/brcmnand/iproc_nand.c - ---- a/drivers/mtd/nand/raw/Kconfig -+++ b/drivers/mtd/nand/raw/Kconfig -@@ -156,6 +156,13 @@ config NAND_BRCMNAND_63158 - help - Enable support for broadcom nand driver on bcm63158. - -+config NAND_BRCMNAND_IPROC -+ bool "Support Broadcom NAND controller on the iproc family" -+ depends on NAND_BRCMNAND -+ help -+ Enable support for broadcom nand driver on the Broadcom -+ iproc family such as Northstar (BCM5301x, BCM4708...) -+ - config NAND_DAVINCI - bool "Support TI Davinci NAND controller" - select SYS_NAND_SELF_INIT if TARGET_DA850EVM ---- a/drivers/mtd/nand/raw/brcmnand/Makefile -+++ b/drivers/mtd/nand/raw/brcmnand/Makefile -@@ -6,5 +6,6 @@ obj-$(CONFIG_NAND_BRCMNAND_6753) += bcm6 - obj-$(CONFIG_NAND_BRCMNAND_68360) += bcm68360_nand.o - obj-$(CONFIG_NAND_BRCMNAND_6838) += bcm6838_nand.o - obj-$(CONFIG_NAND_BRCMNAND_6858) += bcm6858_nand.o -+obj-$(CONFIG_NAND_BRCMNAND_IPROC) += iproc_nand.o - obj-$(CONFIG_NAND_BRCMNAND) += brcmnand.o - obj-$(CONFIG_NAND_BRCMNAND) += brcmnand_compat.o ---- /dev/null -+++ b/drivers/mtd/nand/raw/brcmnand/iproc_nand.c -@@ -0,0 +1,148 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Code borrowed from the Linux driver -+ * Copyright (C) 2015 Broadcom Corporation -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "brcmnand.h" -+ -+struct iproc_nand_soc { -+ struct brcmnand_soc soc; -+ void __iomem *idm_base; -+ void __iomem *ext_base; -+}; -+ -+#define IPROC_NAND_CTLR_READY_OFFSET 0x10 -+#define IPROC_NAND_CTLR_READY BIT(0) -+ -+#define IPROC_NAND_IO_CTRL_OFFSET 0x00 -+#define IPROC_NAND_APB_LE_MODE BIT(24) -+#define IPROC_NAND_INT_CTRL_READ_ENABLE BIT(6) -+ -+static bool iproc_nand_intc_ack(struct brcmnand_soc *soc) -+{ -+ struct iproc_nand_soc *priv = -+ container_of(soc, struct iproc_nand_soc, soc); -+ void __iomem *mmio = priv->ext_base + IPROC_NAND_CTLR_READY_OFFSET; -+ u32 val = brcmnand_readl(mmio); -+ -+ if (val & IPROC_NAND_CTLR_READY) { -+ brcmnand_writel(IPROC_NAND_CTLR_READY, mmio); -+ return true; -+ } -+ -+ return false; -+} -+ -+static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en) -+{ -+ struct iproc_nand_soc *priv = -+ container_of(soc, struct iproc_nand_soc, soc); -+ void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET; -+ u32 val = brcmnand_readl(mmio); -+ -+ if (en) -+ val |= IPROC_NAND_INT_CTRL_READ_ENABLE; -+ else -+ val &= ~IPROC_NAND_INT_CTRL_READ_ENABLE; -+ -+ brcmnand_writel(val, mmio); -+} -+ -+static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare, -+ bool is_param) -+{ -+ struct iproc_nand_soc *priv = -+ container_of(soc, struct iproc_nand_soc, soc); -+ void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET; -+ u32 val; -+ -+ val = brcmnand_readl(mmio); -+ -+ /* -+ * In the case of BE or when dealing with NAND data, always configure -+ * the APB bus to LE mode before accessing the FIFO and back to BE mode -+ * after the access is done -+ */ -+ if (IS_ENABLED(CONFIG_SYS_BIG_ENDIAN) || !is_param) { -+ if (prepare) -+ val |= IPROC_NAND_APB_LE_MODE; -+ else -+ val &= ~IPROC_NAND_APB_LE_MODE; -+ } else { /* when in LE accessing the parameter page, keep APB in BE */ -+ val &= ~IPROC_NAND_APB_LE_MODE; -+ } -+ -+ brcmnand_writel(val, mmio); -+} -+ -+static int iproc_nand_probe(struct udevice *dev) -+{ -+ struct udevice *pdev = dev; -+ struct iproc_nand_soc *priv = dev_get_priv(dev); -+ struct brcmnand_soc *soc; -+ struct resource res; -+ int ret; -+ -+ soc = &priv->soc; -+ -+ ret = dev_read_resource_byname(pdev, "iproc-idm", &res); -+ if (ret) -+ return ret; -+ -+ priv->idm_base = devm_ioremap(dev, res.start, resource_size(&res)); -+ if (IS_ERR(priv->idm_base)) -+ return PTR_ERR(priv->idm_base); -+ -+ ret = dev_read_resource_byname(pdev, "iproc-ext", &res); -+ if (ret) -+ return ret; -+ -+ priv->ext_base = devm_ioremap(dev, res.start, resource_size(&res)); -+ if (IS_ERR(priv->ext_base)) -+ return PTR_ERR(priv->ext_base); -+ -+ soc->ctlrdy_ack = iproc_nand_intc_ack; -+ soc->ctlrdy_set_enabled = iproc_nand_intc_set; -+ soc->prepare_data_bus = iproc_nand_apb_access; -+ -+ return brcmnand_probe(pdev, soc); -+} -+ -+static const struct udevice_id iproc_nand_dt_ids[] = { -+ { -+ .compatible = "brcm,nand-iproc", -+ }, -+ { /* sentinel */ } -+}; -+ -+U_BOOT_DRIVER(iproc_nand) = { -+ .name = "iproc-nand", -+ .id = UCLASS_MTD, -+ .of_match = iproc_nand_dt_ids, -+ .probe = iproc_nand_probe, -+ .priv_auto = sizeof(struct iproc_nand_soc), -+}; -+ -+void board_nand_init(void) -+{ -+ struct udevice *dev; -+ int ret; -+ -+ ret = uclass_get_device_by_driver(UCLASS_MTD, -+ DM_DRIVER_GET(iproc_nand), &dev); -+ if (ret && ret != -ENODEV) -+ pr_err("Failed to initialize %s. (error %d)\n", dev->name, -+ ret); -+} diff --git a/package/boot/uboot-bcm53xx/patches/0002-mtd-rawnand-nand_base-Handle-algorithm-selection.patch b/package/boot/uboot-bcm53xx/patches/0002-mtd-rawnand-nand_base-Handle-algorithm-selection.patch deleted file mode 100644 index eb2a5ec703..0000000000 --- a/package/boot/uboot-bcm53xx/patches/0002-mtd-rawnand-nand_base-Handle-algorithm-selection.patch +++ /dev/null @@ -1,80 +0,0 @@ -From d75483f8892f3a0dfb8f5aa4147e72c02c8b034c Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Fri, 7 Apr 2023 15:40:05 +0200 -Subject: [PATCH 2/5] mtd: rawnand: nand_base: Handle algorithm selection - -For BRCMNAND with 1-bit BCH ECC (BCH-1) such as used on the -D-Link DIR-885L and DIR-890L routers, we need to explicitly -select the ECC like this in the device tree: - - nand-ecc-algo = "bch"; - nand-ecc-strength = <1>; - nand-ecc-step-size = <512>; - -This is handled by the Linux kernel but U-Boot core does -not respect this. Fix it up by parsing the algorithm and -preserve the behaviour using this property to select -software BCH as far as possible. - -Reviewed-by: Michael Trimarchi -Acked-by: William Zhang -Signed-off-by: Linus Walleij -Tested-by: Tom Rini [am335x_evm] -Link: https://lore.kernel.org/all/20230407134008.1939717-3-linus.walleij@linaro.org/ -Signed-off-by: Dario Binacchi ---- - drivers/mtd/nand/raw/nand_base.c | 29 +++++++++++++++++++++++++---- - 1 file changed, 25 insertions(+), 4 deletions(-) - ---- a/drivers/mtd/nand/raw/nand_base.c -+++ b/drivers/mtd/nand/raw/nand_base.c -@@ -4487,6 +4487,7 @@ EXPORT_SYMBOL(nand_detect); - static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, ofnode node) - { - int ret, ecc_mode = -1, ecc_strength, ecc_step; -+ int ecc_algo = NAND_ECC_UNKNOWN; - const char *str; - - ret = ofnode_read_s32_default(node, "nand-bus-width", -1); -@@ -4512,10 +4513,22 @@ static int nand_dt_init(struct mtd_info - ecc_mode = NAND_ECC_SOFT_BCH; - } - -- if (ecc_mode == NAND_ECC_SOFT) { -- str = ofnode_read_string(node, "nand-ecc-algo"); -- if (str && !strcmp(str, "bch")) -- ecc_mode = NAND_ECC_SOFT_BCH; -+ str = ofnode_read_string(node, "nand-ecc-algo"); -+ if (str) { -+ /* -+ * If we are in NAND_ECC_SOFT mode, just alter the -+ * soft mode to BCH here. No change of algorithm. -+ */ -+ if (ecc_mode == NAND_ECC_SOFT) { -+ if (!strcmp(str, "bch")) -+ ecc_mode = NAND_ECC_SOFT_BCH; -+ } else { -+ if (!strcmp(str, "bch")) { -+ ecc_algo = NAND_ECC_BCH; -+ } else if (!strcmp(str, "hamming")) { -+ ecc_algo = NAND_ECC_HAMMING; -+ } -+ } - } - - ecc_strength = ofnode_read_s32_default(node, -@@ -4529,6 +4542,14 @@ static int nand_dt_init(struct mtd_info - return -EINVAL; - } - -+ /* -+ * Chip drivers may have assigned default algorithms here, -+ * onlt override it if we have found something explicitly -+ * specified in the device tree. -+ */ -+ if (ecc_algo != NAND_ECC_UNKNOWN) -+ chip->ecc.algo = ecc_algo; -+ - if (ecc_mode >= 0) - chip->ecc.mode = ecc_mode; - diff --git a/package/boot/uboot-bcm53xx/patches/0003-arm-dts-Import-device-tree-for-Broadcom-Northstar.patch b/package/boot/uboot-bcm53xx/patches/0003-arm-dts-Import-device-tree-for-Broadcom-Northstar.patch deleted file mode 100644 index 6a4eef77f8..0000000000 --- a/package/boot/uboot-bcm53xx/patches/0003-arm-dts-Import-device-tree-for-Broadcom-Northstar.patch +++ /dev/null @@ -1,659 +0,0 @@ -From 3d6098a662b7ff5b80c4b75c54fcd1b2baf9f150 Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Mon, 24 Apr 2023 09:38:28 +0200 -Subject: [PATCH 3/5] arm: dts: Import device tree for Broadcom Northstar -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This brings in the main SoC device tree used by the -Broadcom Northstar chipset, i.e. BCM4709x and BCM5301x. -This is taken from the v6.3 Linux kernel. - -Cc: Rafał Miłecki -Signed-off-by: Linus Walleij ---- - arch/arm/dts/bcm5301x.dtsi | 581 ++++++++++++++++++++++++++++ - include/dt-bindings/clock/bcm-nsp.h | 51 +++ - 2 files changed, 632 insertions(+) - create mode 100644 arch/arm/dts/bcm5301x.dtsi - create mode 100644 include/dt-bindings/clock/bcm-nsp.h - ---- /dev/null -+++ b/arch/arm/dts/bcm5301x.dtsi -@@ -0,0 +1,581 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * Generic DTS part for all BCM53010, BCM53011, BCM53012, BCM53014, BCM53015, -+ * BCM53016, BCM53017, BCM53018, BCM4707, BCM4708 and BCM4709 SoCs -+ * -+ * Copyright 2013-2014 Hauke Mehrtens -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/ { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ interrupt-parent = <&gic>; -+ -+ chipcommon-a-bus@18000000 { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x18000000 0x00001000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@300 { -+ compatible = "ns16550"; -+ reg = <0x0300 0x100>; -+ interrupts = ; -+ clocks = <&iprocslow>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@400 { -+ compatible = "ns16550"; -+ reg = <0x0400 0x100>; -+ interrupts = ; -+ clocks = <&iprocslow>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinmux_uart1>; -+ status = "disabled"; -+ }; -+ }; -+ -+ mpcore-bus@19000000 { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19000000 0x00023000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ a9pll: arm_clk@0 { -+ #clock-cells = <0>; -+ compatible = "brcm,nsp-armpll"; -+ clocks = <&osc>; -+ reg = <0x00000 0x1000>; -+ }; -+ -+ scu@20000 { -+ compatible = "arm,cortex-a9-scu"; -+ reg = <0x20000 0x100>; -+ }; -+ -+ timer@20200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x20200 0x100>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ timer@20600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x20600 0x20>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ watchdog@20620 { -+ compatible = "arm,cortex-a9-twd-wdt"; -+ reg = <0x20620 0x20>; -+ interrupts = ; -+ clocks = <&periph_clk>; -+ }; -+ -+ gic: interrupt-controller@21000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0x21000 0x1000>, -+ <0x20100 0x100>; -+ }; -+ -+ L2: cache-controller@22000 { -+ compatible = "arm,pl310-cache"; -+ reg = <0x22000 0x1000>; -+ cache-unified; -+ arm,shared-override; -+ prefetch-data = <1>; -+ prefetch-instr = <1>; -+ cache-level = <2>; -+ }; -+ }; -+ -+ pmu { -+ compatible = "arm,cortex-a9-pmu"; -+ interrupts = -+ , -+ ; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ osc: oscillator { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <25000000>; -+ }; -+ -+ iprocmed: iprocmed { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&genpll BCM_NSP_GENPLL_IPROCFAST_CLK>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ -+ iprocslow: iprocslow { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&genpll BCM_NSP_GENPLL_IPROCFAST_CLK>; -+ clock-div = <4>; -+ clock-mult = <1>; -+ }; -+ -+ periph_clk: periph_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-factor-clock"; -+ clocks = <&a9pll>; -+ clock-div = <2>; -+ clock-mult = <1>; -+ }; -+ }; -+ -+ axi@18000000 { -+ compatible = "brcm,bus-axi"; -+ reg = <0x18000000 0x1000>; -+ ranges = <0x00000000 0x18000000 0x00100000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0x000fffff 0xffff>; -+ interrupt-map = -+ /* ChipCommon */ -+ <0x00000000 0 &gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Switch Register Access Block */ -+ <0x00007000 0 &gic GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 1 &gic GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 2 &gic GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 3 &gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 4 &gic GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 5 &gic GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 6 &gic GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 7 &gic GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 8 &gic GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 9 &gic GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 10 &gic GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 11 &gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00007000 12 &gic GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* PCIe Controller 0 */ -+ <0x00012000 0 &gic GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 1 &gic GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 2 &gic GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 3 &gic GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 4 &gic GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 5 &gic GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* PCIe Controller 1 */ -+ <0x00013000 0 &gic GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 1 &gic GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 2 &gic GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 3 &gic GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 4 &gic GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 5 &gic GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* PCIe Controller 2 */ -+ <0x00014000 0 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 1 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 2 &gic GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 3 &gic GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 4 &gic GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 5 &gic GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* USB 2.0 Controller */ -+ <0x00021000 0 &gic GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* USB 3.0 Controller */ -+ <0x00023000 0 &gic GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 0 */ -+ <0x00024000 0 &gic GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 1 */ -+ <0x00025000 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 2 */ -+ <0x00026000 0 &gic GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 3 */ -+ <0x00027000 0 &gic GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* NAND Controller */ -+ <0x00028000 0 &gic GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 1 &gic GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 2 &gic GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 3 &gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 4 &gic GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 5 &gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 6 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 7 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; -+ -+ chipcommon: chipcommon@0 { -+ reg = <0x00000000 0x1000>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ pcie0: pcie@12000 { -+ reg = <0x00012000 0x1000>; -+ }; -+ -+ pcie1: pcie@13000 { -+ reg = <0x00013000 0x1000>; -+ }; -+ -+ pcie2: pcie@14000 { -+ reg = <0x00014000 0x1000>; -+ }; -+ -+ usb2: usb2@21000 { -+ reg = <0x00021000 0x1000>; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ interrupt-parent = <&gic>; -+ -+ ehci: usb@21000 { -+ #usb-cells = <0>; -+ -+ compatible = "generic-ehci"; -+ reg = <0x00021000 0x1000>; -+ interrupts = ; -+ phys = <&usb2_phy>; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ehci_port1: port@1 { -+ reg = <1>; -+ #trigger-source-cells = <0>; -+ }; -+ -+ ehci_port2: port@2 { -+ reg = <2>; -+ #trigger-source-cells = <0>; -+ }; -+ }; -+ -+ ohci: usb@22000 { -+ #usb-cells = <0>; -+ -+ compatible = "generic-ohci"; -+ reg = <0x00022000 0x1000>; -+ interrupts = ; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ohci_port1: port@1 { -+ reg = <1>; -+ #trigger-source-cells = <0>; -+ }; -+ -+ ohci_port2: port@2 { -+ reg = <2>; -+ #trigger-source-cells = <0>; -+ }; -+ }; -+ }; -+ -+ usb3: usb3@23000 { -+ reg = <0x00023000 0x1000>; -+ -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ interrupt-parent = <&gic>; -+ -+ xhci: usb@23000 { -+ #usb-cells = <0>; -+ -+ compatible = "generic-xhci"; -+ reg = <0x00023000 0x1000>; -+ interrupts = ; -+ phys = <&usb3_phy>; -+ phy-names = "usb"; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ xhci_port1: port@1 { -+ reg = <1>; -+ #trigger-source-cells = <0>; -+ }; -+ }; -+ }; -+ -+ gmac0: ethernet@24000 { -+ reg = <0x24000 0x800>; -+ }; -+ -+ gmac1: ethernet@25000 { -+ reg = <0x25000 0x800>; -+ }; -+ -+ gmac2: ethernet@26000 { -+ reg = <0x26000 0x800>; -+ }; -+ -+ gmac3: ethernet@27000 { -+ reg = <0x27000 0x800>; -+ }; -+ }; -+ -+ pwm: pwm@18002000 { -+ compatible = "brcm,iproc-pwm"; -+ reg = <0x18002000 0x28>; -+ clocks = <&osc>; -+ #pwm-cells = <3>; -+ status = "disabled"; -+ }; -+ -+ mdio: mdio@18003000 { -+ compatible = "brcm,iproc-mdio"; -+ reg = <0x18003000 0x8>; -+ #size-cells = <0>; -+ #address-cells = <1>; -+ }; -+ -+ mdio-mux@18003000 { -+ compatible = "mdio-mux-mmioreg", "mdio-mux"; -+ mdio-parent-bus = <&mdio>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x18003000 0x4>; -+ mux-mask = <0x200>; -+ -+ mdio@0 { -+ reg = <0x0>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ usb3_phy: usb3-phy@10 { -+ compatible = "brcm,ns-ax-usb3-phy"; -+ reg = <0x10>; -+ usb3-dmp-syscon = <&usb3_dmp>; -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ -+ usb3_dmp: syscon@18105000 { -+ reg = <0x18105000 0x1000>; -+ }; -+ -+ uart2: serial@18008000 { -+ compatible = "ns16550a"; -+ reg = <0x18008000 0x20>; -+ clocks = <&iprocslow>; -+ interrupts = ; -+ reg-shift = <2>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@18009000 { -+ compatible = "brcm,iproc-i2c"; -+ reg = <0x18009000 0x50>; -+ interrupts = ; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ clock-frequency = <100000>; -+ status = "disabled"; -+ }; -+ -+ dmu-bus@1800c000 { -+ compatible = "simple-bus"; -+ ranges = <0 0x1800c000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ cru-bus@100 { -+ compatible = "brcm,ns-cru", "simple-mfd"; -+ reg = <0x100 0x1a4>; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ lcpll0: clock-controller@100 { -+ #clock-cells = <1>; -+ compatible = "brcm,nsp-lcpll0"; -+ reg = <0x100 0x14>; -+ clocks = <&osc>; -+ clock-output-names = "lcpll0", "pcie_phy", -+ "sdio", "ddr_phy"; -+ }; -+ -+ genpll: clock-controller@140 { -+ #clock-cells = <1>; -+ compatible = "brcm,nsp-genpll"; -+ reg = <0x140 0x24>; -+ clocks = <&osc>; -+ clock-output-names = "genpll", "phy", -+ "ethernetclk", -+ "usbclk", "iprocfast", -+ "sata1", "sata2"; -+ }; -+ -+ usb2_phy: phy@164 { -+ compatible = "brcm,ns-usb2-phy"; -+ reg = <0x164 0x4>; -+ brcm,syscon-clkset = <&cru_clkset>; -+ clocks = <&genpll BCM_NSP_GENPLL_USB_PHY_REF_CLK>; -+ clock-names = "phy-ref-clk"; -+ #phy-cells = <0>; -+ }; -+ -+ cru_clkset: syscon@180 { -+ compatible = "brcm,cru-clkset", "syscon"; -+ reg = <0x180 0x4>; -+ }; -+ -+ pinctrl: pinctrl@1c0 { -+ compatible = "brcm,bcm4708-pinmux"; -+ reg = <0x1c0 0x24>; -+ reg-names = "cru_gpio_control"; -+ -+ spi-pins { -+ groups = "spi_grp"; -+ function = "spi"; -+ }; -+ -+ pinmux_i2c: i2c-pins { -+ groups = "i2c_grp"; -+ function = "i2c"; -+ }; -+ -+ pinmux_pwm: pwm-pins { -+ groups = "pwm0_grp", "pwm1_grp", -+ "pwm2_grp", "pwm3_grp"; -+ function = "pwm"; -+ }; -+ -+ pinmux_uart1: uart1-pins { -+ groups = "uart1_grp"; -+ function = "uart1"; -+ }; -+ }; -+ -+ thermal: thermal@2c0 { -+ compatible = "brcm,ns-thermal"; -+ reg = <0x2c0 0x10>; -+ #thermal-sensor-cells = <0>; -+ }; -+ }; -+ }; -+ -+ srab: ethernet-switch@18007000 { -+ compatible = "brcm,bcm53011-srab", "brcm,bcm5301x-srab"; -+ reg = <0x18007000 0x1000>; -+ -+ status = "disabled"; -+ -+ /* ports are defined in board DTS */ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ }; -+ -+ rng: rng@18004000 { -+ compatible = "brcm,bcm5301x-rng"; -+ reg = <0x18004000 0x14>; -+ }; -+ -+ nand_controller: nand-controller@18028000 { -+ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1", "brcm,brcmnand"; -+ reg = <0x18028000 0x600>, <0x1811a408 0x600>, <0x18028f00 0x20>; -+ reg-names = "nand", "iproc-idm", "iproc-ext"; -+ interrupts = ; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ brcm,nand-has-wp; -+ }; -+ -+ spi@18029200 { -+ compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi"; -+ reg = <0x18029200 0x184>, -+ <0x18029000 0x124>, -+ <0x1811b408 0x004>, -+ <0x180293a0 0x01c>; -+ reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg"; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "mspi_done", -+ "mspi_halted", -+ "spi_lr_fullness_reached", -+ "spi_lr_session_aborted", -+ "spi_lr_impatient", -+ "spi_lr_session_done", -+ "spi_lr_overread"; -+ clocks = <&iprocmed>; -+ clock-names = "iprocmed"; -+ num-cs = <2>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ spi_nor: flash@0 { -+ compatible = "jedec,spi-nor"; -+ reg = <0>; -+ spi-max-frequency = <20000000>; -+ status = "disabled"; -+ -+ partitions { -+ compatible = "brcm,bcm947xx-cfe-partitions"; -+ }; -+ }; -+ }; -+ -+ thermal-zones { -+ cpu_thermal: cpu-thermal { -+ polling-delay-passive = <0>; -+ polling-delay = <1000>; -+ coefficients = <(-556) 418000>; -+ thermal-sensors = <&thermal>; -+ -+ trips { -+ cpu-crit { -+ temperature = <125000>; -+ hysteresis = <0>; -+ type = "critical"; -+ }; -+ }; -+ -+ cooling-maps { -+ }; -+ }; -+ }; -+}; ---- /dev/null -+++ b/include/dt-bindings/clock/bcm-nsp.h -@@ -0,0 +1,51 @@ -+/* -+ * BSD LICENSE -+ * -+ * Copyright(c) 2015 Broadcom Corporation. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in -+ * the documentation and/or other materials provided with the -+ * distribution. -+ * * Neither the name of Broadcom Corporation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef _CLOCK_BCM_NSP_H -+#define _CLOCK_BCM_NSP_H -+ -+/* GENPLL clock channel ID */ -+#define BCM_NSP_GENPLL 0 -+#define BCM_NSP_GENPLL_PHY_CLK 1 -+#define BCM_NSP_GENPLL_ENET_SW_CLK 2 -+#define BCM_NSP_GENPLL_USB_PHY_REF_CLK 3 -+#define BCM_NSP_GENPLL_IPROCFAST_CLK 4 -+#define BCM_NSP_GENPLL_SATA1_CLK 5 -+#define BCM_NSP_GENPLL_SATA2_CLK 6 -+ -+/* LCPLL0 clock channel ID */ -+#define BCM_NSP_LCPLL0 0 -+#define BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK 1 -+#define BCM_NSP_LCPLL0_SDIO_CLK 2 -+#define BCM_NSP_LCPLL0_DDR_PHY_CLK 3 -+ -+#endif /* _CLOCK_BCM_NSP_H */ diff --git a/package/boot/uboot-bcm53xx/patches/0004-arm-Add-support-for-the-Broadcom-Northstar-SoCs.patch b/package/boot/uboot-bcm53xx/patches/0004-arm-Add-support-for-the-Broadcom-Northstar-SoCs.patch deleted file mode 100644 index 92eaa46e51..0000000000 --- a/package/boot/uboot-bcm53xx/patches/0004-arm-Add-support-for-the-Broadcom-Northstar-SoCs.patch +++ /dev/null @@ -1,66 +0,0 @@ -From b81ea0a64b01ae42e8b41d2a8b9a3fabffe97489 Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Mon, 24 Apr 2023 09:38:29 +0200 -Subject: [PATCH 4/5] arm: Add support for the Broadcom Northstar SoCs -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The original Northstar is an ARM SoC series that comprise -BCM4709x and BCM5301x and uses a dual-core Cortex A9, the -global timer and a few other things. - -This series should not be confused with North Star Plus -(NSP) which is partly supported by U-Boot already. - -The SoC is well supported by the Linux kernel and OpenWrt -as it is used in many routers. - -Since we currently don't need any chip-specific quirks -and can get the system up from just the device tree, a -mach-* directory doesn't even need to be added, just -some small Kconfig fragments. - -Cc: Rafał Miłecki -Signed-off-by: Linus Walleij ---- - arch/arm/Kconfig | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -357,7 +357,7 @@ config SYS_ARM_ARCH - - choice - prompt "Select the ARM data write cache policy" -- default SYS_ARM_CACHE_WRITETHROUGH if TARGET_BCMCYGNUS || RZA1 -+ default SYS_ARM_CACHE_WRITETHROUGH if TARGET_BCMCYGNUS || TARGET_BCMNS || RZA1 - default SYS_ARM_CACHE_WRITEBACK - - config SYS_ARM_CACHE_WRITEBACK -@@ -670,6 +670,25 @@ config TARGET_BCMCYGNUS - imply HASH_VERIFY - imply NETDEVICES - -+config TARGET_BCMNS -+ bool "Support Broadcom Northstar" -+ select CPU_V7A -+ select DM -+ select DM_GPIO -+ select DM_SERIAL -+ select OF_CONTROL -+ select TIMER -+ select SYS_NS16550 -+ select ARM_GLOBAL_TIMER -+ imply SYS_THUMB_BUILD -+ imply MTD_RAW_NAND -+ imply NAND_BRCMNAND -+ imply NAND_BRCMNAND_IPROC -+ help -+ Support for Broadcom Northstar SoCs. NS is a dual-core 32-bit -+ ARMv7 Cortex-A9 SoC family including BCM4708, BCM47094, -+ BCM5301x etc. -+ - config TARGET_BCMNS2 - bool "Support Broadcom Northstar2" - select ARM64 diff --git a/package/boot/uboot-bcm53xx/patches/0005-board-Add-new-Broadcom-Northstar-board.patch b/package/boot/uboot-bcm53xx/patches/0005-board-Add-new-Broadcom-Northstar-board.patch deleted file mode 100644 index 158718133d..0000000000 --- a/package/boot/uboot-bcm53xx/patches/0005-board-Add-new-Broadcom-Northstar-board.patch +++ /dev/null @@ -1,372 +0,0 @@ -From 652a6fa45b6c9d52dd9685fc12ad662e54a9092e Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Mon, 24 Apr 2023 09:38:30 +0200 -Subject: [PATCH 5/5] board: Add new Broadcom Northstar board -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This adds a simple Northstar "BRCMNS" board to be used with -the BCM4708x and BCM5301x chips. - -The main intention is to use this with the D-Link DIR-890L -and DIR-885L routers for loading the kernel into RAM from -NAND memory using the BCH-1 ECC and using the separately -submitted SEAMA load command, so we are currently not adding -support for things such as networking. - -The DTS file is a multiplatform NorthStar board, designed to -be usable with several NorthStar designs by avoiding any -particulars not related to the operation of U-Boot. - -If other board need other ECC for example, they need to -create a separate DTS file and augment the code, but I don't -know if any other users will turn up. - -Cc: Rafał Miłecki -Signed-off-by: Linus Walleij ---- - arch/arm/Kconfig | 1 + - arch/arm/dts/Makefile | 2 ++ - arch/arm/dts/ns-board.dts | 57 ++++++++++++++++++++++++++++++ - board/broadcom/bcmns/Kconfig | 12 +++++++ - board/broadcom/bcmns/MAINTAINERS | 6 ++++ - board/broadcom/bcmns/Makefile | 2 ++ - board/broadcom/bcmns/ns.c | 60 ++++++++++++++++++++++++++++++++ - configs/bcmns_defconfig | 41 ++++++++++++++++++++++ - doc/board/broadcom/index.rst | 1 + - doc/board/broadcom/northstar.rst | 44 +++++++++++++++++++++++ - include/configs/bcmns.h | 49 ++++++++++++++++++++++++++ - 11 files changed, 275 insertions(+) - create mode 100644 arch/arm/dts/ns-board.dts - create mode 100644 board/broadcom/bcmns/Kconfig - create mode 100644 board/broadcom/bcmns/MAINTAINERS - create mode 100644 board/broadcom/bcmns/Makefile - create mode 100644 board/broadcom/bcmns/ns.c - create mode 100644 configs/bcmns_defconfig - create mode 100644 doc/board/broadcom/northstar.rst - create mode 100644 include/configs/bcmns.h - ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -2286,6 +2286,7 @@ source "board/Marvell/octeontx2/Kconfig" - source "board/armltd/vexpress/Kconfig" - source "board/armltd/vexpress64/Kconfig" - source "board/cortina/presidio-asic/Kconfig" -+source "board/broadcom/bcmns/Kconfig" - source "board/broadcom/bcmns3/Kconfig" - source "board/cavium/thunderx/Kconfig" - source "board/eets/pdu001/Kconfig" ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -1185,6 +1185,8 @@ dtb-$(CONFIG_ARCH_BCM283X) += \ - bcm2837-rpi-cm3-io3.dtb \ - bcm2711-rpi-4-b.dtb - -+dtb-$(CONFIG_TARGET_BCMNS) += ns-board.dtb -+ - dtb-$(CONFIG_TARGET_BCMNS3) += ns3-board.dtb - - dtb-$(CONFIG_ARCH_BCMSTB) += bcm7xxx.dtb ---- /dev/null -+++ b/arch/arm/dts/ns-board.dts -@@ -0,0 +1,57 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+ -+/dts-v1/; -+ -+#include "bcm5301x.dtsi" -+ -+/ { -+ /* -+ * The Northstar does not have a proper fallback compatible, but -+ * these basic chips will suffice. -+ */ -+ model = "Northstar model"; -+ compatible = "brcm,bcm47094", "brcm,bcm4708"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ interrupt-parent = <&gic>; -+ -+ memory { -+ device_type = "memory"; -+ reg = <0x00000000 0x08000000>, -+ <0x88000000 0x08000000>; -+ }; -+ -+ aliases { -+ serial0 = &uart0; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ nand-controller@18028000 { -+ nandcs: nand@0 { -+ compatible = "brcm,nandcs"; -+ reg = <0>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ /* -+ * Same as using the bcm5301x-nand-cs0-bch1.dtsi -+ * include from the Linux kernel. -+ */ -+ nand-ecc-algo = "bch"; -+ nand-ecc-strength = <1>; -+ nand-ecc-step-size = <512>; -+ -+ partitions { -+ compatible = "brcm,bcm947xx-cfe-partitions"; -+ }; -+ }; -+ }; -+}; -+ -+&uart0 { -+ clock-frequency = <125000000>; -+ status = "okay"; -+}; ---- /dev/null -+++ b/board/broadcom/bcmns/Kconfig -@@ -0,0 +1,12 @@ -+if TARGET_BCMNS -+ -+config SYS_BOARD -+ default "bcmns" -+ -+config SYS_VENDOR -+ default "broadcom" -+ -+config SYS_CONFIG_NAME -+ default "bcmns" -+ -+endif ---- /dev/null -+++ b/board/broadcom/bcmns/MAINTAINERS -@@ -0,0 +1,6 @@ -+BCMNS BOARD -+M: Linus Walleij -+S: Maintained -+F: board/broadcom/bcmnsp/ -+F: configs/bcmnsp_defconfig -+F: include/configs/bcmnsp.h ---- /dev/null -+++ b/board/broadcom/bcmns/Makefile -@@ -0,0 +1,2 @@ -+# SPDX-License-Identifier: GPL-2.0-or-later -+obj-y := ns.o ---- /dev/null -+++ b/board/broadcom/bcmns/ns.c -@@ -0,0 +1,60 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Broadcom Northstar generic board set-up code -+ * Copyright (C) 2023 Linus Walleij -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+DECLARE_GLOBAL_DATA_PTR; -+ -+int dram_init(void) -+{ -+ return fdtdec_setup_mem_size_base(); -+} -+ -+int dram_init_banksize(void) -+{ -+ return fdtdec_setup_memory_banksize(); -+} -+ -+int board_late_init(void) -+{ -+ /* LEDs etc can be initialized here */ -+ return 0; -+} -+ -+int board_init(void) -+{ -+ return 0; -+} -+ -+void reset_cpu(void) -+{ -+} -+ -+int print_cpuinfo(void) -+{ -+ printf("BCMNS Northstar SoC\n"); -+ return 0; -+} -+ -+int misc_init_r(void) -+{ -+ return 0; -+} -+ -+int ft_board_setup(void *fdt, struct bd_info *bd) -+{ -+ printf("Northstar board setup: DTB at 0x%08lx\n", (ulong)fdt); -+ return 0; -+} -+ ---- /dev/null -+++ b/configs/bcmns_defconfig -@@ -0,0 +1,41 @@ -+CONFIG_ARM=y -+CONFIG_TARGET_BCMNS=y -+CONFIG_TEXT_BASE=0x00008000 -+CONFIG_SYS_MALLOC_LEN=0x2000000 -+CONFIG_SYS_MALLOC_F_LEN=0x8000 -+CONFIG_NR_DRAM_BANKS=2 -+CONFIG_DEFAULT_DEVICE_TREE="ns-board" -+CONFIG_IDENT_STRING="Broadcom Northstar" -+CONFIG_SYS_LOAD_ADDR=0x00008000 -+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x00100000 -+# CONFIG_BOOTSTD is not set -+CONFIG_AUTOBOOT_KEYED=y -+CONFIG_AUTOBOOT_PROMPT="Boot Northstar system in %d seconds\n" -+CONFIG_BOOTDELAY=1 -+CONFIG_USE_BOOTCOMMAND=y -+CONFIG_BOOTCOMMAND="run bootcmd_dlink_dir8xxl" -+CONFIG_SYS_PROMPT="northstar> " -+CONFIG_ENV_VARS_UBOOT_CONFIG=y -+CONFIG_OF_BOARD_SETUP=y -+CONFIG_OF_STDOUT_VIA_ALIAS=y -+CONFIG_DISPLAY_BOARDINFO_LATE=y -+CONFIG_HUSH_PARSER=y -+CONFIG_SYS_MAXARGS=64 -+CONFIG_CMD_SEAMA=y -+CONFIG_CMD_BOOTZ=y -+CONFIG_CMD_CACHE=y -+CONFIG_OF_EMBED=y -+CONFIG_USE_HOSTNAME=y -+CONFIG_HOSTNAME="NS" -+CONFIG_CLK=y -+CONFIG_MTD=y -+CONFIG_DM_MTD=y -+CONFIG_MTD_RAW_NAND=y -+CONFIG_NAND_BRCMNAND=y -+CONFIG_SYS_NAND_ONFI_DETECTION=y -+CONFIG_CMD_NAND=y -+CONFIG_DM_SERIAL=y -+CONFIG_SYS_NS16550=y -+# CONFIG_NET is not set -+# CONFIG_EFI_LOADER is not set ---- a/doc/board/broadcom/index.rst -+++ b/doc/board/broadcom/index.rst -@@ -9,3 +9,4 @@ Broadcom - - bcm7xxx - raspberrypi -+ northstar ---- /dev/null -+++ b/doc/board/broadcom/northstar.rst -@@ -0,0 +1,44 @@ -+.. SPDX-License-Identifier: GPL-2.0+ -+.. Copyright (C) 2023 Linus Walleij -+ -+Broadcom Northstar Boards -+========================= -+ -+This document describes how to use U-Boot on the Broadcom Northstar -+boards, comprised of the Cortex A9 ARM-based BCM470x and BCM5301x SoCs. These -+were introduced in 2012-2013 and some of them are also called StrataGX. -+ -+Northstar is part of the iProc SoC family. -+ -+A good overview of these boards can be found in Jon Mason's presentation -+"Enabling New Hardware in U-Boot" where the difference between Northstar -+and Northstar Plus and Northstar 2 (Aarch64) is addressed. -+ -+The ROM in the Northstar SoC will typically look into NOR flash memory -+for a boot loader, and the way this works is undocumented. It should be -+possible to execute U-Boot as the first binary from the NOR flash but -+this usage path is unexplored. Please add information if you know more. -+ -+D-Link Boards -+------------- -+ -+When we use U-Boot with D-Link routers, the NOR flash has a boot loader -+and web server that can re-flash the bigger NAND flash memory for object -+code in the SEAMA format, so on these platforms U-Boot is converted into -+a SEAMA binary and installed in the SoC using the flash tool resident in -+the NOR flash. Details can be found in the OpenWrt project codebase. -+ -+Configure -+--------- -+ -+.. code-block:: console -+ -+ $ make CROSS_COMPILE=${CROSS_COMPILE} bcmns_defconfig -+ -+Build -+----- -+ -+.. code-block:: console -+ -+ $ make CROSS_COMPILE=${CROSS_COMPILE} -+ $ ${CROSS_COMPILE}strip u-boot ---- /dev/null -+++ b/include/configs/bcmns.h -@@ -0,0 +1,49 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+ -+#ifndef __BCM_NS_H -+#define __BCM_NS_H -+ -+#include -+ -+/* Physical Memory Map */ -+#define V2M_BASE 0x00000000 -+#define PHYS_SDRAM_1 V2M_BASE -+ -+#define CFG_SYS_SDRAM_BASE PHYS_SDRAM_1 -+ -+/* Called "periph_clk" in Linux, used by the global timer */ -+#define CFG_SYS_HZ_CLOCK 500000000 -+ -+/* Called "iprocslow" in Linux */ -+#define CFG_SYS_NS16550_CLK 125000000 -+ -+/* console configuration */ -+#define CONSOLE_ARGS "console_args=console=ttyS0,115200n8\0" -+#define MAX_CPUS "max_cpus=maxcpus=2\0" -+#define EXTRA_ARGS "extra_args=earlycon=uart8250,mmio32,0x18000300\0" -+ -+#define BASE_ARGS "${console_args} ${extra_args} ${pcie_args}" \ -+ " ${max_cpus} ${log_level} ${reserved_mem}" -+#define SETBOOTARGS "setbootargs=setenv bootargs " BASE_ARGS "\0" -+ -+#define KERNEL_LOADADDR_CFG \ -+ "loadaddr=0x01000000\0" \ -+ "dtb_loadaddr=0x02000000\0" -+ -+/* -+ * Hardcoded for the only boards we support, if you add more -+ * boards, add a more clever bootcmd! -+ */ -+#define NS_BOOTCMD "bootcmd_dlink_dir8xxl=seama 0x00fe0000; go 0x01000000" -+ -+#define ARCH_ENV_SETTINGS \ -+ CONSOLE_ARGS \ -+ MAX_CPUS \ -+ EXTRA_ARGS \ -+ KERNEL_LOADADDR_CFG \ -+ NS_BOOTCMD -+ -+#define CFG_EXTRA_ENV_SETTINGS \ -+ ARCH_ENV_SETTINGS -+ -+#endif /* __BCM_NS_H */ From 7b5aeef6dbfae724fa4bef4edee49be389fd4a5e Mon Sep 17 00:00:00 2001 From: Samuele Longhi Date: Wed, 20 Dec 2023 19:27:15 +0100 Subject: [PATCH 167/222] ath79: generic: rework ar9342_ubnt_xw dtsi, and add support for Ubiquiti LiteBeam M5 (XW), Ubiquiti AirGrid M5 HP (XW), Ubiquiti PowerBeam M5 300 (XW) Add support for Ubiquiti LiteBeam M5 (XW). The device was previously supported in ar71xx. See commit: https://git.openwrt.org/?p=openwrt/openwrt.git;a=commit;h=d0988235dd277b9a832bbc4b2a100ac6e821f577 Add ALTX_MODEL for Ubiquiti AirGrid M5 HP (XW), Ubiquiti PowerBeam M5 300 (XW) in generic-ubnt.mk This models are identical (firmware-wise) to the already supported Ubiquiti Nanostation Loco M (XW) Add also Ubiquiti NanoBeam M5 to ALTX_MODEL of Ubiquiti Nanostation Loco M (XW) since it's another clone. Tested on: - Ubiquiti LiteBeam M5 (XW) - Ubiquiti PowerBeam M5 (XW) This also modify target/ath79/dts/ar9342_ubnt_xw.dtsi to use nvmem for calibration data Checked that the caldata size in the eeprom partition are actually 0x440 on: - Ubiquiti PowerBeam M5 (XW) - Ubiquiti Nanostation M5 (XW) - Ubiquiti LiteBeam M5 (XW) - Ubiquiti AirGrid M5 HP (XW) Signed-off-by: Samuele Longhi --- .../ath79/dts/ar9342_ubnt_bullet-m-xw.dts | 2 +- .../ath79/dts/ar9342_ubnt_litebeam-m5-xw.dts | 59 +++++++++++++++++++ .../ath79/dts/ar9342_ubnt_nanobeam-m5-xw.dts | 24 -------- .../dts/ar9342_ubnt_nanostation-loco-m-xw.dts | 2 +- .../dts/ar9342_ubnt_nanostation-m-xw.dts | 2 +- .../ath79/dts/ar9342_ubnt_powerbeam-m2-xw.dts | 2 +- .../ath79/dts/ar9342_ubnt_powerbeam-m5-xw.dts | 2 +- target/linux/ath79/dts/ar9342_ubnt_xw.dtsi | 39 ++---------- .../ath79/dts/ar9342_ubnt_xw_rssileds.dtsi | 43 ++++++++++++++ .../generic/base-files/etc/board.d/01_leds | 3 +- .../generic/base-files/etc/board.d/02_network | 1 + target/linux/ath79/image/generic-ubnt.mk | 29 +++++---- 12 files changed, 135 insertions(+), 73 deletions(-) create mode 100644 target/linux/ath79/dts/ar9342_ubnt_litebeam-m5-xw.dts delete mode 100644 target/linux/ath79/dts/ar9342_ubnt_nanobeam-m5-xw.dts create mode 100644 target/linux/ath79/dts/ar9342_ubnt_xw_rssileds.dtsi diff --git a/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts index c448ac4e61..8c7d1dc918 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include "ar9342_ubnt_xw.dtsi" +#include "ar9342_ubnt_xw_rssileds.dtsi" / { compatible = "ubnt,bullet-m-xw", "ubnt,xw", "qca,ar9342"; diff --git a/target/linux/ath79/dts/ar9342_ubnt_litebeam-m5-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_litebeam-m5-xw.dts new file mode 100644 index 0000000000..bc01bdffb5 --- /dev/null +++ b/target/linux/ath79/dts/ar9342_ubnt_litebeam-m5-xw.dts @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "ar9342_ubnt_xw.dtsi" + +#include +#include +#include + +/ { + compatible = "ubnt,litebeam-m5-xw", "qca,ar9342"; + model = "Ubiquiti LiteBeam M5 (XW)"; + + aliases { + led-boot = &led_status; + led-running = &led_status; + led-upgrade = &led_status; + led-failsafe = &led_status; + label-mac-device = &wmac; + }; + + leds { + compatible = "gpio-leds"; + + led-lan { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + }; + + led-wlan { + color = ; + function = LED_FUNCTION_WLAN; + linux,default-trigger = "phy0tpt"; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + }; + + led_status: led-power { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&mdio0 { + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + phy-mode = "mii"; + reset-gpios = <&gpio 0 GPIO_ACTIVE_LOW>; + }; +}; + +ð0 { + status = "okay"; + + phy-handle = <&phy1>; +}; diff --git a/target/linux/ath79/dts/ar9342_ubnt_nanobeam-m5-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_nanobeam-m5-xw.dts deleted file mode 100644 index 9b9b217f24..0000000000 --- a/target/linux/ath79/dts/ar9342_ubnt_nanobeam-m5-xw.dts +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -#include "ar9342_ubnt_xw.dtsi" - -/ { - compatible = "ubnt,nanobeam-m5-xw", "ubnt,xw", "qca,ar9342"; - model = "Ubiquiti NanoBeam M5 (XW)"; -}; - -&mdio0 { - status = "okay"; - - phy1: ethernet-phy@1 { - reg = <1>; - phy-mode = "mii"; - reset-gpios = <&gpio 0 GPIO_ACTIVE_LOW>; - }; -}; - -ð0 { - status = "okay"; - - phy-handle = <&phy1>; -}; diff --git a/target/linux/ath79/dts/ar9342_ubnt_nanostation-loco-m-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_nanostation-loco-m-xw.dts index c71cf11dd2..ba3ad5a8d0 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_nanostation-loco-m-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_nanostation-loco-m-xw.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include "ar9342_ubnt_xw.dtsi" +#include "ar9342_ubnt_xw_rssileds.dtsi" / { compatible = "ubnt,nanostation-loco-m-xw", "ubnt,xw", "qca,ar9342"; diff --git a/target/linux/ath79/dts/ar9342_ubnt_nanostation-m-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_nanostation-m-xw.dts index e359297661..fb02bb188a 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_nanostation-m-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_nanostation-m-xw.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include "ar9342_ubnt_xw.dtsi" +#include "ar9342_ubnt_xw_rssileds.dtsi" / { compatible = "ubnt,nanostation-m-xw", "ubnt,xw", "qca,ar9342"; diff --git a/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m2-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m2-xw.dts index 762a17b177..11bd71ca3d 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m2-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m2-xw.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include "ar9342_ubnt_xw.dtsi" +#include "ar9342_ubnt_xw_rssileds.dtsi" / { compatible = "ubnt,powerbeam-m2-xw", "ubnt,xw", "qca,ar9342"; diff --git a/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m5-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m5-xw.dts index 978a05fed6..7199d184e9 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m5-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_powerbeam-m5-xw.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT -#include "ar9342_ubnt_xw.dtsi" +#include "ar9342_ubnt_xw_rssileds.dtsi" / { compatible = "ubnt,powerbeam-m5-xw", "ubnt,xw", "qca,ar9342"; diff --git a/target/linux/ath79/dts/ar9342_ubnt_xw.dtsi b/target/linux/ath79/dts/ar9342_ubnt_xw.dtsi index 899f167748..cd39410be5 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_xw.dtsi +++ b/target/linux/ath79/dts/ar9342_ubnt_xw.dtsi @@ -9,38 +9,6 @@ compatible = "ubnt,xw", "qca,ar9342"; model = "Ubiquiti Networks XW board"; - aliases { - led-boot = &led_link4; - led-running = &led_link4; - led-upgrade = &led_link4; - led-failsafe = &led_link4; - label-mac-device = &wmac; - }; - - leds { - compatible = "gpio-leds"; - - link1 { - label = "red:link1"; - gpios = <&gpio 11 GPIO_ACTIVE_LOW>; - }; - - link2 { - label = "orange:link2"; - gpios = <&gpio 16 GPIO_ACTIVE_LOW>; - }; - - link3 { - label = "green:link3"; - gpios = <&gpio 13 GPIO_ACTIVE_LOW>; - }; - - led_link4: link4 { - label = "green:link4"; - gpios = <&gpio 14 GPIO_ACTIVE_LOW>; - }; - }; - keys { compatible = "gpio-keys"; @@ -107,6 +75,10 @@ macaddr_art_0: macaddr@0 { reg = <0x0 0x6>; }; + + calibration_art_1000: calibration@1000 { + reg = <0x1000 0x440>; + }; }; }; }; @@ -116,7 +88,8 @@ &wmac { status = "okay"; - mtd-cal-data = <&art 0x1000>; + nvmem-cells = <&calibration_art_1000>; + nvmem-cell-names = "calibration"; }; ð0 { diff --git a/target/linux/ath79/dts/ar9342_ubnt_xw_rssileds.dtsi b/target/linux/ath79/dts/ar9342_ubnt_xw_rssileds.dtsi new file mode 100644 index 0000000000..d54dbeba38 --- /dev/null +++ b/target/linux/ath79/dts/ar9342_ubnt_xw_rssileds.dtsi @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "ar9342_ubnt_xw.dtsi" + +#include +#include + +/ { + compatible = "ubnt,xw", "qca,ar9342"; + model = "Ubiquiti Networks XW board"; + + aliases { + led-boot = &led_link4; + led-running = &led_link4; + led-upgrade = &led_link4; + led-failsafe = &led_link4; + label-mac-device = &wmac; + }; + + leds { + compatible = "gpio-leds"; + + link1 { + label = "red:link1"; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + }; + + link2 { + label = "orange:link2"; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + }; + + link3 { + label = "green:link3"; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + }; + + led_link4: link4 { + label = "green:link4"; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + }; + }; +}; diff --git a/target/linux/ath79/generic/base-files/etc/board.d/01_leds b/target/linux/ath79/generic/base-files/etc/board.d/01_leds index ae6e3c4d30..525224bec9 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/01_leds +++ b/target/linux/ath79/generic/base-files/etc/board.d/01_leds @@ -27,7 +27,8 @@ pcs,cap324|\ tplink,cpe605-v1|\ tplink,cpe610-v1|\ tplink,cpe610-v2|\ -tplink,tl-wa1201-v2) +tplink,tl-wa1201-v2|\ +ubnt,litebeam-m5-xw) ucidef_set_led_netdev "lan" "LAN" "green:lan" "eth0" ;; tplink,tl-wdr6500-v2) diff --git a/target/linux/ath79/generic/base-files/etc/board.d/02_network b/target/linux/ath79/generic/base-files/etc/board.d/02_network index 70bfd95f9e..01747acae0 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/02_network +++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network @@ -105,6 +105,7 @@ ath79_setup_interfaces() ubnt,bullet-m-xw|\ ubnt,lap-120|\ ubnt,litebeam-ac-gen2|\ + ubnt,litebeam-m5-xw|\ ubnt,nanobeam-ac|\ ubnt,nanobeam-ac-xc|\ ubnt,nanostation-ac-loco|\ diff --git a/target/linux/ath79/image/generic-ubnt.mk b/target/linux/ath79/image/generic-ubnt.mk index 68cef7d14b..179de961be 100644 --- a/target/linux/ath79/image/generic-ubnt.mk +++ b/target/linux/ath79/image/generic-ubnt.mk @@ -62,6 +62,14 @@ define Device/ubnt_litebeam-ac-gen2 endef TARGET_DEVICES += ubnt_litebeam-ac-gen2 +define Device/ubnt_litebeam-m5-xw + $(Device/ubnt-xw) + DEVICE_MODEL := LiteBeam M5 + SUPPORTED_DEVICES += lbe-m5 + DEVICE_PACKAGES := -kmod-usb2 +endef +TARGET_DEVICES += ubnt_litebeam-m5-xw + define Device/ubnt_nanobeam-ac $(Device/ubnt-wa) DEVICE_MODEL := NanoBeam AC @@ -87,14 +95,6 @@ define Device/ubnt_nanobeam-ac-xc endef TARGET_DEVICES += ubnt_nanobeam-ac-xc -define Device/ubnt_nanobeam-m5-xw - $(Device/ubnt-xw) - DEVICE_MODEL := NanoBeam M5 - DEVICE_PACKAGES += rssileds - SUPPORTED_DEVICES += loco-m-xw -endef -TARGET_DEVICES += ubnt_nanobeam-m5-xw - define Device/ubnt_nanostation-ac $(Device/ubnt-wa) DEVICE_MODEL := Nanostation AC @@ -112,8 +112,17 @@ TARGET_DEVICES += ubnt_nanostation-ac-loco define Device/ubnt_nanostation-loco-m-xw $(Device/ubnt-xw) DEVICE_MODEL := Nanostation Loco M - DEVICE_PACKAGES += rssileds - SUPPORTED_DEVICES += loco-m-xw + DEVICE_PACKAGES += rssileds -kmod-usb2 + DEVICE_ALT0_VENDOR := Ubiquiti + DEVICE_ALT0_MODEL := AirGrid M5 HP + DEVICE_ALT0_VARIANT := XW + DEVICE_ALT1_VENDOR := Ubiquiti + DEVICE_ALT1_MODEL := PowerBeam M5 300 + DEVICE_ALT1_VARIANT := XW + DEVICE_ALT2_VENDOR := Ubiquiti + DEVICE_ALT2_MODEL := NanoBeam M5 + DEVICE_ALT2_VARIANT := XW + SUPPORTED_DEVICES += loco-m-xw nanostation-m-xw ubnt,nanobeam-m5-xw endef TARGET_DEVICES += ubnt_nanostation-loco-m-xw From 1fc729a2ac401337bd38bc84bb5a321eef6ea5d1 Mon Sep 17 00:00:00 2001 From: John Audia Date: Sat, 20 Jan 2024 08:03:12 -0500 Subject: [PATCH 168/222] kernel: bump 6.1 to 6.1.74 Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.1.74 No patches needed a rebase/only updated source hash. Build system: x86/64 Build-tested: x86/64/AMD Cezanne Run-tested: x86/64/AMD Cezanne Signed-off-by: John Audia --- include/kernel-6.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/kernel-6.1 b/include/kernel-6.1 index fde32f3ca3..87c6bf5097 100644 --- a/include/kernel-6.1 +++ b/include/kernel-6.1 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.1 = .73 -LINUX_KERNEL_HASH-6.1.73 = 6cad48706bf1cde342613dca2a2cd6dd4f79f88f9e4d356263564e4b2a5d7e87 +LINUX_VERSION-6.1 = .74 +LINUX_KERNEL_HASH-6.1.74 = b7fbd1d79faed2ce3570ef79dc1223e4e19c868b86326b14a435db56ebbb2022 From d531c344792f60e8f9e7132494e7016a1baedee2 Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Wed, 10 Jan 2024 17:10:13 +0800 Subject: [PATCH 169/222] arm-trusted-firmware-rockchip: Update to 2.10 Runtime tested on Orange Pi R1 Plus LTS (RK3328) and NanoPi R4S (RK3399). Changelog: https://trustedfirmware-a.readthedocs.io/en/v2.10/change-log.html Signed-off-by: Tianling Shen --- package/boot/arm-trusted-firmware-rockchip/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/boot/arm-trusted-firmware-rockchip/Makefile b/package/boot/arm-trusted-firmware-rockchip/Makefile index aaae4ce392..6fbcbef0a8 100644 --- a/package/boot/arm-trusted-firmware-rockchip/Makefile +++ b/package/boot/arm-trusted-firmware-rockchip/Makefile @@ -7,10 +7,10 @@ include $(TOPDIR)/rules.mk -PKG_VERSION:=2.9 +PKG_VERSION:=2.10 PKG_RELEASE:=1 -PKG_HASH:=76a66a1de0c01aeb83dfc7b72b51173fe62c6e51d6fca17cc562393117bed08b +PKG_HASH:=88215a62291b9ba87da8e50b077741103cdc08fb6c9e1ebd34dfaace746d3201 PKG_MAINTAINER:=Tobias Maedel From 7939df9587b9627f3032ad070e8b43afee8c840f Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Wed, 10 Jan 2024 17:12:46 +0800 Subject: [PATCH 170/222] uboot-rockchip: Update to 2024.01 Runtime tested on Orange Pi R1 Plus LTS and NanoPi R4S. Removed upstreamed patches: - 100-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus.patch - 101-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus-LT.patch - 103-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch - 104-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch Refreshed remaining patches. Signed-off-by: Tianling Shen --- package/boot/uboot-rockchip/Makefile | 4 +- ...28-Add-support-for-Orange-Pi-R1-Plus.patch | 594 ------------ ...Add-support-for-Orange-Pi-R1-Plus-LT.patch | 257 ----- ...Add-support-for-FriendlyARM-NanoPi-R.patch | 917 ------------------ ...Add-support-for-FriendlyARM-NanoPi-R.patch | 269 ----- ...105-nanopc-t4-fix-memory-unstability.patch | 2 - 6 files changed, 2 insertions(+), 2041 deletions(-) delete mode 100644 package/boot/uboot-rockchip/patches/100-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus.patch delete mode 100644 package/boot/uboot-rockchip/patches/101-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus-LT.patch delete mode 100644 package/boot/uboot-rockchip/patches/103-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch delete mode 100644 package/boot/uboot-rockchip/patches/104-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch diff --git a/package/boot/uboot-rockchip/Makefile b/package/boot/uboot-rockchip/Makefile index 1dad3c1e1c..71eac09d98 100644 --- a/package/boot/uboot-rockchip/Makefile +++ b/package/boot/uboot-rockchip/Makefile @@ -5,9 +5,9 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk -PKG_VERSION:=2023.07.02 +PKG_VERSION:=2024.01 PKG_RELEASE:=1 -PKG_HASH:=6b6a48581c14abb0f95bd87c1af4d740922406d7b801002a9f94727fdde021d5 +PKG_HASH:=b99611f1ed237bf3541bdc8434b68c96a6e05967061f992443cb30aabebef5b3 PKG_MAINTAINER:=Tobias Maedel diff --git a/package/boot/uboot-rockchip/patches/100-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus.patch b/package/boot/uboot-rockchip/patches/100-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus.patch deleted file mode 100644 index 487e6afda8..0000000000 --- a/package/boot/uboot-rockchip/patches/100-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus.patch +++ /dev/null @@ -1,594 +0,0 @@ -From 89afb631d965292aaf433806d8224b53d9e74036 Mon Sep 17 00:00:00 2001 -From: Tianling Shen -Date: Sat, 20 May 2023 18:50:38 +0800 -Subject: [PATCH] rockchip: rk3328: Add support for Orange Pi R1 Plus - -Orange Pi R1 Plus is a Rockchip RK3328 based SBC by Xunlong. - -This device is similar to the NanoPi R2S, and has a 16MB -SPI NOR (mx25l12805d). The reset button is changed to -directly reset the power supply, another detail is that -both network ports have independent MAC addresses. - -The device tree and description are taken from kernel v6.3-rc1. - -Reviewed-by: Kever Yang -Signed-off-by: Tianling Shen ---- - arch/arm/dts/Makefile | 1 + - .../dts/rk3328-orangepi-r1-plus-u-boot.dtsi | 46 +++ - arch/arm/dts/rk3328-orangepi-r1-plus.dts | 373 ++++++++++++++++++ - board/rockchip/evb_rk3328/MAINTAINERS | 6 + - configs/orangepi-r1-plus-rk3328_defconfig | 114 ++++++ - 5 files changed, 540 insertions(+) - create mode 100644 arch/arm/dts/rk3328-orangepi-r1-plus-u-boot.dtsi - create mode 100644 arch/arm/dts/rk3328-orangepi-r1-plus.dts - create mode 100644 configs/orangepi-r1-plus-rk3328_defconfig - ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -125,6 +125,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3328) += \ - rk3328-evb.dtb \ - rk3328-nanopi-r2c.dtb \ - rk3328-nanopi-r2s.dtb \ -+ rk3328-orangepi-r1-plus.dtb \ - rk3328-roc-cc.dtb \ - rk3328-rock64.dtb \ - rk3328-rock-pi-e.dtb ---- /dev/null -+++ b/arch/arm/dts/rk3328-orangepi-r1-plus-u-boot.dtsi -@@ -0,0 +1,46 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * (C) Copyright 2018-2019 Rockchip Electronics Co., Ltd -+ * (C) Copyright 2020 David Bauer -+ */ -+ -+#include "rk3328-u-boot.dtsi" -+#include "rk3328-sdram-ddr4-666.dtsi" -+/ { -+ chosen { -+ u-boot,spl-boot-order = "same-as-spl", &sdmmc, &emmc; -+ }; -+}; -+ -+&gpio0 { -+ bootph-pre-ram; -+}; -+ -+&pinctrl { -+ bootph-pre-ram; -+}; -+ -+&sdmmc0m1_pin { -+ bootph-pre-ram; -+}; -+ -+&pcfg_pull_up_4ma { -+ bootph-pre-ram; -+}; -+ -+/* Need this and all the pinctrl/gpio stuff above to set pinmux */ -+&vcc_sd { -+ bootph-pre-ram; -+}; -+ -+&gmac2io { -+ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ snps,reset-active-low; -+ snps,reset-delays-us = <0 10000 50000>; -+}; -+ -+&spi0 { -+ spi_flash: spiflash@0 { -+ bootph-all; -+ }; -+}; ---- /dev/null -+++ b/arch/arm/dts/rk3328-orangepi-r1-plus.dts -@@ -0,0 +1,373 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -+/* -+ * Based on rk3328-nanopi-r2s.dts, which is: -+ * Copyright (c) 2020 David Bauer -+ */ -+ -+/dts-v1/; -+ -+#include -+#include -+#include "rk3328.dtsi" -+ -+/ { -+ model = "Xunlong Orange Pi R1 Plus"; -+ compatible = "xunlong,orangepi-r1-plus", "rockchip,rk3328"; -+ -+ aliases { -+ ethernet1 = &rtl8153; -+ mmc0 = &sdmmc; -+ }; -+ -+ chosen { -+ stdout-path = "serial2:1500000n8"; -+ }; -+ -+ gmac_clk: gmac-clock { -+ compatible = "fixed-clock"; -+ clock-frequency = <125000000>; -+ clock-output-names = "gmac_clkin"; -+ #clock-cells = <0>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>; -+ pinctrl-names = "default"; -+ -+ led-0 { -+ function = LED_FUNCTION_LAN; -+ color = ; -+ gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-1 { -+ function = LED_FUNCTION_STATUS; -+ color = ; -+ gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "heartbeat"; -+ }; -+ -+ led-2 { -+ function = LED_FUNCTION_WAN; -+ color = ; -+ gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+ -+ vcc_sd: sdmmc-regulator { -+ compatible = "regulator-fixed"; -+ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; -+ pinctrl-0 = <&sdmmc0m1_pin>; -+ pinctrl-names = "default"; -+ regulator-name = "vcc_sd"; -+ regulator-boot-on; -+ vin-supply = <&vcc_io>; -+ }; -+ -+ vcc_sys: vcc-sys-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_sys"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ -+ vdd_5v_lan: vdd-5v-lan-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; -+ pinctrl-0 = <&lan_vdd_pin>; -+ pinctrl-names = "default"; -+ regulator-name = "vdd_5v_lan"; -+ regulator-always-on; -+ regulator-boot-on; -+ vin-supply = <&vcc_sys>; -+ }; -+}; -+ -+&cpu0 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu1 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu2 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&cpu3 { -+ cpu-supply = <&vdd_arm>; -+}; -+ -+&display_subsystem { -+ status = "disabled"; -+}; -+ -+&gmac2io { -+ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; -+ assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; -+ clock_in_out = "input"; -+ phy-handle = <&rtl8211e>; -+ phy-mode = "rgmii"; -+ phy-supply = <&vcc_io>; -+ pinctrl-0 = <&rgmiim1_pins>; -+ pinctrl-names = "default"; -+ snps,aal; -+ rx_delay = <0x18>; -+ tx_delay = <0x24>; -+ status = "okay"; -+ -+ mdio { -+ compatible = "snps,dwmac-mdio"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ rtl8211e: ethernet-phy@1 { -+ reg = <1>; -+ pinctrl-0 = <ð_phy_reset_pin>; -+ pinctrl-names = "default"; -+ reset-assert-us = <10000>; -+ reset-deassert-us = <50000>; -+ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; -+ -+&i2c1 { -+ status = "okay"; -+ -+ rk805: pmic@18 { -+ compatible = "rockchip,rk805"; -+ reg = <0x18>; -+ interrupt-parent = <&gpio1>; -+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>; -+ #clock-cells = <1>; -+ clock-output-names = "xin32k", "rk805-clkout2"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ pinctrl-0 = <&pmic_int_l>; -+ pinctrl-names = "default"; -+ rockchip,system-power-controller; -+ wakeup-source; -+ -+ vcc1-supply = <&vcc_sys>; -+ vcc2-supply = <&vcc_sys>; -+ vcc3-supply = <&vcc_sys>; -+ vcc4-supply = <&vcc_sys>; -+ vcc5-supply = <&vcc_io>; -+ vcc6-supply = <&vcc_sys>; -+ -+ regulators { -+ vdd_log: DCDC_REG1 { -+ regulator-name = "vdd_log"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <712500>; -+ regulator-max-microvolt = <1450000>; -+ regulator-ramp-delay = <12500>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ -+ vdd_arm: DCDC_REG2 { -+ regulator-name = "vdd_arm"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <712500>; -+ regulator-max-microvolt = <1450000>; -+ regulator-ramp-delay = <12500>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <950000>; -+ }; -+ }; -+ -+ vcc_ddr: DCDC_REG3 { -+ regulator-name = "vcc_ddr"; -+ regulator-always-on; -+ regulator-boot-on; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vcc_io: DCDC_REG4 { -+ regulator-name = "vcc_io"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vcc_18: LDO_REG1 { -+ regulator-name = "vcc_18"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vcc18_emmc: LDO_REG2 { -+ regulator-name = "vcc18_emmc"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vdd_10: LDO_REG3 { -+ regulator-name = "vdd_10"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1000000>; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&io_domains { -+ pmuio-supply = <&vcc_io>; -+ vccio1-supply = <&vcc_io>; -+ vccio2-supply = <&vcc18_emmc>; -+ vccio3-supply = <&vcc_io>; -+ vccio4-supply = <&vcc_io>; -+ vccio5-supply = <&vcc_io>; -+ vccio6-supply = <&vcc_io>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ gmac2io { -+ eth_phy_reset_pin: eth-phy-reset-pin { -+ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; -+ }; -+ }; -+ -+ leds { -+ lan_led_pin: lan-led-pin { -+ rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ sys_led_pin: sys-led-pin { -+ rockchip,pins = <3 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ wan_led_pin: wan-led-pin { -+ rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ lan { -+ lan_vdd_pin: lan-vdd-pin { -+ rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ pmic { -+ pmic_int_l: pmic-int-l { -+ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+}; -+ -+&pwm2 { -+ status = "okay"; -+}; -+ -+&sdmmc { -+ bus-width = <4>; -+ cap-sd-highspeed; -+ disable-wp; -+ pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>; -+ pinctrl-names = "default"; -+ vmmc-supply = <&vcc_sd>; -+ status = "okay"; -+}; -+ -+&spi0 { -+ status = "okay"; -+ -+ flash@0 { -+ compatible = "jedec,spi-nor"; -+ reg = <0>; -+ spi-max-frequency = <50000000>; -+ }; -+}; -+ -+&tsadc { -+ rockchip,hw-tshut-mode = <0>; -+ rockchip,hw-tshut-polarity = <0>; -+ status = "okay"; -+}; -+ -+&u2phy { -+ status = "okay"; -+}; -+ -+&u2phy_host { -+ status = "okay"; -+}; -+ -+&u2phy_otg { -+ status = "okay"; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&usb20_otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usbdrd3 { -+ dr_mode = "host"; -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ /* Second port is for USB 3.0 */ -+ rtl8153: device@2 { -+ compatible = "usbbda,8153"; -+ reg = <2>; -+ }; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; ---- a/board/rockchip/evb_rk3328/MAINTAINERS -+++ b/board/rockchip/evb_rk3328/MAINTAINERS -@@ -18,6 +18,12 @@ F: configs/nanopi-r2s-rk3328_defcon - F: arch/arm/dts/rk3328-nanopi-r2s-u-boot.dtsi - F: arch/arm/dts/rk3328-nanopi-r2s.dts - -+ORANGEPI-R1-PLUS-RK3328 -+M: Tianling Shen -+S: Maintained -+F: configs/orangepi-r1-plus-rk3328_defconfig -+F: arch/arm/dts/rk3328-orangepi-r1-plus-u-boot.dtsi -+ - ROC-RK3328-CC - M: Loic Devulder - M: Chen-Yu Tsai ---- /dev/null -+++ b/configs/orangepi-r1-plus-rk3328_defconfig -@@ -0,0 +1,114 @@ -+CONFIG_ARM=y -+CONFIG_SKIP_LOWLEVEL_INIT=y -+CONFIG_COUNTER_FREQUENCY=24000000 -+CONFIG_ARCH_ROCKCHIP=y -+CONFIG_TEXT_BASE=0x00200000 -+CONFIG_SPL_GPIO=y -+CONFIG_NR_DRAM_BANKS=1 -+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x300000 -+CONFIG_ENV_OFFSET=0x3F8000 -+CONFIG_DEFAULT_DEVICE_TREE="rk3328-orangepi-r1-plus" -+CONFIG_DM_RESET=y -+CONFIG_ROCKCHIP_RK3328=y -+CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y -+CONFIG_TPL_LIBCOMMON_SUPPORT=y -+CONFIG_TPL_LIBGENERIC_SUPPORT=y -+CONFIG_SPL_DRIVERS_MISC=y -+CONFIG_SPL_STACK_R_ADDR=0x600000 -+CONFIG_SPL_STACK=0x400000 -+CONFIG_TPL_SYS_MALLOC_F_LEN=0x800 -+CONFIG_DEBUG_UART_BASE=0xFF130000 -+CONFIG_DEBUG_UART_CLOCK=24000000 -+CONFIG_SYS_LOAD_ADDR=0x800800 -+CONFIG_DEBUG_UART=y -+# CONFIG_ANDROID_BOOT_IMAGE is not set -+CONFIG_FIT=y -+CONFIG_FIT_VERBOSE=y -+CONFIG_SPL_LOAD_FIT=y -+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-orangepi-r1-plus.dtb" -+# CONFIG_DISPLAY_CPUINFO is not set -+CONFIG_DISPLAY_BOARDINFO_LATE=y -+CONFIG_MISC_INIT_R=y -+CONFIG_SPL_MAX_SIZE=0x40000 -+CONFIG_SPL_PAD_TO=0x7f8000 -+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y -+CONFIG_SPL_BSS_START_ADDR=0x2000000 -+CONFIG_SPL_BSS_MAX_SIZE=0x2000 -+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set -+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set -+CONFIG_SPL_STACK_R=y -+CONFIG_SPL_I2C=y -+CONFIG_SPL_POWER=y -+CONFIG_SPL_ATF=y -+CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y -+CONFIG_TPL_SYS_MALLOC_SIMPLE=y -+CONFIG_CMD_BOOTZ=y -+CONFIG_CMD_GPT=y -+CONFIG_CMD_MMC=y -+CONFIG_CMD_USB=y -+# CONFIG_CMD_SETEXPR is not set -+CONFIG_CMD_TIME=y -+CONFIG_SPL_OF_CONTROL=y -+CONFIG_TPL_OF_CONTROL=y -+CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" -+CONFIG_TPL_OF_PLATDATA=y -+CONFIG_ENV_IS_IN_MMC=y -+CONFIG_SYS_RELOC_GD_ENV_ADDR=y -+CONFIG_SYS_MMC_ENV_DEV=1 -+CONFIG_NET_RANDOM_ETHADDR=y -+CONFIG_TPL_DM=y -+CONFIG_REGMAP=y -+CONFIG_SPL_REGMAP=y -+CONFIG_TPL_REGMAP=y -+CONFIG_SYSCON=y -+CONFIG_SPL_SYSCON=y -+CONFIG_TPL_SYSCON=y -+CONFIG_CLK=y -+CONFIG_SPL_CLK=y -+CONFIG_FASTBOOT_BUF_ADDR=0x800800 -+CONFIG_FASTBOOT_CMD_OEM_FORMAT=y -+CONFIG_ROCKCHIP_GPIO=y -+CONFIG_SYS_I2C_ROCKCHIP=y -+CONFIG_MMC_DW=y -+CONFIG_MMC_DW_ROCKCHIP=y -+CONFIG_SF_DEFAULT_SPEED=20000000 -+CONFIG_SPI_FLASH_GIGADEVICE=y -+CONFIG_ETH_DESIGNWARE=y -+CONFIG_GMAC_ROCKCHIP=y -+CONFIG_PINCTRL=y -+CONFIG_SPL_PINCTRL=y -+CONFIG_DM_PMIC=y -+CONFIG_PMIC_RK8XX=y -+CONFIG_SPL_PMIC_RK8XX=y -+CONFIG_SPL_DM_REGULATOR=y -+CONFIG_REGULATOR_PWM=y -+CONFIG_DM_REGULATOR_FIXED=y -+CONFIG_SPL_DM_REGULATOR_FIXED=y -+CONFIG_REGULATOR_RK8XX=y -+CONFIG_PWM_ROCKCHIP=y -+CONFIG_RAM=y -+CONFIG_SPL_RAM=y -+CONFIG_TPL_RAM=y -+CONFIG_BAUDRATE=1500000 -+CONFIG_DEBUG_UART_SHIFT=2 -+CONFIG_SYS_NS16550_MEM32=y -+CONFIG_ROCKCHIP_SPI=y -+CONFIG_SYSINFO=y -+CONFIG_SYSRESET=y -+# CONFIG_TPL_SYSRESET is not set -+CONFIG_USB=y -+CONFIG_USB_XHCI_HCD=y -+CONFIG_USB_XHCI_DWC3=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_EHCI_GENERIC=y -+CONFIG_USB_OHCI_HCD=y -+CONFIG_USB_OHCI_GENERIC=y -+CONFIG_USB_DWC2=y -+CONFIG_USB_DWC3=y -+# CONFIG_USB_DWC3_GADGET is not set -+CONFIG_USB_GADGET=y -+CONFIG_USB_GADGET_DWC2_OTG=y -+CONFIG_SPL_TINY_MEMSET=y -+CONFIG_TPL_TINY_MEMSET=y -+CONFIG_ERRNO_STR=y diff --git a/package/boot/uboot-rockchip/patches/101-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus-LT.patch b/package/boot/uboot-rockchip/patches/101-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus-LT.patch deleted file mode 100644 index 56d36c74dc..0000000000 --- a/package/boot/uboot-rockchip/patches/101-rockchip-rk3328-Add-support-for-Orange-Pi-R1-Plus-LT.patch +++ /dev/null @@ -1,257 +0,0 @@ -From 408fd4570c0f1e6b1fe3722998394651144f2a29 Mon Sep 17 00:00:00 2001 -From: Tianling Shen -Date: Sat, 20 May 2023 18:52:14 +0800 -Subject: [PATCH] rockchip: rk3328: Add support for Orange Pi R1 Plus LTS - -The OrangePi R1 Plus LTS is a minor variant of OrangePi R1 Plus with -the on-board NIC chip changed from rtl8211e to yt8531c, and RAM type -changed from DDR4 to LPDDR3. - -The device tree is taken from kernel v6.4-rc1. - -Signed-off-by: Tianling Shen ---- - arch/arm/dts/Makefile | 1 + - .../rk3328-orangepi-r1-plus-lts-u-boot.dtsi | 46 +++++++ - arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts | 40 ++++++ - board/rockchip/evb_rk3328/MAINTAINERS | 6 + - configs/orangepi-r1-plus-lts-rk3328_defconfig | 114 ++++++++++++++++++ - 5 files changed, 207 insertions(+) - create mode 100644 arch/arm/dts/rk3328-orangepi-r1-plus-lts-u-boot.dtsi - create mode 100644 arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts - create mode 100644 configs/orangepi-r1-plus-lts-rk3328_defconfig - ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -126,6 +126,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3328) += \ - rk3328-nanopi-r2c.dtb \ - rk3328-nanopi-r2s.dtb \ - rk3328-orangepi-r1-plus.dtb \ -+ rk3328-orangepi-r1-plus-lts.dtb \ - rk3328-roc-cc.dtb \ - rk3328-rock64.dtb \ - rk3328-rock-pi-e.dtb ---- /dev/null -+++ b/arch/arm/dts/rk3328-orangepi-r1-plus-lts-u-boot.dtsi -@@ -0,0 +1,46 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * (C) Copyright 2018-2019 Rockchip Electronics Co., Ltd -+ * (C) Copyright 2020 David Bauer -+ */ -+ -+#include "rk3328-u-boot.dtsi" -+#include "rk3328-sdram-lpddr3-666.dtsi" -+/ { -+ chosen { -+ u-boot,spl-boot-order = "same-as-spl", &sdmmc, &emmc; -+ }; -+}; -+ -+&gpio0 { -+ bootph-pre-ram; -+}; -+ -+&pinctrl { -+ bootph-pre-ram; -+}; -+ -+&sdmmc0m1_pin { -+ bootph-pre-ram; -+}; -+ -+&pcfg_pull_up_4ma { -+ bootph-pre-ram; -+}; -+ -+/* Need this and all the pinctrl/gpio stuff above to set pinmux */ -+&vcc_sd { -+ bootph-pre-ram; -+}; -+ -+&gmac2io { -+ snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ snps,reset-active-low; -+ snps,reset-delays-us = <0 10000 50000>; -+}; -+ -+&spi0 { -+ spi_flash: spiflash@0 { -+ bootph-all; -+ }; -+}; ---- /dev/null -+++ b/arch/arm/dts/rk3328-orangepi-r1-plus-lts.dts -@@ -0,0 +1,40 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/* -+ * Copyright (c) 2016 Xunlong Software. Co., Ltd. -+ * (http://www.orangepi.org) -+ * -+ * Copyright (c) 2021-2023 Tianling Shen -+ */ -+ -+/dts-v1/; -+#include "rk3328-orangepi-r1-plus.dts" -+ -+/ { -+ model = "Xunlong Orange Pi R1 Plus LTS"; -+ compatible = "xunlong,orangepi-r1-plus-lts", "rockchip,rk3328"; -+}; -+ -+&gmac2io { -+ phy-handle = <&yt8531c>; -+ tx_delay = <0x19>; -+ rx_delay = <0x05>; -+ -+ mdio { -+ /delete-node/ ethernet-phy@1; -+ -+ yt8531c: ethernet-phy@0 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <0>; -+ -+ motorcomm,clk-out-frequency-hz = <125000000>; -+ motorcomm,keep-pll-enabled; -+ motorcomm,auto-sleep-disabled; -+ -+ pinctrl-0 = <ð_phy_reset_pin>; -+ pinctrl-names = "default"; -+ reset-assert-us = <15000>; -+ reset-deassert-us = <50000>; -+ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; ---- a/board/rockchip/evb_rk3328/MAINTAINERS -+++ b/board/rockchip/evb_rk3328/MAINTAINERS -@@ -24,6 +24,12 @@ S: Maintained - F: configs/orangepi-r1-plus-rk3328_defconfig - F: arch/arm/dts/rk3328-orangepi-r1-plus-u-boot.dtsi - -+ORANGEPI-R1-PLUS-LTS-RK3328 -+M: Tianling Shen -+S: Maintained -+F: configs/orangepi-r1-plus-lts-rk3328_defconfig -+F: arch/arm/dts/rk3328-orangepi-r1-plus-lts-u-boot.dtsi -+ - ROC-RK3328-CC - M: Loic Devulder - M: Chen-Yu Tsai ---- /dev/null -+++ b/configs/orangepi-r1-plus-lts-rk3328_defconfig -@@ -0,0 +1,114 @@ -+CONFIG_ARM=y -+CONFIG_SKIP_LOWLEVEL_INIT=y -+CONFIG_COUNTER_FREQUENCY=24000000 -+CONFIG_ARCH_ROCKCHIP=y -+CONFIG_TEXT_BASE=0x00200000 -+CONFIG_SPL_GPIO=y -+CONFIG_NR_DRAM_BANKS=1 -+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x300000 -+CONFIG_ENV_OFFSET=0x3F8000 -+CONFIG_DEFAULT_DEVICE_TREE="rk3328-orangepi-r1-plus-lts" -+CONFIG_DM_RESET=y -+CONFIG_ROCKCHIP_RK3328=y -+CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y -+CONFIG_TPL_LIBCOMMON_SUPPORT=y -+CONFIG_TPL_LIBGENERIC_SUPPORT=y -+CONFIG_SPL_DRIVERS_MISC=y -+CONFIG_SPL_STACK_R_ADDR=0x600000 -+CONFIG_SPL_STACK=0x400000 -+CONFIG_TPL_SYS_MALLOC_F_LEN=0x800 -+CONFIG_DEBUG_UART_BASE=0xFF130000 -+CONFIG_DEBUG_UART_CLOCK=24000000 -+CONFIG_SYS_LOAD_ADDR=0x800800 -+CONFIG_DEBUG_UART=y -+# CONFIG_ANDROID_BOOT_IMAGE is not set -+CONFIG_FIT=y -+CONFIG_FIT_VERBOSE=y -+CONFIG_SPL_LOAD_FIT=y -+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-orangepi-r1-plus-lts.dtb" -+# CONFIG_DISPLAY_CPUINFO is not set -+CONFIG_DISPLAY_BOARDINFO_LATE=y -+CONFIG_MISC_INIT_R=y -+CONFIG_SPL_MAX_SIZE=0x40000 -+CONFIG_SPL_PAD_TO=0x7f8000 -+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y -+CONFIG_SPL_BSS_START_ADDR=0x2000000 -+CONFIG_SPL_BSS_MAX_SIZE=0x2000 -+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set -+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set -+CONFIG_SPL_STACK_R=y -+CONFIG_SPL_I2C=y -+CONFIG_SPL_POWER=y -+CONFIG_SPL_ATF=y -+CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y -+CONFIG_TPL_SYS_MALLOC_SIMPLE=y -+CONFIG_CMD_BOOTZ=y -+CONFIG_CMD_GPT=y -+CONFIG_CMD_MMC=y -+CONFIG_CMD_USB=y -+# CONFIG_CMD_SETEXPR is not set -+CONFIG_CMD_TIME=y -+CONFIG_SPL_OF_CONTROL=y -+CONFIG_TPL_OF_CONTROL=y -+CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" -+CONFIG_TPL_OF_PLATDATA=y -+CONFIG_ENV_IS_IN_MMC=y -+CONFIG_SYS_RELOC_GD_ENV_ADDR=y -+CONFIG_SYS_MMC_ENV_DEV=1 -+CONFIG_NET_RANDOM_ETHADDR=y -+CONFIG_TPL_DM=y -+CONFIG_REGMAP=y -+CONFIG_SPL_REGMAP=y -+CONFIG_TPL_REGMAP=y -+CONFIG_SYSCON=y -+CONFIG_SPL_SYSCON=y -+CONFIG_TPL_SYSCON=y -+CONFIG_CLK=y -+CONFIG_SPL_CLK=y -+CONFIG_FASTBOOT_BUF_ADDR=0x800800 -+CONFIG_FASTBOOT_CMD_OEM_FORMAT=y -+CONFIG_ROCKCHIP_GPIO=y -+CONFIG_SYS_I2C_ROCKCHIP=y -+CONFIG_MMC_DW=y -+CONFIG_MMC_DW_ROCKCHIP=y -+CONFIG_SF_DEFAULT_SPEED=20000000 -+CONFIG_SPI_FLASH_GIGADEVICE=y -+CONFIG_ETH_DESIGNWARE=y -+CONFIG_GMAC_ROCKCHIP=y -+CONFIG_PINCTRL=y -+CONFIG_SPL_PINCTRL=y -+CONFIG_DM_PMIC=y -+CONFIG_PMIC_RK8XX=y -+CONFIG_SPL_PMIC_RK8XX=y -+CONFIG_SPL_DM_REGULATOR=y -+CONFIG_REGULATOR_PWM=y -+CONFIG_DM_REGULATOR_FIXED=y -+CONFIG_SPL_DM_REGULATOR_FIXED=y -+CONFIG_REGULATOR_RK8XX=y -+CONFIG_PWM_ROCKCHIP=y -+CONFIG_RAM=y -+CONFIG_SPL_RAM=y -+CONFIG_TPL_RAM=y -+CONFIG_BAUDRATE=1500000 -+CONFIG_DEBUG_UART_SHIFT=2 -+CONFIG_SYS_NS16550_MEM32=y -+CONFIG_ROCKCHIP_SPI=y -+CONFIG_SYSINFO=y -+CONFIG_SYSRESET=y -+# CONFIG_TPL_SYSRESET is not set -+CONFIG_USB=y -+CONFIG_USB_XHCI_HCD=y -+CONFIG_USB_XHCI_DWC3=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_EHCI_GENERIC=y -+CONFIG_USB_OHCI_HCD=y -+CONFIG_USB_OHCI_GENERIC=y -+CONFIG_USB_DWC2=y -+CONFIG_USB_DWC3=y -+# CONFIG_USB_DWC3_GADGET is not set -+CONFIG_USB_GADGET=y -+CONFIG_USB_GADGET_DWC2_OTG=y -+CONFIG_SPL_TINY_MEMSET=y -+CONFIG_TPL_TINY_MEMSET=y -+CONFIG_ERRNO_STR=y diff --git a/package/boot/uboot-rockchip/patches/103-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch b/package/boot/uboot-rockchip/patches/103-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch deleted file mode 100644 index 09cafb3227..0000000000 --- a/package/boot/uboot-rockchip/patches/103-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch +++ /dev/null @@ -1,917 +0,0 @@ -From c84214aab0e4c5b2f619dd89655f27b3ae40e82b Mon Sep 17 00:00:00 2001 -From: Tianling Shen -Date: Tue, 30 May 2023 15:00:33 +0800 -Subject: [PATCH] rockchip: rk3568: Add support for FriendlyARM NanoPi R5S - -FriendlyARM NanoPi R5S is an open-sourced mini IoT gateway device. - -Board Specifications -- Rockchip RK3568 -- 2 or 4GB LPDDR4X -- 8GB or 16GB eMMC, SD card slot -- GbE LAN (Native) -- 2x 2.5G LAN (PCIe) -- M.2 Connector -- HDMI 2.0, MIPI DSI/CSI -- 2xUSB 3.0 Host -- USB Type C PD, 5V/9V/12V -- GPIO: 12-pin 0.5mm FPC connector - -The device tree is taken from kernel v6.4-rc1. - -Reviewed-by: Kever Yang -Signed-off-by: Tianling Shen ---- - arch/arm/dts/Makefile | 1 + - arch/arm/dts/rk3568-nanopi-r5s-u-boot.dtsi | 31 ++ - arch/arm/dts/rk3568-nanopi-r5s.dts | 136 +++++ - arch/arm/dts/rk3568-nanopi-r5s.dtsi | 590 +++++++++++++++++++++ - board/rockchip/evb_rk3568/MAINTAINERS | 8 + - configs/nanopi-r5s-rk3568_defconfig | 85 +++ - 6 files changed, 851 insertions(+) - create mode 100644 arch/arm/dts/rk3568-nanopi-r5s-u-boot.dtsi - create mode 100644 arch/arm/dts/rk3568-nanopi-r5s.dts - create mode 100644 arch/arm/dts/rk3568-nanopi-r5s.dtsi - create mode 100644 configs/nanopi-r5s-rk3568_defconfig - ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -171,6 +171,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3568) += \ - rk3566-anbernic-rgxx3.dtb \ - rk3566-radxa-cm3-io.dtb \ - rk3568-evb.dtb \ -+ rk3568-nanopi-r5s.dtb \ - rk3568-rock-3a.dtb - - dtb-$(CONFIG_ROCKCHIP_RK3588) += \ ---- /dev/null -+++ b/arch/arm/dts/rk3568-nanopi-r5s-u-boot.dtsi -@@ -0,0 +1,31 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/* -+ * Copyright (c) 2022 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyelec.com) -+ * -+ * Copyright (c) 2023 Tianling Shen -+ */ -+ -+#include "rk356x-u-boot.dtsi" -+ -+/ { -+ chosen { -+ stdout-path = &uart2; -+ u-boot,spl-boot-order = "same-as-spl", &sdmmc0, &sdhci; -+ }; -+}; -+ -+&sdhci { -+ cap-mmc-highspeed; -+ mmc-ddr-1_8v; -+ mmc-hs200-1_8v; -+ mmc-hs400-1_8v; -+ mmc-hs400-enhanced-strobe; -+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>; -+}; -+ -+&uart2 { -+ clock-frequency = <24000000>; -+ bootph-all; -+ status = "okay"; -+}; ---- /dev/null -+++ b/arch/arm/dts/rk3568-nanopi-r5s.dts -@@ -0,0 +1,136 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/* -+ * Copyright (c) 2022 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyelec.com) -+ * -+ * Copyright (c) 2023 Tianling Shen -+ */ -+ -+/dts-v1/; -+#include "rk3568-nanopi-r5s.dtsi" -+ -+/ { -+ model = "FriendlyElec NanoPi R5S"; -+ compatible = "friendlyarm,nanopi-r5s", "rockchip,rk3568"; -+ -+ aliases { -+ ethernet0 = &gmac0; -+ }; -+ -+ gpio-leds { -+ compatible = "gpio-leds"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&lan1_led_pin>, <&lan2_led_pin>, <&power_led_pin>, <&wan_led_pin>; -+ -+ led-lan1 { -+ color = ; -+ function = LED_FUNCTION_LAN; -+ function-enumerator = <1>; -+ gpios = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-lan2 { -+ color = ; -+ function = LED_FUNCTION_LAN; -+ function-enumerator = <2>; -+ gpios = <&gpio3 RK_PD7 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ power_led: led-power { -+ color = ; -+ function = LED_FUNCTION_POWER; -+ linux,default-trigger = "heartbeat"; -+ gpios = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-wan { -+ color = ; -+ function = LED_FUNCTION_WAN; -+ gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+}; -+ -+&gmac0 { -+ assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>; -+ assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>, <&cru CLK_MAC0_2TOP>; -+ assigned-clock-rates = <0>, <125000000>; -+ clock_in_out = "output"; -+ phy-handle = <&rgmii_phy0>; -+ phy-mode = "rgmii"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&gmac0_miim -+ &gmac0_tx_bus2 -+ &gmac0_rx_bus2 -+ &gmac0_rgmii_clk -+ &gmac0_rgmii_bus>; -+ snps,reset-gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_LOW>; -+ snps,reset-active-low; -+ /* Reset time is 15ms, 50ms for rtl8211f */ -+ snps,reset-delays-us = <0 15000 50000>; -+ tx_delay = <0x3c>; -+ rx_delay = <0x2f>; -+ status = "okay"; -+}; -+ -+&mdio0 { -+ rgmii_phy0: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <1>; -+ pinctrl-0 = <ð_phy0_reset_pin>; -+ pinctrl-names = "default"; -+ }; -+}; -+ -+&pcie2x1 { -+ num-lanes = <1>; -+ reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+}; -+ -+&pcie30phy { -+ data-lanes = <1 2>; -+ status = "okay"; -+}; -+ -+&pcie3x1 { -+ num-lanes = <1>; -+ reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; -+ vpcie3v3-supply = <&vcc3v3_pcie>; -+ status = "okay"; -+}; -+ -+&pcie3x2 { -+ num-lanes = <1>; -+ num-ib-windows = <8>; -+ num-ob-windows = <8>; -+ reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>; -+ vpcie3v3-supply = <&vcc3v3_pcie>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ gmac0 { -+ eth_phy0_reset_pin: eth-phy0-reset-pin { -+ rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ gpio-leds { -+ lan1_led_pin: lan1-led-pin { -+ rockchip,pins = <3 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ lan2_led_pin: lan2-led-pin { -+ rockchip,pins = <3 RK_PD7 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ power_led_pin: power-led-pin { -+ rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ wan_led_pin: wan-led-pin { -+ rockchip,pins = <2 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm/dts/rk3568-nanopi-r5s.dtsi -@@ -0,0 +1,590 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/* -+ * Copyright (c) 2022 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyelec.com) -+ * -+ * Copyright (c) 2023 Tianling Shen -+ */ -+ -+/dts-v1/; -+#include -+#include -+#include -+#include -+#include -+#include "rk3568.dtsi" -+ -+/ { -+ aliases { -+ mmc0 = &sdmmc0; -+ mmc1 = &sdhci; -+ }; -+ -+ chosen: chosen { -+ stdout-path = "serial2:1500000n8"; -+ }; -+ -+ hdmi-con { -+ compatible = "hdmi-connector"; -+ type = "a"; -+ -+ port { -+ hdmi_con_in: endpoint { -+ remote-endpoint = <&hdmi_out_con>; -+ }; -+ }; -+ }; -+ -+ vdd_usbc: vdd-usbc-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vdd_usbc"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ -+ vcc3v3_sys: vcc3v3-sys-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc3v3_sys"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ vin-supply = <&vdd_usbc>; -+ }; -+ -+ vcc5v0_sys: vcc5v0-sys-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_sys"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ vin-supply = <&vdd_usbc>; -+ }; -+ -+ vcc3v3_pcie: vcc3v3-pcie-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc3v3_pcie"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ enable-active-high; -+ gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>; -+ startup-delay-us = <200000>; -+ vin-supply = <&vcc5v0_sys>; -+ }; -+ -+ vcc5v0_usb: vcc5v0-usb-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_usb"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ vin-supply = <&vdd_usbc>; -+ }; -+ -+ vcc5v0_usb_host: vcc5v0-usb-host-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&vcc5v0_usb_host_en>; -+ regulator-name = "vcc5v0_usb_host"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ vin-supply = <&vcc5v0_usb>; -+ }; -+ -+ vcc5v0_usb_otg: vcc5v0-usb-otg-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&vcc5v0_usb_otg_en>; -+ regulator-name = "vcc5v0_usb_otg"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ vin-supply = <&vcc5v0_usb>; -+ }; -+ -+ pcie30_avdd0v9: pcie30-avdd0v9-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "pcie30_avdd0v9"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <900000>; -+ vin-supply = <&vcc3v3_sys>; -+ }; -+ -+ pcie30_avdd1v8: pcie30-avdd1v8-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "pcie30_avdd1v8"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ vin-supply = <&vcc3v3_sys>; -+ }; -+}; -+ -+&combphy0 { -+ status = "okay"; -+}; -+ -+&combphy1 { -+ status = "okay"; -+}; -+ -+&combphy2 { -+ status = "okay"; -+}; -+ -+&cpu0 { -+ cpu-supply = <&vdd_cpu>; -+}; -+ -+&cpu1 { -+ cpu-supply = <&vdd_cpu>; -+}; -+ -+&cpu2 { -+ cpu-supply = <&vdd_cpu>; -+}; -+ -+&cpu3 { -+ cpu-supply = <&vdd_cpu>; -+}; -+ -+&gpu { -+ mali-supply = <&vdd_gpu>; -+ status = "okay"; -+}; -+ -+&hdmi { -+ avdd-0v9-supply = <&vdda0v9_image>; -+ avdd-1v8-supply = <&vcca1v8_image>; -+ status = "okay"; -+}; -+ -+&hdmi_in { -+ hdmi_in_vp0: endpoint { -+ remote-endpoint = <&vp0_out_hdmi>; -+ }; -+}; -+ -+&hdmi_out { -+ hdmi_out_con: endpoint { -+ remote-endpoint = <&hdmi_con_in>; -+ }; -+}; -+ -+&hdmi_sound { -+ status = "okay"; -+}; -+ -+&i2c0 { -+ status = "okay"; -+ -+ vdd_cpu: regulator@1c { -+ compatible = "tcs,tcs4525"; -+ reg = <0x1c>; -+ fcs,suspend-voltage-selector = <1>; -+ regulator-name = "vdd_cpu"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1150000>; -+ regulator-ramp-delay = <2300>; -+ vin-supply = <&vcc5v0_sys>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ rk809: pmic@20 { -+ compatible = "rockchip,rk809"; -+ reg = <0x20>; -+ interrupt-parent = <&gpio0>; -+ interrupts = ; -+ #clock-cells = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pmic_int>; -+ rockchip,system-power-controller; -+ vcc1-supply = <&vcc3v3_sys>; -+ vcc2-supply = <&vcc3v3_sys>; -+ vcc3-supply = <&vcc3v3_sys>; -+ vcc4-supply = <&vcc3v3_sys>; -+ vcc5-supply = <&vcc3v3_sys>; -+ vcc6-supply = <&vcc3v3_sys>; -+ vcc7-supply = <&vcc3v3_sys>; -+ vcc8-supply = <&vcc3v3_sys>; -+ vcc9-supply = <&vcc3v3_sys>; -+ wakeup-source; -+ -+ regulators { -+ vdd_logic: DCDC_REG1 { -+ regulator-name = "vdd_logic"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-init-microvolt = <900000>; -+ regulator-initial-mode = <0x2>; -+ regulator-min-microvolt = <500000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-ramp-delay = <6001>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdd_gpu: DCDC_REG2 { -+ regulator-name = "vdd_gpu"; -+ regulator-always-on; -+ regulator-init-microvolt = <900000>; -+ regulator-initial-mode = <0x2>; -+ regulator-min-microvolt = <500000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-ramp-delay = <6001>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc_ddr: DCDC_REG3 { -+ regulator-name = "vcc_ddr"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-initial-mode = <0x2>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vdd_npu: DCDC_REG4 { -+ regulator-name = "vdd_npu"; -+ regulator-init-microvolt = <900000>; -+ regulator-initial-mode = <0x2>; -+ regulator-min-microvolt = <500000>; -+ regulator-max-microvolt = <1350000>; -+ regulator-ramp-delay = <6001>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc_1v8: DCDC_REG5 { -+ regulator-name = "vcc_1v8"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdda0v9_image: LDO_REG1 { -+ regulator-name = "vdda0v9_image"; -+ regulator-min-microvolt = <950000>; -+ regulator-max-microvolt = <950000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdda_0v9: LDO_REG2 { -+ regulator-name = "vdda_0v9"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <900000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdda0v9_pmu: LDO_REG3 { -+ regulator-name = "vdda0v9_pmu"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <900000>; -+ regulator-max-microvolt = <900000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <900000>; -+ }; -+ }; -+ -+ vccio_acodec: LDO_REG4 { -+ regulator-name = "vccio_acodec"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vccio_sd: LDO_REG5 { -+ regulator-name = "vccio_sd"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc3v3_pmu: LDO_REG6 { -+ regulator-name = "vcc3v3_pmu"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vcca_1v8: LDO_REG7 { -+ regulator-name = "vcca_1v8"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcca1v8_pmu: LDO_REG8 { -+ regulator-name = "vcca1v8_pmu"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vcca1v8_image: LDO_REG9 { -+ regulator-name = "vcca1v8_image"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc_3v3: SWITCH_REG1 { -+ regulator-name = "vcc_3v3"; -+ regulator-always-on; -+ regulator-boot-on; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc3v3_sd: SWITCH_REG2 { -+ regulator-name = "vcc3v3_sd"; -+ regulator-always-on; -+ regulator-boot-on; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ }; -+ -+ }; -+}; -+ -+&i2c5 { -+ status = "okay"; -+ -+ hym8563: rtc@51 { -+ compatible = "haoyu,hym8563"; -+ reg = <0x51>; -+ interrupt-parent = <&gpio0>; -+ interrupts = ; -+ #clock-cells = <0>; -+ clock-output-names = "rtcic_32kout"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hym8563_int>; -+ wakeup-source; -+ }; -+}; -+ -+&i2s0_8ch { -+ status = "okay"; -+}; -+ -+&pcie30phy { -+ data-lanes = <1 2>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ hym8563 { -+ hym8563_int: hym8563-int { -+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ pmic { -+ pmic_int: pmic-int { -+ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ usb { -+ vcc5v0_usb_host_en: vcc5v0-usb-host-en { -+ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ vcc5v0_usb_otg_en: vcc5v0-usb-otg-en { -+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; -+ -+&pmu_io_domains { -+ pmuio1-supply = <&vcc3v3_pmu>; -+ pmuio2-supply = <&vcc3v3_pmu>; -+ vccio1-supply = <&vccio_acodec>; -+ vccio3-supply = <&vccio_sd>; -+ vccio4-supply = <&vcc_1v8>; -+ vccio5-supply = <&vcc_3v3>; -+ vccio6-supply = <&vcc_1v8>; -+ vccio7-supply = <&vcc_3v3>; -+ status = "okay"; -+}; -+ -+&saradc { -+ vref-supply = <&vcca_1v8>; -+ status = "okay"; -+}; -+ -+&sdhci { -+ bus-width = <8>; -+ max-frequency = <200000000>; -+ non-removable; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd>; -+ status = "okay"; -+}; -+ -+&sdmmc0 { -+ max-frequency = <150000000>; -+ no-sdio; -+ no-mmc; -+ bus-width = <4>; -+ cap-mmc-highspeed; -+ cap-sd-highspeed; -+ disable-wp; -+ vmmc-supply = <&vcc3v3_sd>; -+ vqmmc-supply = <&vccio_sd>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; -+ status = "okay"; -+}; -+ -+&tsadc { -+ rockchip,hw-tshut-mode = <1>; -+ rockchip,hw-tshut-polarity = <0>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&usb_host0_xhci { -+ extcon = <&usb2phy0>; -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usb_host1_ehci { -+ status = "okay"; -+}; -+ -+&usb_host1_ohci { -+ status = "okay"; -+}; -+ -+&usb_host1_xhci { -+ status = "okay"; -+}; -+ -+&usb2phy0 { -+ status = "okay"; -+}; -+ -+&usb2phy0_host { -+ phy-supply = <&vcc5v0_usb_host>; -+ status = "okay"; -+}; -+ -+&usb2phy0_otg { -+ status = "okay"; -+}; -+ -+&usb2phy1 { -+ status = "okay"; -+}; -+ -+&usb2phy1_host { -+ phy-supply = <&vcc5v0_usb_otg>; -+ status = "okay"; -+}; -+ -+&usb2phy1_otg { -+ status = "okay"; -+}; -+ -+&vop { -+ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>; -+ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>; -+ status = "okay"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; -+ -+&vp0 { -+ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { -+ reg = ; -+ remote-endpoint = <&hdmi_in_vp0>; -+ }; -+}; ---- a/board/rockchip/evb_rk3568/MAINTAINERS -+++ b/board/rockchip/evb_rk3568/MAINTAINERS -@@ -7,6 +7,14 @@ F: configs/evb-rk3568_defconfig - F: arch/arm/dts/rk3568-evb-boot.dtsi - F: arch/arm/dts/rk3568-evb.dts - -+NANOPI-R5S -+M: Tianling Shen -+S: Maintained -+F: configs/nanopi-r5s-rk3568_defconfig -+F: arch/arm/dts/rk3568-nanopi-r5s.dts -+F: arch/arm/dts/rk3568-nanopi-r5s.dtsi -+F: arch/arm/dts/rk3568-nanopi-r5s-u-boot.dtsi -+ - RADXA-CM3 - M: Jagan Teki - S: Maintained ---- /dev/null -+++ b/configs/nanopi-r5s-rk3568_defconfig -@@ -0,0 +1,85 @@ -+CONFIG_ARM=y -+CONFIG_SKIP_LOWLEVEL_INIT=y -+CONFIG_COUNTER_FREQUENCY=24000000 -+CONFIG_ARCH_ROCKCHIP=y -+CONFIG_TEXT_BASE=0x00a00000 -+CONFIG_SPL_LIBCOMMON_SUPPORT=y -+CONFIG_SPL_LIBGENERIC_SUPPORT=y -+CONFIG_NR_DRAM_BANKS=2 -+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000 -+CONFIG_DEFAULT_DEVICE_TREE="rk3568-nanopi-r5s" -+CONFIG_ROCKCHIP_RK3568=y -+CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y -+CONFIG_SPL_SERIAL=y -+CONFIG_SPL_STACK_R_ADDR=0x600000 -+CONFIG_TARGET_EVB_RK3568=y -+CONFIG_SPL_STACK=0x400000 -+CONFIG_DEBUG_UART_BASE=0xFE660000 -+CONFIG_DEBUG_UART_CLOCK=24000000 -+CONFIG_SYS_LOAD_ADDR=0xc00800 -+CONFIG_DEBUG_UART=y -+CONFIG_FIT=y -+CONFIG_FIT_VERBOSE=y -+CONFIG_SPL_LOAD_FIT=y -+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-nanopi-r5s.dtb" -+# CONFIG_DISPLAY_CPUINFO is not set -+CONFIG_DISPLAY_BOARDINFO_LATE=y -+CONFIG_SPL_MAX_SIZE=0x40000 -+CONFIG_SPL_PAD_TO=0x7f8000 -+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y -+CONFIG_SPL_BSS_START_ADDR=0x4000000 -+CONFIG_SPL_BSS_MAX_SIZE=0x4000 -+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set -+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set -+CONFIG_SPL_STACK_R=y -+CONFIG_SPL_ATF=y -+CONFIG_CMD_GPIO=y -+CONFIG_CMD_GPT=y -+CONFIG_CMD_I2C=y -+CONFIG_CMD_MMC=y -+CONFIG_CMD_USB=y -+CONFIG_CMD_PMIC=y -+CONFIG_CMD_REGULATOR=y -+# CONFIG_SPL_DOS_PARTITION is not set -+CONFIG_SPL_OF_CONTROL=y -+CONFIG_OF_LIVE=y -+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" -+CONFIG_SPL_DM_WARN=y -+CONFIG_SPL_REGMAP=y -+CONFIG_SPL_SYSCON=y -+CONFIG_SPL_CLK=y -+CONFIG_ROCKCHIP_GPIO=y -+CONFIG_SYS_I2C_ROCKCHIP=y -+CONFIG_MISC=y -+CONFIG_SUPPORT_EMMC_RPMB=y -+CONFIG_MMC_DW=y -+CONFIG_MMC_DW_ROCKCHIP=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_SDMA=y -+CONFIG_MMC_SDHCI_ROCKCHIP=y -+CONFIG_ETH_DESIGNWARE=y -+CONFIG_GMAC_ROCKCHIP=y -+CONFIG_PHY_ROCKCHIP_INNO_USB2=y -+CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y -+CONFIG_POWER_DOMAIN=y -+CONFIG_DM_PMIC=y -+CONFIG_PMIC_RK8XX=y -+CONFIG_SPL_DM_REGULATOR_FIXED=y -+CONFIG_REGULATOR_RK8XX=y -+CONFIG_PWM_ROCKCHIP=y -+CONFIG_SPL_RAM=y -+CONFIG_BAUDRATE=1500000 -+CONFIG_DEBUG_UART_SHIFT=2 -+CONFIG_SYS_NS16550_MEM32=y -+CONFIG_SYSRESET=y -+CONFIG_SYSRESET_PSCI=y -+CONFIG_USB=y -+CONFIG_USB_XHCI_HCD=y -+CONFIG_USB_XHCI_DWC3=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_EHCI_GENERIC=y -+CONFIG_USB_OHCI_HCD=y -+CONFIG_USB_OHCI_GENERIC=y -+CONFIG_USB_DWC3=y -+CONFIG_ERRNO_STR=y diff --git a/package/boot/uboot-rockchip/patches/104-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch b/package/boot/uboot-rockchip/patches/104-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch deleted file mode 100644 index d1a5197e7d..0000000000 --- a/package/boot/uboot-rockchip/patches/104-rockchip-rk3568-Add-support-for-FriendlyARM-NanoPi-R.patch +++ /dev/null @@ -1,269 +0,0 @@ -From 41538742491c46100f570680c02fbdd0d2b6b880 Mon Sep 17 00:00:00 2001 -From: Tianling Shen -Date: Tue, 30 May 2023 15:00:33 +0800 -Subject: [PATCH] rockchip: rk3568: Add support for FriendlyARM NanoPi R5C - -FriendlyARM NanoPi R5C is an open-sourced mini IoT gateway device. - -Specification: -- Rockchip RK3568 -- 1/4GB LPDDR4X RAM -- 8/32GB eMMC -- SD card slot -- M.2 Connector -- 2x USB 3.0 Port -- 2x 2500 Base-T (PCIe, r8125) -- HDMI 2.0 -- MIPI DSI/CSI -- USB Type C 5V - -The device tree is taken from kernel v6.4-rc1. - -Reviewed-by: Kever Yang -Signed-off-by: Tianling Shen ---- - arch/arm/dts/Makefile | 1 + - arch/arm/dts/rk3568-nanopi-r5c-u-boot.dtsi | 3 + - arch/arm/dts/rk3568-nanopi-r5c.dts | 112 +++++++++++++++++++++ - board/rockchip/evb_rk3568/MAINTAINERS | 7 ++ - configs/nanopi-r5c-rk3568_defconfig | 85 ++++++++++++++++ - 5 files changed, 208 insertions(+) - create mode 100644 arch/arm/dts/rk3568-nanopi-r5c-u-boot.dtsi - create mode 100644 arch/arm/dts/rk3568-nanopi-r5c.dts - create mode 100644 configs/nanopi-r5c-rk3568_defconfig - ---- a/arch/arm/dts/Makefile -+++ b/arch/arm/dts/Makefile -@@ -171,6 +171,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3568) += \ - rk3566-anbernic-rgxx3.dtb \ - rk3566-radxa-cm3-io.dtb \ - rk3568-evb.dtb \ -+ rk3568-nanopi-r5c.dtb \ - rk3568-nanopi-r5s.dtb \ - rk3568-rock-3a.dtb - ---- /dev/null -+++ b/arch/arm/dts/rk3568-nanopi-r5c-u-boot.dtsi -@@ -0,0 +1,3 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+ -+#include "rk3568-nanopi-r5s-u-boot.dtsi" ---- /dev/null -+++ b/arch/arm/dts/rk3568-nanopi-r5c.dts -@@ -0,0 +1,112 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -+/* -+ * Copyright (c) 2022 FriendlyElec Computer Tech. Co., Ltd. -+ * (http://www.friendlyelec.com) -+ * -+ * Copyright (c) 2023 Tianling Shen -+ */ -+ -+/dts-v1/; -+#include "rk3568-nanopi-r5s.dtsi" -+ -+/ { -+ model = "FriendlyElec NanoPi R5C"; -+ compatible = "friendlyarm,nanopi-r5c", "rockchip,rk3568"; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&reset_button_pin>; -+ -+ button-reset { -+ debounce-interval = <50>; -+ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_LOW>; -+ label = "reset"; -+ linux,code = ; -+ }; -+ }; -+ -+ gpio-leds { -+ compatible = "gpio-leds"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&lan_led_pin>, <&power_led_pin>, <&wan_led_pin>, <&wlan_led_pin>; -+ -+ led-lan { -+ color = ; -+ function = LED_FUNCTION_LAN; -+ gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ power_led: led-power { -+ color = ; -+ function = LED_FUNCTION_POWER; -+ linux,default-trigger = "heartbeat"; -+ gpios = <&gpio3 RK_PA2 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-wan { -+ color = ; -+ function = LED_FUNCTION_WAN; -+ gpios = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-wlan { -+ color = ; -+ function = LED_FUNCTION_WLAN; -+ gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+}; -+ -+&pcie2x1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie20_reset_pin>; -+ reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+}; -+ -+&pcie3x1 { -+ num-lanes = <1>; -+ reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; -+ vpcie3v3-supply = <&vcc3v3_pcie>; -+ status = "okay"; -+}; -+ -+&pcie3x2 { -+ num-lanes = <1>; -+ reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; -+ vpcie3v3-supply = <&vcc3v3_pcie>; -+ status = "okay"; -+}; -+ -+&pinctrl { -+ gpio-leds { -+ lan_led_pin: lan-led-pin { -+ rockchip,pins = <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ power_led_pin: power-led-pin { -+ rockchip,pins = <3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ wan_led_pin: wan-led-pin { -+ rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ wlan_led_pin: wlan-led-pin { -+ rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ pcie { -+ pcie20_reset_pin: pcie20-reset-pin { -+ rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+ -+ rockchip-key { -+ reset_button_pin: reset-button-pin { -+ rockchip,pins = <4 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+}; ---- a/board/rockchip/evb_rk3568/MAINTAINERS -+++ b/board/rockchip/evb_rk3568/MAINTAINERS -@@ -7,6 +7,13 @@ F: configs/evb-rk3568_defconfig - F: arch/arm/dts/rk3568-evb-boot.dtsi - F: arch/arm/dts/rk3568-evb.dts - -+NANOPI-R5C -+M: Tianling Shen -+S: Maintained -+F: configs/nanopi-r5c-rk3568_defconfig -+F: arch/arm/dts/rk3568-nanopi-r5c.dts -+F: arch/arm/dts/rk3568-nanopi-r5c-u-boot.dtsi -+ - NANOPI-R5S - M: Tianling Shen - S: Maintained ---- /dev/null -+++ b/configs/nanopi-r5c-rk3568_defconfig -@@ -0,0 +1,85 @@ -+CONFIG_ARM=y -+CONFIG_SKIP_LOWLEVEL_INIT=y -+CONFIG_COUNTER_FREQUENCY=24000000 -+CONFIG_ARCH_ROCKCHIP=y -+CONFIG_TEXT_BASE=0x00a00000 -+CONFIG_SPL_LIBCOMMON_SUPPORT=y -+CONFIG_SPL_LIBGENERIC_SUPPORT=y -+CONFIG_NR_DRAM_BANKS=2 -+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000 -+CONFIG_DEFAULT_DEVICE_TREE="rk3568-nanopi-r5c" -+CONFIG_ROCKCHIP_RK3568=y -+CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y -+CONFIG_SPL_SERIAL=y -+CONFIG_SPL_STACK_R_ADDR=0x600000 -+CONFIG_TARGET_EVB_RK3568=y -+CONFIG_SPL_STACK=0x400000 -+CONFIG_DEBUG_UART_BASE=0xFE660000 -+CONFIG_DEBUG_UART_CLOCK=24000000 -+CONFIG_SYS_LOAD_ADDR=0xc00800 -+CONFIG_DEBUG_UART=y -+CONFIG_FIT=y -+CONFIG_FIT_VERBOSE=y -+CONFIG_SPL_LOAD_FIT=y -+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3568-nanopi-r5c.dtb" -+# CONFIG_DISPLAY_CPUINFO is not set -+CONFIG_DISPLAY_BOARDINFO_LATE=y -+CONFIG_SPL_MAX_SIZE=0x40000 -+CONFIG_SPL_PAD_TO=0x7f8000 -+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y -+CONFIG_SPL_BSS_START_ADDR=0x4000000 -+CONFIG_SPL_BSS_MAX_SIZE=0x4000 -+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set -+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set -+CONFIG_SPL_STACK_R=y -+CONFIG_SPL_ATF=y -+CONFIG_CMD_GPIO=y -+CONFIG_CMD_GPT=y -+CONFIG_CMD_I2C=y -+CONFIG_CMD_MMC=y -+CONFIG_CMD_USB=y -+CONFIG_CMD_PMIC=y -+CONFIG_CMD_REGULATOR=y -+# CONFIG_SPL_DOS_PARTITION is not set -+CONFIG_SPL_OF_CONTROL=y -+CONFIG_OF_LIVE=y -+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" -+CONFIG_SPL_DM_WARN=y -+CONFIG_SPL_REGMAP=y -+CONFIG_SPL_SYSCON=y -+CONFIG_SPL_CLK=y -+CONFIG_ROCKCHIP_GPIO=y -+CONFIG_SYS_I2C_ROCKCHIP=y -+CONFIG_MISC=y -+CONFIG_SUPPORT_EMMC_RPMB=y -+CONFIG_MMC_DW=y -+CONFIG_MMC_DW_ROCKCHIP=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_SDMA=y -+CONFIG_MMC_SDHCI_ROCKCHIP=y -+CONFIG_ETH_DESIGNWARE=y -+CONFIG_GMAC_ROCKCHIP=y -+CONFIG_PHY_ROCKCHIP_INNO_USB2=y -+CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y -+CONFIG_POWER_DOMAIN=y -+CONFIG_DM_PMIC=y -+CONFIG_PMIC_RK8XX=y -+CONFIG_SPL_DM_REGULATOR_FIXED=y -+CONFIG_REGULATOR_RK8XX=y -+CONFIG_PWM_ROCKCHIP=y -+CONFIG_SPL_RAM=y -+CONFIG_BAUDRATE=1500000 -+CONFIG_DEBUG_UART_SHIFT=2 -+CONFIG_SYS_NS16550_MEM32=y -+CONFIG_SYSRESET=y -+CONFIG_SYSRESET_PSCI=y -+CONFIG_USB=y -+CONFIG_USB_XHCI_HCD=y -+CONFIG_USB_XHCI_DWC3=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_EHCI_GENERIC=y -+CONFIG_USB_OHCI_HCD=y -+CONFIG_USB_OHCI_GENERIC=y -+CONFIG_USB_DWC3=y -+CONFIG_ERRNO_STR=y diff --git a/package/boot/uboot-rockchip/patches/105-nanopc-t4-fix-memory-unstability.patch b/package/boot/uboot-rockchip/patches/105-nanopc-t4-fix-memory-unstability.patch index 7d2161ae42..b467f48f72 100644 --- a/package/boot/uboot-rockchip/patches/105-nanopc-t4-fix-memory-unstability.patch +++ b/package/boot/uboot-rockchip/patches/105-nanopc-t4-fix-memory-unstability.patch @@ -12,8 +12,6 @@ Signed-off-by: Lu jicong arch/arm/dts/rk3399-nanopc-t4-u-boot.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/arch/arm/dts/rk3399-nanopc-t4-u-boot.dtsi b/arch/arm/dts/rk3399-nanopc-t4-u-boot.dtsi -index 17201bcf41..8b6c9059ab 100644 --- a/arch/arm/dts/rk3399-nanopc-t4-u-boot.dtsi +++ b/arch/arm/dts/rk3399-nanopc-t4-u-boot.dtsi @@ -4,4 +4,4 @@ From 09bc806229345819788712b575a168ff63152297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sun, 21 Jan 2024 13:39:33 +0100 Subject: [PATCH 171/222] bcm27xx: drop unneeded github workflow and readme patches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These patches can be dropped since we don't care about RPi's Github CI and READMEs. Signed-off-by: Álvaro Fernández Rojas --- ...950-0149-Update-issue-templates-2736.patch | 47 --- ...e-GitHubs-issue-form-for-bug-reports.patch | 163 --------- ...github-Add-Github-Workflow-for-KUnit.patch | 74 ---- ...orkflows-Add-dtoverlaycheck-workflow.patch | 62 ---- ...s-Create-workflow-to-CI-kernel-build.patch | 285 --------------- ...E.md-with-CI-kernel-build-status-tag.patch | 50 --- ...ws-Set-warnings-as-errors-for-builds.patch | 63 ---- ...lows-Correct-kernel-builds-artifacts.patch | 147 -------- ...b-workflows-Switch-to-a-matrix-build.patch | 333 ------------------ ...md-Replace-6.0-build-status-with-6.2.patch | 27 -- ...rkflows-Retain-artifacts-for-90-days.patch | 18 - ...-love-checkpatch-so-add-it-to-the-CI.patch | 46 --- 12 files changed, 1315 deletions(-) delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0149-Update-issue-templates-2736.patch delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0368-Use-GitHubs-issue-form-for-bug-reports.patch delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0506-.github-Add-Github-Workflow-for-KUnit.patch delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0507-.github-workflows-Add-dtoverlaycheck-workflow.patch delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0508-.github-workflows-Create-workflow-to-CI-kernel-build.patch delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0509-README-Add-README.md-with-CI-kernel-build-status-tag.patch delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0538-.github-workflows-Set-warnings-as-errors-for-builds.patch delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0540-.github-workflows-Correct-kernel-builds-artifacts.patch delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0547-.github-workflows-Switch-to-a-matrix-build.patch delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0555-README.md-Replace-6.0-build-status-with-6.2.patch delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0556-.github-workflows-Retain-artifacts-for-90-days.patch delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0583-workflows-We-all-love-checkpatch-so-add-it-to-the-CI.patch diff --git a/target/linux/bcm27xx/patches-6.1/950-0149-Update-issue-templates-2736.patch b/target/linux/bcm27xx/patches-6.1/950-0149-Update-issue-templates-2736.patch deleted file mode 100644 index c394b48981..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0149-Update-issue-templates-2736.patch +++ /dev/null @@ -1,47 +0,0 @@ -From f1457e83cd211ef7c8c90e9a69d044366621c83f Mon Sep 17 00:00:00 2001 -From: James Hughes -Date: Fri, 2 Nov 2018 11:55:49 +0000 -Subject: [PATCH] Update issue templates (#2736) - ---- - .github/ISSUE_TEMPLATE/bug_report.md | 34 ++++++++++++++++++++++++++++ - 1 file changed, 34 insertions(+) - create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md - ---- /dev/null -+++ b/.github/ISSUE_TEMPLATE/bug_report.md -@@ -0,0 +1,34 @@ -+--- -+name: Bug report -+about: Create a report to help us fix your issue -+ -+--- -+ -+**Is this the right place for my bug report?** -+This repository contains the Linux kernel used on the Raspberry Pi. If you believe that the issue you are seeing is kernel-related, this is the right place. If not, we have other repositories for the GPU firmware at [github.com/raspberrypi/firmware](https://github.com/raspberrypi/firmware) and Raspberry Pi userland applications at [github.com/raspberrypi/userland](https://github.com/raspberrypi/userland). If you have problems with the Raspbian distribution packages, report them in the [github.com/RPi-Distro/repo](https://github.com/RPi-Distro/repo). If you simply have a question, then [the Raspberry Pi forums](https://www.raspberrypi.org/forums) are the best place to ask it. -+ -+**Describe the bug** -+Add a clear and concise description of what you think the bug is. -+ -+**To reproduce** -+List the steps required to reproduce the issue. -+ -+**Expected behaviour** -+Add a clear and concise description of what you expected to happen. -+ -+**Actual behaviour** -+Add a clear and concise description of what actually happened. -+ -+**System** -+ Copy and paste the results of the raspinfo command in to this section. Alternatively, copy and paste a pastebin link, or add answers to the following questions: -+ -+* Which model of Raspberry Pi? e.g. Pi3B+, PiZeroW -+* Which OS and version (`cat /etc/rpi-issue`)? -+* Which firmware version (`vcgencmd version`)? -+* Which kernel version (`uname -a`)? -+ -+**Logs** -+If applicable, add the relevant output from `dmesg` or similar. -+ -+**Additional context** -+Add any other relevant context for the problem. diff --git a/target/linux/bcm27xx/patches-6.1/950-0368-Use-GitHubs-issue-form-for-bug-reports.patch b/target/linux/bcm27xx/patches-6.1/950-0368-Use-GitHubs-issue-form-for-bug-reports.patch deleted file mode 100644 index 7d08793af6..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0368-Use-GitHubs-issue-form-for-bug-reports.patch +++ /dev/null @@ -1,163 +0,0 @@ -From b9bf4e573a1e07ef999636cdb61f393df61cc447 Mon Sep 17 00:00:00 2001 -From: Andreas Blaesius -Date: Wed, 5 Jan 2022 20:38:39 +0100 -Subject: [PATCH] Use GitHubs issue form for bug reports - -Use GitHubs issue form for bug reports. - -- modern look -- user don't need to mess with given markdown parts while filling the issue template - -Setup config.yml for general questions and problems with the Raspbian distribution packages. ---- - .github/ISSUE_TEMPLATE/bug_report.md | 34 ---------- - .github/ISSUE_TEMPLATE/bug_report.yml | 91 +++++++++++++++++++++++++++ - .github/ISSUE_TEMPLATE/config.yml | 9 +++ - 3 files changed, 100 insertions(+), 34 deletions(-) - delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md - create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml - create mode 100644 .github/ISSUE_TEMPLATE/config.yml - ---- a/.github/ISSUE_TEMPLATE/bug_report.md -+++ /dev/null -@@ -1,34 +0,0 @@ ----- --name: Bug report --about: Create a report to help us fix your issue -- ----- -- --**Is this the right place for my bug report?** --This repository contains the Linux kernel used on the Raspberry Pi. If you believe that the issue you are seeing is kernel-related, this is the right place. If not, we have other repositories for the GPU firmware at [github.com/raspberrypi/firmware](https://github.com/raspberrypi/firmware) and Raspberry Pi userland applications at [github.com/raspberrypi/userland](https://github.com/raspberrypi/userland). If you have problems with the Raspbian distribution packages, report them in the [github.com/RPi-Distro/repo](https://github.com/RPi-Distro/repo). If you simply have a question, then [the Raspberry Pi forums](https://www.raspberrypi.org/forums) are the best place to ask it. -- --**Describe the bug** --Add a clear and concise description of what you think the bug is. -- --**To reproduce** --List the steps required to reproduce the issue. -- --**Expected behaviour** --Add a clear and concise description of what you expected to happen. -- --**Actual behaviour** --Add a clear and concise description of what actually happened. -- --**System** -- Copy and paste the results of the raspinfo command in to this section. Alternatively, copy and paste a pastebin link, or add answers to the following questions: -- --* Which model of Raspberry Pi? e.g. Pi3B+, PiZeroW --* Which OS and version (`cat /etc/rpi-issue`)? --* Which firmware version (`vcgencmd version`)? --* Which kernel version (`uname -a`)? -- --**Logs** --If applicable, add the relevant output from `dmesg` or similar. -- --**Additional context** --Add any other relevant context for the problem. ---- /dev/null -+++ b/.github/ISSUE_TEMPLATE/bug_report.yml -@@ -0,0 +1,91 @@ -+name: "Bug report" -+description: Create a report to help us fix your issue -+body: -+- type: markdown -+ attributes: -+ value: | -+ **Is this the right place for my bug report?** -+ This repository contains the Linux kernel used on the Raspberry Pi. -+ If you believe that the issue you are seeing is kernel-related, this is the right place. -+ If not, we have other repositories for the GPU firmware at [github.com/raspberrypi/firmware](https://github.com/raspberrypi/firmware) and Raspberry Pi userland applications at [github.com/raspberrypi/userland](https://github.com/raspberrypi/userland). -+ -+ If you have problems with the Raspbian distribution packages, report them in the [github.com/RPi-Distro/repo](https://github.com/RPi-Distro/repo). -+ If you simply have a question, then [the Raspberry Pi forums](https://www.raspberrypi.org/forums) are the best place to ask it. -+ -+- type: textarea -+ id: description -+ attributes: -+ label: Describe the bug -+ description: | -+ Add a clear and concise description of what you think the bug is. -+ validations: -+ required: true -+ -+- type: textarea -+ id: reproduce -+ attributes: -+ label: Steps to reproduce the behaviour -+ description: | -+ List the steps required to reproduce the issue. -+ validations: -+ required: true -+ -+- type: dropdown -+ id: model -+ attributes: -+ label: Device (s) -+ description: On which device you are facing the bug? -+ multiple: true -+ options: -+ - Raspberry Pi Zero -+ - Raspberry Pi Zero W / WH -+ - Raspberry Pi Zero 2 W -+ - Raspberry Pi 1 Mod. A -+ - Raspberry Pi 1 Mod. A+ -+ - Raspberry Pi 1 Mod. B -+ - Raspberry Pi 1 Mod. B+ -+ - Raspberry Pi 2 Mod. B -+ - Raspberry Pi 2 Mod. B v1.2 -+ - Raspberry Pi 3 Mod. A+ -+ - Raspberry Pi 3 Mod. B -+ - Raspberry Pi 3 Mod. B+ -+ - Raspberry Pi 4 Mod. B -+ - Raspberry Pi 400 -+ - Raspberry Pi CM1 -+ - Raspberry Pi CM3 -+ - Raspberry Pi CM3 Lite -+ - Raspberry Pi CM3+ -+ - Raspberry Pi CM3+ Lite -+ - Raspberry Pi CM4 -+ - Raspberry Pi CM4 Lite -+ - Other -+ validations: -+ required: true -+ -+- type: textarea -+ id: system -+ attributes: -+ label: System -+ description: | -+ Copy and paste the results of the raspinfo command in to this section. -+ Alternatively, copy and paste a pastebin link, or add answers to the following questions: -+ * Which OS and version (`cat /etc/rpi-issue`)? -+ * Which firmware version (`vcgencmd version`)? -+ * Which kernel version (`uname -a`)? -+ validations: -+ required: true -+ -+- type: textarea -+ id: logs -+ attributes: -+ label: Logs -+ description: | -+ If applicable, add the relevant output from `dmesg` or similar. -+ -+- type: textarea -+ id: additional -+ attributes: -+ label: Additional context -+ description: | -+ Add any other relevant context for the problem. -+ ---- /dev/null -+++ b/.github/ISSUE_TEMPLATE/config.yml -@@ -0,0 +1,9 @@ -+blank_issues_enabled: false -+contact_links: -+ - name: "⛔ Question" -+ url: https://www.raspberrypi.org/forums -+ about: "Please do not use GitHub for asking questions. If you simply have a question, then the Raspberry Pi forums are the best place to ask it. Thanks in advance for helping us keep the issue tracker clean!" -+ - name: "⛔ Problems with the Raspbian distribution packages" -+ url: https://github.com/RPi-Distro/repo -+ about: "If you have problems with the Raspbian distribution packages, please report them in the github.com/RPi-Distro/repo." -+ diff --git a/target/linux/bcm27xx/patches-6.1/950-0506-.github-Add-Github-Workflow-for-KUnit.patch b/target/linux/bcm27xx/patches-6.1/950-0506-.github-Add-Github-Workflow-for-KUnit.patch deleted file mode 100644 index bb3c3f160a..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0506-.github-Add-Github-Workflow-for-KUnit.patch +++ /dev/null @@ -1,74 +0,0 @@ -From d172f330087422b8f33ad5e0f60f903820e7b321 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 8 Dec 2022 13:17:42 +0100 -Subject: [PATCH] .github: Add Github Workflow for KUnit - -Now that we have some KUnit coverage, let's add a github actions file to -run them on each push or pull request. - -Signed-off-by: Maxime Ripard ---- - .github/workflows/kunit.yml | 57 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 57 insertions(+) - create mode 100644 .github/workflows/kunit.yml - ---- /dev/null -+++ b/.github/workflows/kunit.yml -@@ -0,0 +1,57 @@ -+name: KUnit Tests -+ -+on: -+ pull_request: -+ branches: [ "rpi-*"] -+ -+ push: -+ branches: [ "rpi-*"] -+ -+jobs: -+ core: -+ name: Generic DRM/KMS Unit Tests -+ runs-on: ubuntu-latest -+ -+ steps: -+ - uses: actions/checkout@v3 -+ -+ - name: Run Generic DRM Tests -+ run: | -+ ./tools/testing/kunit/kunit.py run \ -+ --kunitconfig=drivers/gpu/drm/tests -+ -+ vc4-arm: -+ name: VC4 Unit Tests on ARM -+ runs-on: ubuntu-latest -+ -+ steps: -+ - uses: actions/checkout@v3 -+ -+ - name: Install Dependencies -+ run: | -+ sudo apt-get update -+ sudo apt-get install -y gcc-arm-linux-gnueabihf qemu-system-arm -+ -+ - name: Run VC4 Tests -+ run: | -+ ./tools/testing/kunit/kunit.py run \ -+ --kunitconfig=drivers/gpu/drm/vc4/tests \ -+ --cross_compile=arm-linux-gnueabihf- --arch=arm -+ -+ vc4-arm64: -+ name: VC4 Unit Tests on ARM64 -+ runs-on: ubuntu-latest -+ -+ steps: -+ - uses: actions/checkout@v3 -+ -+ - name: Install Dependencies -+ run: | -+ sudo apt-get update -+ sudo apt-get install -y gcc-aarch64-linux-gnu qemu-system-arm -+ -+ - name: Run VC4 Tests -+ run: | -+ ./tools/testing/kunit/kunit.py run \ -+ --kunitconfig=drivers/gpu/drm/vc4/tests \ -+ --cross_compile=aarch64-linux-gnu- --arch=arm64 diff --git a/target/linux/bcm27xx/patches-6.1/950-0507-.github-workflows-Add-dtoverlaycheck-workflow.patch b/target/linux/bcm27xx/patches-6.1/950-0507-.github-workflows-Add-dtoverlaycheck-workflow.patch deleted file mode 100644 index 92a7b7edf4..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0507-.github-workflows-Add-dtoverlaycheck-workflow.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 4aec59014afc64d912502d70194a8823b0a6150a Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Tue, 6 Dec 2022 18:11:58 +0000 -Subject: [PATCH] .github/workflows: Add dtoverlaycheck workflow - -Signed-off-by: Dave Stevenson ---- - .github/workflows/dtoverlaycheck.yml | 48 ++++++++++++++++++++++++++++ - 1 file changed, 48 insertions(+) - create mode 100644 .github/workflows/dtoverlaycheck.yml - ---- /dev/null -+++ b/.github/workflows/dtoverlaycheck.yml -@@ -0,0 +1,48 @@ -+name: Pi dtoverlay checks -+ -+on: -+ pull_request: -+ paths-ignore: -+ - '.github/**' -+ branches: [ "rpi-*" ] -+ push: -+ paths-ignore: -+ - '.github/**' -+ branches: [ "rpi-*" ] -+ workflow_dispatch: -+ -+env: -+ UTILS_DIR: "${{github.workspace}}/utils" -+ -+jobs: -+ dtoverlaycheck: -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Install toolchain -+ run: | -+ sudo apt update -+ sudo apt-get install gcc-arm-linux-gnueabihf libfdt-dev device-tree-compiler -+ timeout-minutes: 10 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: overlaycheck -+ run: | -+ git clone https://github.com/raspberrypi/utils ${{env.UTILS_DIR}} -+ cd ${{env.UTILS_DIR}} -+ pwd -+ mkdir build -+ cd build -+ pwd -+ cmake .. -+ make -j4 -+ sudo make install -+ cd ${{github.workspace}} -+ pwd -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- bcm2711_defconfig -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- dtbs -+ ${{env.UTILS_DIR}}/overlaycheck/overlaycheck diff --git a/target/linux/bcm27xx/patches-6.1/950-0508-.github-workflows-Create-workflow-to-CI-kernel-build.patch b/target/linux/bcm27xx/patches-6.1/950-0508-.github-workflows-Create-workflow-to-CI-kernel-build.patch deleted file mode 100644 index 101f6dafca..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0508-.github-workflows-Create-workflow-to-CI-kernel-build.patch +++ /dev/null @@ -1,285 +0,0 @@ -From baa2e8235af7143148d8799c5caed2a2eefd9107 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Fri, 11 Nov 2022 17:09:32 +0000 -Subject: [PATCH] .github/workflows: Create workflow to CI kernel - builds - -Builds the bcmrpi, bcm2709, bcm2711, and bcm2835 32 bit kernels, -and defconfig and bcm2711 64bit kernels, saving the artifacts for -7 days. - -Signed-off-by: Dave Stevenson ---- - .github/workflows/kernel-build.yml | 266 +++++++++++++++++++++++++++++ - 1 file changed, 266 insertions(+) - create mode 100644 .github/workflows/kernel-build.yml - ---- /dev/null -+++ b/.github/workflows/kernel-build.yml -@@ -0,0 +1,266 @@ -+name: Pi kernel build tests -+ -+on: -+ pull_request: -+ paths-ignore: -+ - '.github/**' -+ branches: [ "rpi-*" ] -+ push: -+ paths-ignore: -+ - '.github/**' -+ branches: [ "rpi-*" ] -+ workflow_dispatch: -+ -+env: -+ NUM_JOBS: 3 -+ -+jobs: -+ build-bcm2835: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-arm-linux-gnueabihf -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2835_defconfig -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/Image ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf bcm2835_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: bcm2835_build -+ path: bcm2835_build.tar -+ retention-days: 7 -+ -+ build-arm64: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-aarch64-linux-gnu -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build defconfig -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf arm64_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: arm64_build -+ path: arm64_build.tar -+ retention-days: 7 -+ -+ build-bcmrpi: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-arm-linux-gnueabihf -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf bcmrpi_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: bcmrpi_build -+ path: bcmrpi_build.tar -+ retention-days: 7 -+ -+ build-bcm2709: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-arm-linux-gnueabihf -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2709_defconfig -+ make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf bcm2709_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: bcm2709_build -+ path: bcm2709_build.tar -+ retention-days: 7 -+ -+ build-bcm2711: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-arm-linux-gnueabihf -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf bcm2711_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: bcm2711_build -+ path: bcm2711_build.tar -+ retention-days: 7 -+ -+ build-bcm2711-arm64: -+ -+ runs-on: ubuntu-latest -+ -+ steps: -+ - name: Update install -+ run: -+ sudo apt-get update -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-arm-linux-gnueabihf -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Install toolchain -+ run: -+ sudo apt-get install gcc-aarch64-linux-gnu -+ timeout-minutes: 5 -+ -+ - uses: actions/checkout@v3 -+ with: -+ fetch-depth: 1 -+ clean: true -+ -+ - name: Build kernel -+ run: | -+ mkdir ${{github.workspace}}/build -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -+ cp -r ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/ -+ -+ - name: Tar build -+ run: tar -cvf bcm2711_arm64_build.tar -C ${{github.workspace}}/install . -+ -+ - name: Upload results -+ uses: actions/upload-artifact@v3 -+ with: -+ name: bcm2711_arm64_build -+ path: bcm2711_arm64_build.tar -+ retention-days: 7 diff --git a/target/linux/bcm27xx/patches-6.1/950-0509-README-Add-README.md-with-CI-kernel-build-status-tag.patch b/target/linux/bcm27xx/patches-6.1/950-0509-README-Add-README.md-with-CI-kernel-build-status-tag.patch deleted file mode 100644 index 610efdc8a7..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0509-README-Add-README.md-with-CI-kernel-build-status-tag.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 81eebfa296eb1454cde3bf1cbd919f8b9eb6cf64 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 14 Nov 2022 17:14:15 +0000 -Subject: [PATCH] README: Add README.md with CI kernel build status - tags - -This is a copy of README with the tags added. - -You can not delete the file README as then checkpatch complains -you aren't in a kernel tree. - -Signed-off-by: Dave Stevenson ---- - README.md | 30 ++++++++++++++++++++++++++++++ - 1 file changed, 30 insertions(+) - create mode 100644 README.md - ---- /dev/null -+++ b/README.md -@@ -0,0 +1,30 @@ -+Linux kernel -+============ -+ -+There are several guides for kernel developers and users. These guides can -+be rendered in a number of formats, like HTML and PDF. Please read -+Documentation/admin-guide/README.rst first. -+ -+In order to build the documentation, use ``make htmldocs`` or -+``make pdfdocs``. The formatted documentation can also be read online at: -+ -+ https://www.kernel.org/doc/html/latest/ -+ -+There are various text files in the Documentation/ subdirectory, -+several of them using the Restructured Text markup notation. -+ -+Please read the Documentation/process/changes.rst file, as it contains the -+requirements for building and running the kernel, and information about -+the problems which may result by upgrading your kernel. -+ -+Build status for rpi-5.15.y: -+[![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-5.15.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) -+[![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-5.15.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) -+ -+Build status for rpi-6.0.y: -+[![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-6.0.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) -+[![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-6.0.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) -+ -+Build status for rpi-6.1.y: -+[![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-6.1.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) -+[![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-6.1.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) diff --git a/target/linux/bcm27xx/patches-6.1/950-0538-.github-workflows-Set-warnings-as-errors-for-builds.patch b/target/linux/bcm27xx/patches-6.1/950-0538-.github-workflows-Set-warnings-as-errors-for-builds.patch deleted file mode 100644 index f880a637c1..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0538-.github-workflows-Set-warnings-as-errors-for-builds.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0a1c5c32cfe570a688a09c90ab16052fcb258342 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 13 Jan 2023 14:32:45 +0000 -Subject: [PATCH] .github/workflows: Set warnings-as-errors for builds - -To avoid code with build warnings being introduced into the tree, force -CONFIG_WERROR=y in the build workflow. - -Signed-off-by: Phil Elwell ---- - .github/workflows/kernel-build.yml | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/.github/workflows/kernel-build.yml -+++ b/.github/workflows/kernel-build.yml -@@ -38,6 +38,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2835_defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -@@ -78,6 +79,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -@@ -118,6 +120,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -@@ -158,6 +161,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2709_defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -@@ -198,6 +202,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -@@ -248,6 +253,7 @@ jobs: - run: | - mkdir ${{github.workspace}}/build - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build bcm2711_defconfig -+ scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs - mkdir -p ${{github.workspace}}/install/boot - make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install diff --git a/target/linux/bcm27xx/patches-6.1/950-0540-.github-workflows-Correct-kernel-builds-artifacts.patch b/target/linux/bcm27xx/patches-6.1/950-0540-.github-workflows-Correct-kernel-builds-artifacts.patch deleted file mode 100644 index 359efd5c85..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0540-.github-workflows-Correct-kernel-builds-artifacts.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 3e32a992acb7248183a3eb1d92503ac2d2eb2617 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 18 Jan 2023 09:34:31 +0000 -Subject: [PATCH] .github/workflows: Correct kernel builds artifacts - -Modify the kernel build workflow to create artifacts with the correct -names and structure, both as an example of what we expect and in case -anyone wants to use the output. - -Signed-off-by: Phil Elwell ---- - .github/workflows/kernel-build.yml | 76 ++++++++++++++++-------------- - 1 file changed, 41 insertions(+), 35 deletions(-) - ---- a/.github/workflows/kernel-build.yml -+++ b/.github/workflows/kernel-build.yml -@@ -37,14 +37,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2835_defconfig -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2835_defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays - make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/Image ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel.img - - - name: Tar build - run: tar -cvf bcm2835_build.tar -C ${{github.workspace}}/install . -@@ -78,14 +79,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build defconfig -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm64/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/kernel8.img - - - name: Tar build - run: tar -cvf arm64_build.tar -C ${{github.workspace}}/install . -@@ -119,14 +121,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcmrpi_defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -- make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel.img - - - name: Tar build - run: tar -cvf bcmrpi_build.tar -C ${{github.workspace}}/install . -@@ -160,14 +163,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2709_defconfig -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2709_defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -- make ARCH=arm KERNEL=kernel7 CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel7.img - - - name: Tar build - run: tar -cvf bcm2709_build.tar -C ${{github.workspace}}/install . -@@ -201,14 +205,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -- make ARCH=arm KERNEL=kernel7l CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays -+ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel7l.img - - - name: Tar build - run: tar -cvf bcm2711_build.tar -C ${{github.workspace}}/install . -@@ -252,14 +257,15 @@ jobs: - - name: Build kernel - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build bcm2711_defconfig -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build bcm2711_defconfig - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -- mkdir -p ${{github.workspace}}/install/boot -- make ARCH=arm64 KERNEL=kernel8 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -+ mkdir -p ${{github.workspace}}/install/boot/overlays -+ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -- cp -r ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/arm64/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/kernel8.img - - - name: Tar build - run: tar -cvf bcm2711_arm64_build.tar -C ${{github.workspace}}/install . diff --git a/target/linux/bcm27xx/patches-6.1/950-0547-.github-workflows-Switch-to-a-matrix-build.patch b/target/linux/bcm27xx/patches-6.1/950-0547-.github-workflows-Switch-to-a-matrix-build.patch deleted file mode 100644 index 51f32be5a0..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0547-.github-workflows-Switch-to-a-matrix-build.patch +++ /dev/null @@ -1,333 +0,0 @@ -From 3ca614742a496b66a9b92ce6be05ff555fdfc2c2 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 23 Jan 2023 16:50:51 +0000 -Subject: [PATCH] .github/workflows: Switch to a matrix build - -Remove the per-build duplication by putting build parameters in a -matrix. - -Signed-off-by: Phil Elwell ---- - .github/workflows/kernel-build.yml | 293 ++++++----------------------- - 1 file changed, 59 insertions(+), 234 deletions(-) - ---- a/.github/workflows/kernel-build.yml -+++ b/.github/workflows/kernel-build.yml -@@ -15,177 +15,40 @@ env: - NUM_JOBS: 3 - - jobs: -- build-bcm2835: -- -- runs-on: ubuntu-latest -- -- steps: -- - name: Update install -- run: -- sudo apt-get update -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-arm-linux-gnueabihf -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -- -- - name: Build kernel -- run: | -- mkdir ${{github.workspace}}/build -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2835_defconfig -- scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel.img -- -- - name: Tar build -- run: tar -cvf bcm2835_build.tar -C ${{github.workspace}}/install . -- -- - name: Upload results -- uses: actions/upload-artifact@v3 -- with: -- name: bcm2835_build -- path: bcm2835_build.tar -- retention-days: 7 -- -- build-arm64: -- -- runs-on: ubuntu-latest -- -- steps: -- - name: Update install -- run: -- sudo apt-get update -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-aarch64-linux-gnu -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -- -- - name: Build kernel -- run: | -- mkdir ${{github.workspace}}/build -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build defconfig -- scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -- mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm64/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/kernel8.img -- -- - name: Tar build -- run: tar -cvf arm64_build.tar -C ${{github.workspace}}/install . -- -- - name: Upload results -- uses: actions/upload-artifact@v3 -- with: -- name: arm64_build -- path: arm64_build.tar -- retention-days: 7 -- -- build-bcmrpi: -- -- runs-on: ubuntu-latest -- -- steps: -- - name: Update install -- run: -- sudo apt-get update -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-arm-linux-gnueabihf -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -- -- - name: Build kernel -- run: | -- mkdir ${{github.workspace}}/build -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcmrpi_defconfig -- scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel.img -- -- - name: Tar build -- run: tar -cvf bcmrpi_build.tar -C ${{github.workspace}}/install . -- -- - name: Upload results -- uses: actions/upload-artifact@v3 -- with: -- name: bcmrpi_build -- path: bcmrpi_build.tar -- retention-days: 7 -- -- build-bcm2709: -- -+ build: - runs-on: ubuntu-latest -+ strategy: -+ matrix: -+ include: -+ - name: bcm2835 -+ arch: arm -+ defconfig: bcm2835_defconfig -+ kernel: kernel - -- steps: -- - name: Update install -- run: -- sudo apt-get update -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-arm-linux-gnueabihf -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -+ - name: arm64 -+ arch: arm64 -+ defconfig: defconfig -+ kernel: kernel8 - -- - name: Build kernel -- run: | -- mkdir ${{github.workspace}}/build -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2709_defconfig -- scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel7.img -+ - name: bcmrpi -+ arch: arm -+ defconfig: bcmrpi_defconfig -+ kernel: kernel - -- - name: Tar build -- run: tar -cvf bcm2709_build.tar -C ${{github.workspace}}/install . -+ - name: bcm2709 -+ arch: arm -+ defconfig: bcm2709_defconfig -+ kernel: kernel7 - -- - name: Upload results -- uses: actions/upload-artifact@v3 -- with: -- name: bcm2709_build -- path: bcm2709_build.tar -- retention-days: 7 -- -- build-bcm2711: -+ - name: bcm2711 -+ arch: arm -+ defconfig: bcm2711_defconfig -+ kernel: kernel7l - -- runs-on: ubuntu-latest -+ - name: bcm2711_arm64 -+ arch: arm64 -+ defconfig: bcm2711_defconfig -+ kernel: kernel8 - - steps: - - name: Update install -@@ -194,59 +57,11 @@ jobs: - - - name: Install toolchain - run: -- sudo apt-get install gcc-arm-linux-gnueabihf -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -- -- - name: Build kernel -- run: | -- mkdir ${{github.workspace}}/build -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build bcm2711_defconfig -- scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} zImage modules dtbs -- mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm/boot/dts/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm/boot/zImage ${{github.workspace}}/install/boot/kernel7l.img -- -- - name: Tar build -- run: tar -cvf bcm2711_build.tar -C ${{github.workspace}}/install . -- -- - name: Upload results -- uses: actions/upload-artifact@v3 -- with: -- name: bcm2711_build -- path: bcm2711_build.tar -- retention-days: 7 -- -- build-bcm2711-arm64: -- -- runs-on: ubuntu-latest -- -- steps: -- - name: Update install -- run: -- sudo apt-get update -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-arm-linux-gnueabihf -- timeout-minutes: 5 -- -- - uses: actions/checkout@v3 -- with: -- fetch-depth: 1 -- clean: true -- -- - name: Install toolchain -- run: -- sudo apt-get install gcc-aarch64-linux-gnu -+ if [[ "${{matrix.arch}}" == "arm64" ]]; then -+ sudo apt-get install gcc-aarch64-linux-gnu; -+ else -+ sudo apt-get install gcc-arm-linux-gnueabihf; -+ fi - timeout-minutes: 5 - - - uses: actions/checkout@v3 -@@ -254,25 +69,35 @@ jobs: - fetch-depth: 1 - clean: true - -- - name: Build kernel -+ - name: Build kernel ${{matrix.name}} - run: | - mkdir ${{github.workspace}}/build -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build bcm2711_defconfig -+ export ARCH=${{matrix.arch}} -+ if [[ "$ARCH" == "arm64" ]]; then -+ export CROSS_COMPILE=aarch64-linux-gnu- -+ export DTS_SUBDIR=broadcom -+ export IMAGE=Image.gz -+ else -+ export CROSS_COMPILE=arm-linux-gnueabihf- -+ export DTS_SUBDIR= -+ export IMAGE=zImage -+ fi -+ make O=${{github.workspace}}/build ${{matrix.defconfig}} - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} Image.gz modules dtbs -+ make O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} $IMAGE modules dtbs - mkdir -p ${{github.workspace}}/install/boot/overlays -- make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -- cp ${{github.workspace}}/build/arch/arm64/boot/dts/broadcom/*.dtb ${{github.workspace}}/install/boot/ -- cp ${{github.workspace}}/build/arch/arm64/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/arch/arm64/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -- cp ${{github.workspace}}/build/arch/arm64/boot/Image.gz ${{github.workspace}}/install/boot/kernel8.img -+ make O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install -+ cp ${{github.workspace}}/build/arch/${ARCH}/boot/dts/${DTS_SUBDIR}/*.dtb ${{github.workspace}}/install/boot/ -+ cp ${{github.workspace}}/build/arch/${ARCH}/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/arch/${ARCH}/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ -+ cp ${{github.workspace}}/build/arch/${ARCH}/boot/$IMAGE ${{github.workspace}}/install/boot/${{matrix.kernel}}.img - - - name: Tar build -- run: tar -cvf bcm2711_arm64_build.tar -C ${{github.workspace}}/install . -+ run: tar -cvf ${{matrix.name}}_build.tar -C ${{github.workspace}}/install . - - - name: Upload results - uses: actions/upload-artifact@v3 - with: -- name: bcm2711_arm64_build -- path: bcm2711_arm64_build.tar -+ name: ${{matrix.name}}_build -+ path: ${{matrix.name}}_build.tar - retention-days: 7 diff --git a/target/linux/bcm27xx/patches-6.1/950-0555-README.md-Replace-6.0-build-status-with-6.2.patch b/target/linux/bcm27xx/patches-6.1/950-0555-README.md-Replace-6.0-build-status-with-6.2.patch deleted file mode 100644 index 889ae948a8..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0555-README.md-Replace-6.0-build-status-with-6.2.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 1cc246c143210efe249978419b094b03bf2137e0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell <8911409+pelwell@users.noreply.github.com> -Date: Wed, 25 Jan 2023 10:19:52 +0000 -Subject: [PATCH] README.md: Replace 6.0 build status with 6.2 - -6.0 is EOL and 6.2 is heading towards release, so update the build status display accordingly. ---- - README.md | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/README.md -+++ b/README.md -@@ -21,10 +21,10 @@ Build status for rpi-5.15.y: - [![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-5.15.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) - [![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-5.15.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) - --Build status for rpi-6.0.y: --[![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-6.0.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) --[![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-6.0.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) -- - Build status for rpi-6.1.y: - [![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-6.1.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) - [![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-6.1.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) -+ -+Build status for rpi-6.2.y: -+[![Pi kernel build tests](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml/badge.svg?branch=rpi-6.2.y)](https://github.com/raspberrypi/linux/actions/workflows/kernel-build.yml) -+[![dtoverlaycheck](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml/badge.svg?branch=rpi-6.2.y)](https://github.com/raspberrypi/linux/actions/workflows/dtoverlaycheck.yml) diff --git a/target/linux/bcm27xx/patches-6.1/950-0556-.github-workflows-Retain-artifacts-for-90-days.patch b/target/linux/bcm27xx/patches-6.1/950-0556-.github-workflows-Retain-artifacts-for-90-days.patch deleted file mode 100644 index abc61e8b68..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0556-.github-workflows-Retain-artifacts-for-90-days.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 05a9a53de8785c82332081a5f44cc34dc9fa5f0c Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 25 Jan 2023 15:01:43 +0000 -Subject: [PATCH] .github/workflows: Retain artifacts for 90 days - -Signed-off-by: Phil Elwell ---- - .github/workflows/kernel-build.yml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/.github/workflows/kernel-build.yml -+++ b/.github/workflows/kernel-build.yml -@@ -100,4 +100,4 @@ jobs: - with: - name: ${{matrix.name}}_build - path: ${{matrix.name}}_build.tar -- retention-days: 7 -+ retention-days: 90 diff --git a/target/linux/bcm27xx/patches-6.1/950-0583-workflows-We-all-love-checkpatch-so-add-it-to-the-CI.patch b/target/linux/bcm27xx/patches-6.1/950-0583-workflows-We-all-love-checkpatch-so-add-it-to-the-CI.patch deleted file mode 100644 index 109ae27c40..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0583-workflows-We-all-love-checkpatch-so-add-it-to-the-CI.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 6c110195b1f9b4e39676065d5973ecf603746862 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Wed, 8 Mar 2023 15:28:19 +0000 -Subject: [PATCH] workflows: We all love checkpatch, so add it to the - CI workflows - -This is currently running on defaults, so the --strict desired -for media drivers and similar won't be observed. That may be -possible to add later. - -Signed-off-by: Dave Stevenson ---- - .github/workflows/checkpatch.yml | 18 ++++++++++++++++++ - .github/workflows/ci_checkpatch.conf | 4 ++++ - 2 files changed, 22 insertions(+) - create mode 100644 .github/workflows/checkpatch.yml - create mode 100644 .github/workflows/ci_checkpatch.conf - ---- /dev/null -+++ b/.github/workflows/checkpatch.yml -@@ -0,0 +1,18 @@ -+name: Advisory checkpatch review -+on: [pull_request] -+ -+jobs: -+ review: -+ name: checkpatch review -+ runs-on: ubuntu-latest -+ steps: -+ - name: 'Calculate PR commits + 1' -+ run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> $GITHUB_ENV -+ - uses: actions/checkout@v3 -+ with: -+ ref: ${{ github.event.pull_request.head.sha }} -+ fetch-depth: ${{ env.PR_FETCH_DEPTH }} -+ - name: Copy checkpatch.conf -+ run: cp ${{github.workspace}}/.github/workflows/ci_checkpatch.conf ${{github.workspace}}/.checkpatch.conf -+ - name: Run checkpatch review -+ uses: webispy/checkpatch-action@v9 ---- /dev/null -+++ b/.github/workflows/ci_checkpatch.conf -@@ -0,0 +1,4 @@ -+--no-tree -+--ignore FILE_PATH_CHANGES -+--ignore GIT_COMMIT_ID -+--ignore SPDX_LICENSE_TAG From 797d46c34d90eddce7acd369d70347dfae545065 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 21 Jan 2024 22:07:31 +0100 Subject: [PATCH 172/222] generic: 6.1: move stmmac backport fix patches to generic Move stmmac backport fix patches from ipq806x to generic backport directory as they got merged upstream and they fix wide performance regression. This will eventually cause performance increase on any user of the stmmac driver. Generic patch automatically refreshed with make target/linux/refresh. Signed-off-by: Christian Marangi --- ...-introduce-napi_is_scheduled-helper.patch} | 39 ++++++++++++++----- ...t-stmmac-improve-TX-timer-arm-logic.patch} | 9 +++-- ...-move-TX-timer-arm-after-DMA-enable.patch} | 31 +++++++++------ ...c-increase-TX-coalesce-timer-to-5ms.patch} | 7 ++-- ...ive-renaming-when-an-interface-is-up.patch | 6 +-- .../721-net-add-packet-mangeling.patch | 8 ++-- ...T-skip-GRO-for-foreign-MAC-addresses.patch | 2 +- ...0211_ptr-even-with-no-CFG82111-suppo.patch | 2 +- ...ional-threading-for-backlog-processi.patch | 4 +- 9 files changed, 68 insertions(+), 40 deletions(-) rename target/linux/{ipq806x/patches-6.1/700-01-net-introduce-napi_is_scheduled-helper.patch => generic/backport-6.1/770-net-introduce-napi_is_scheduled-helper.patch} (62%) rename target/linux/{ipq806x/patches-6.1/700-03-net-stmmac-improve-TX-timer-arm-logic.patch => generic/backport-6.1/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch} (91%) rename target/linux/{ipq806x/patches-6.1/700-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch => generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch} (71%) rename target/linux/{ipq806x/patches-6.1/700-04-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch => generic/backport-6.1/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch} (86%) diff --git a/target/linux/ipq806x/patches-6.1/700-01-net-introduce-napi_is_scheduled-helper.patch b/target/linux/generic/backport-6.1/770-net-introduce-napi_is_scheduled-helper.patch similarity index 62% rename from target/linux/ipq806x/patches-6.1/700-01-net-introduce-napi_is_scheduled-helper.patch rename to target/linux/generic/backport-6.1/770-net-introduce-napi_is_scheduled-helper.patch index f59c461f65..789b93e9f9 100644 --- a/target/linux/ipq806x/patches-6.1/700-01-net-introduce-napi_is_scheduled-helper.patch +++ b/target/linux/generic/backport-6.1/770-net-introduce-napi_is_scheduled-helper.patch @@ -1,7 +1,7 @@ -From b5532bdc6d09e6e789417f0c7a0b665b57b0e7be Mon Sep 17 00:00:00 2001 +From 7f3eb2174512fe6c9c0f062e96eccb0d3cc6d5cd Mon Sep 17 00:00:00 2001 From: Christian Marangi -Date: Mon, 18 Sep 2023 14:21:56 +0200 -Subject: [PATCH 1/4] net: introduce napi_is_scheduled helper +Date: Wed, 18 Oct 2023 14:35:47 +0200 +Subject: [PATCH] net: introduce napi_is_scheduled helper We currently have napi_if_scheduled_mark_missed that can be used to check if napi is scheduled but that does more thing than simply checking @@ -15,12 +15,13 @@ Update any driver and code that implement a similar check and instead use this new helper. Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni --- - drivers/net/ethernet/chelsio/cxgb3/sge.c | 8 -------- - drivers/net/wireless/realtek/rtw89/core.c | 2 +- - include/linux/netdevice.h | 5 +++++ - net/core/dev.c | 2 +- - 4 files changed, 7 insertions(+), 10 deletions(-) + drivers/net/ethernet/chelsio/cxgb3/sge.c | 8 -------- + drivers/net/wireless/realtek/rtw89/core.c | 2 +- + include/linux/netdevice.h | 23 +++++++++++++++++++++++ + net/core/dev.c | 2 +- + 4 files changed, 25 insertions(+), 10 deletions(-) --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -52,10 +53,28 @@ Signed-off-by: Christian Marangi rtw89_core_hw_to_sband_rate(rx_status); --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -468,6 +468,11 @@ static inline bool napi_prefer_busy_poll +@@ -468,6 +468,29 @@ static inline bool napi_prefer_busy_poll return test_bit(NAPI_STATE_PREFER_BUSY_POLL, &n->state); } ++/** ++ * napi_is_scheduled - test if NAPI is scheduled ++ * @n: NAPI context ++ * ++ * This check is "best-effort". With no locking implemented, ++ * a NAPI can be scheduled or terminate right after this check ++ * and produce not precise results. ++ * ++ * NAPI_STATE_SCHED is an internal state, napi_is_scheduled ++ * should not be used normally and napi_schedule should be ++ * used instead. ++ * ++ * Use only if the driver really needs to check if a NAPI ++ * is scheduled for example in the context of delayed timer ++ * that can be skipped if a NAPI is already scheduled. ++ * ++ * Return True if NAPI is scheduled, False otherwise. ++ */ +static inline bool napi_is_scheduled(struct napi_struct *n) +{ + return test_bit(NAPI_STATE_SCHED, &n->state); @@ -66,7 +85,7 @@ Signed-off-by: Christian Marangi /** --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -6594,7 +6594,7 @@ static int __napi_poll(struct napi_struc +@@ -6533,7 +6533,7 @@ static int __napi_poll(struct napi_struc * accidentally calling ->poll() when NAPI is not scheduled. */ work = 0; diff --git a/target/linux/ipq806x/patches-6.1/700-03-net-stmmac-improve-TX-timer-arm-logic.patch b/target/linux/generic/backport-6.1/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch similarity index 91% rename from target/linux/ipq806x/patches-6.1/700-03-net-stmmac-improve-TX-timer-arm-logic.patch rename to target/linux/generic/backport-6.1/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch index 21c7ff1777..07c087260c 100644 --- a/target/linux/ipq806x/patches-6.1/700-03-net-stmmac-improve-TX-timer-arm-logic.patch +++ b/target/linux/generic/backport-6.1/771-v6.7-01-net-stmmac-improve-TX-timer-arm-logic.patch @@ -1,7 +1,7 @@ -From cd40cd8b1ca4a6f531c6c3fd78b306e5014f9c04 Mon Sep 17 00:00:00 2001 +From 2d1a42cf7f77cda54dbbee18d00b1200e7bc22aa Mon Sep 17 00:00:00 2001 From: Christian Marangi -Date: Mon, 18 Sep 2023 14:39:01 +0200 -Subject: [PATCH 3/4] net: stmmac: improve TX timer arm logic +Date: Wed, 18 Oct 2023 14:35:48 +0200 +Subject: [PATCH 1/3] net: stmmac: improve TX timer arm logic There is currently a problem with the TX timer getting armed multiple unnecessary times causing big performance regression on some device that @@ -39,13 +39,14 @@ With the following new logic the original performance are restored while keeping using the hrtimer. Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -2976,13 +2976,25 @@ static void stmmac_tx_timer_arm(struct s +@@ -2975,13 +2975,25 @@ static void stmmac_tx_timer_arm(struct s { struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; u32 tx_coal_timer = priv->tx_coal_timer[queue]; diff --git a/target/linux/ipq806x/patches-6.1/700-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch b/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch similarity index 71% rename from target/linux/ipq806x/patches-6.1/700-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch rename to target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch index 6df071c9b8..d1e04e9069 100644 --- a/target/linux/ipq806x/patches-6.1/700-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch +++ b/target/linux/generic/backport-6.1/771-v6.7-02-net-stmmac-move-TX-timer-arm-after-DMA-enable.patch @@ -1,7 +1,7 @@ -From fb04db35447d1e8ff557c8e57139164cecab7de5 Mon Sep 17 00:00:00 2001 +From a594166387fe08e6f5a32130c400249a35b298f9 Mon Sep 17 00:00:00 2001 From: Christian Marangi -Date: Wed, 27 Sep 2023 15:38:31 +0200 -Subject: [PATCH 2/4] net: stmmac: move TX timer arm after DMA enable +Date: Wed, 18 Oct 2023 14:35:49 +0200 +Subject: [PATCH 2/3] net: stmmac: move TX timer arm after DMA enable Move TX timer arm call after DMA interrupt is enabled again. @@ -11,15 +11,21 @@ we permit to correctly skip if a DMA interrupt has been fired and a napi has been scheduled again. Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni --- - .../net/ethernet/stmicro/stmmac/stmmac_main.c | 19 +++++++++++++++---- - 1 file changed, 15 insertions(+), 4 deletions(-) + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 22 +++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -2530,7 +2530,8 @@ static void stmmac_bump_dma_threshold(st +@@ -2528,9 +2528,13 @@ static void stmmac_bump_dma_threshold(st + * @priv: driver private structure + * @budget: napi budget limiting this functions packet handling * @queue: TX queue index ++ * @pending_packets: signal to arm the TX coal timer * Description: it reclaims the transmit resources after transmission completes. ++ * If some packets still needs to be handled, due to TX coalesce, set ++ * pending_packets to true to make NAPI arm the TX coal timer. */ -static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue) +static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue, @@ -27,7 +33,7 @@ Signed-off-by: Christian Marangi { struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; unsigned int bytes_compl = 0, pkts_compl = 0; -@@ -2693,7 +2694,7 @@ static int stmmac_tx_clean(struct stmmac +@@ -2693,7 +2697,7 @@ static int stmmac_tx_clean(struct stmmac /* We still have pending packets, let's call for a new scheduling */ if (tx_q->dirty_tx != tx_q->cur_tx) @@ -36,7 +42,7 @@ Signed-off-by: Christian Marangi __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue)); -@@ -5473,12 +5474,13 @@ static int stmmac_napi_poll_tx(struct na +@@ -5485,12 +5489,13 @@ static int stmmac_napi_poll_tx(struct na struct stmmac_channel *ch = container_of(napi, struct stmmac_channel, tx_napi); struct stmmac_priv *priv = ch->priv_data; @@ -51,7 +57,7 @@ Signed-off-by: Christian Marangi work_done = min(work_done, budget); if (work_done < budget && napi_complete_done(napi, work_done)) { -@@ -5489,6 +5491,10 @@ static int stmmac_napi_poll_tx(struct na +@@ -5501,6 +5506,10 @@ static int stmmac_napi_poll_tx(struct na spin_unlock_irqrestore(&ch->lock, flags); } @@ -62,11 +68,12 @@ Signed-off-by: Christian Marangi return work_done; } -@@ -5498,11 +5504,12 @@ static int stmmac_napi_poll_rxtx(struct +@@ -5509,12 +5518,13 @@ static int stmmac_napi_poll_rxtx(struct + struct stmmac_channel *ch = container_of(napi, struct stmmac_channel, rxtx_napi); struct stmmac_priv *priv = ch->priv_data; - int rx_done, tx_done, rxtx_done; + bool tx_pending_packets = false; + int rx_done, tx_done, rxtx_done; u32 chan = ch->index; priv->xstats.napi_poll++; @@ -76,7 +83,7 @@ Signed-off-by: Christian Marangi tx_done = min(tx_done, budget); rx_done = stmmac_rx_zc(priv, budget, chan); -@@ -5527,6 +5534,10 @@ static int stmmac_napi_poll_rxtx(struct +@@ -5539,6 +5549,10 @@ static int stmmac_napi_poll_rxtx(struct spin_unlock_irqrestore(&ch->lock, flags); } diff --git a/target/linux/ipq806x/patches-6.1/700-04-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch b/target/linux/generic/backport-6.1/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch similarity index 86% rename from target/linux/ipq806x/patches-6.1/700-04-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch rename to target/linux/generic/backport-6.1/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch index 3f97702097..cc8cbf5a16 100644 --- a/target/linux/ipq806x/patches-6.1/700-04-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch +++ b/target/linux/generic/backport-6.1/771-v6.7-03-net-stmmac-increase-TX-coalesce-timer-to-5ms.patch @@ -1,7 +1,7 @@ -From 95281ab33fbaa1e974bceb20cfb0f5c92934f2b3 Mon Sep 17 00:00:00 2001 +From 039550960a2235cfe2dfaa773df9f98f8da31a0c Mon Sep 17 00:00:00 2001 From: Christian Marangi -Date: Mon, 18 Sep 2023 15:11:13 +0200 -Subject: [PATCH 4/4] net: stmmac: increase TX coalesce timer to 5ms +Date: Wed, 18 Oct 2023 14:35:50 +0200 +Subject: [PATCH 3/3] net: stmmac: increase TX coalesce timer to 5ms Commit 8fce33317023 ("net: stmmac: Rework coalesce timer and fix multi-queue races") decreased the TX coalesce timer from 40ms to 1ms. @@ -20,6 +20,7 @@ much interrupt to be generated and permitting good performance for internet oriented devices. Signed-off-by: Christian Marangi +Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch b/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch index a9e3c71d54..c4141eee93 100644 --- a/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch +++ b/target/linux/generic/backport-6.1/794-v6.2-net-core-Allow-live-renaming-when-an-interface-is-up.patch @@ -46,7 +46,7 @@ Signed-off-by: David S. Miller --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1668,7 +1668,6 @@ struct net_device_ops { +@@ -1691,7 +1691,6 @@ struct net_device_ops { * @IFF_FAILOVER: device is a failover master device * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device @@ -54,7 +54,7 @@ Signed-off-by: David S. Miller * @IFF_TX_SKB_NO_LINEAR: device/driver is capable of xmitting frames with * skb_headlen(skb) == 0 (data starts from frag0) * @IFF_CHANGE_PROTO_DOWN: device supports setting carrier via IFLA_PROTO_DOWN -@@ -1704,7 +1703,7 @@ enum netdev_priv_flags { +@@ -1727,7 +1726,7 @@ enum netdev_priv_flags { IFF_FAILOVER = 1<<27, IFF_FAILOVER_SLAVE = 1<<28, IFF_L3MDEV_RX_HANDLER = 1<<29, @@ -63,7 +63,7 @@ Signed-off-by: David S. Miller IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), }; -@@ -1739,7 +1738,6 @@ enum netdev_priv_flags { +@@ -1762,7 +1761,6 @@ enum netdev_priv_flags { #define IFF_FAILOVER IFF_FAILOVER #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER diff --git a/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch index 40aeb5da6f..b0be9dfdcb 100644 --- a/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-6.1/721-net-add-packet-mangeling.patch @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1707,6 +1707,7 @@ enum netdev_priv_flags { +@@ -1730,6 +1730,7 @@ enum netdev_priv_flags { /* was IFF_LIVE_RENAME_OK */ IFF_TX_SKB_NO_LINEAR = BIT_ULL(31), IFF_CHANGE_PROTO_DOWN = BIT_ULL(32), @@ -27,7 +27,7 @@ Signed-off-by: Felix Fietkau }; #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN -@@ -1740,6 +1741,7 @@ enum netdev_priv_flags { +@@ -1763,6 +1764,7 @@ enum netdev_priv_flags { #define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE #define IFF_L3MDEV_RX_HANDLER IFF_L3MDEV_RX_HANDLER #define IFF_TX_SKB_NO_LINEAR IFF_TX_SKB_NO_LINEAR @@ -35,7 +35,7 @@ Signed-off-by: Felix Fietkau /* Specifies the type of the struct net_device::ml_priv pointer */ enum netdev_ml_priv_type { -@@ -2108,6 +2110,11 @@ struct net_device { +@@ -2131,6 +2133,11 @@ struct net_device { const struct tlsdev_ops *tlsdev_ops; #endif @@ -47,7 +47,7 @@ Signed-off-by: Felix Fietkau const struct header_ops *header_ops; unsigned char operstate; -@@ -2183,6 +2190,10 @@ struct net_device { +@@ -2206,6 +2213,10 @@ struct net_device { struct mctp_dev __rcu *mctp_ptr; #endif diff --git a/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index 8763b92c02..11850c0418 100644 --- a/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/target/linux/generic/pending-6.1/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -2134,6 +2134,8 @@ struct net_device { +@@ -2157,6 +2157,8 @@ struct net_device { struct netdev_hw_addr_list mc; struct netdev_hw_addr_list dev_addrs; diff --git a/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch b/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch index df422e3a08..a7a4bafbb6 100644 --- a/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch +++ b/target/linux/generic/pending-6.1/731-net-permit-ieee80211_ptr-even-with-no-CFG82111-suppo.patch @@ -17,7 +17,7 @@ Signed-off-by: Christian Marangi --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -2169,7 +2169,7 @@ struct net_device { +@@ -2192,7 +2192,7 @@ struct net_device { #if IS_ENABLED(CONFIG_AX25) void *ax25_ptr; #endif diff --git a/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch b/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch index baaf850fe4..944e4d1869 100644 --- a/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch +++ b/target/linux/generic/pending-6.1/760-net-core-add-optional-threading-for-backlog-processi.patch @@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -520,6 +520,7 @@ static inline bool napi_complete(struct +@@ -543,6 +543,7 @@ static inline bool napi_complete(struct } int dev_set_threaded(struct net_device *dev, bool threaded); @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau /** * napi_disable - prevent NAPI from scheduling -@@ -3129,6 +3130,7 @@ struct softnet_data { +@@ -3152,6 +3153,7 @@ struct softnet_data { unsigned int processed; unsigned int time_squeeze; unsigned int received_rps; From cf43e523c2ee79c4b2bfb3e74fb7083c05d9ea5d Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 21 Jan 2024 22:38:11 +0100 Subject: [PATCH 173/222] ipq806x: renumber backport patches starting from 000 Renumber backport patches starting from 000 to tidy things up. Also fix patch name format for the mmc backport patch. Refresh patches affected by this renumber change. Signed-off-by: Christian Marangi --- ...01-v6.2-clk-qcom-kpss-xcc-register-it-as-clk-provider.patch} | 0 ...-clk-qcom-krait-cc-use-devm-variant-for-clk-notifier-.patch} | 0 ...-clk-qcom-krait-cc-fix-wrong-parent-order-for-seconda.patch} | 0 ...-clk-qcom-krait-cc-also-enable-secondary-mux-and-div-.patch} | 0 ...-clk-qcom-krait-cc-handle-secondary-mux-sourcing-out-.patch} | 0 ...-05-clk-qcom-krait-cc-convert-to-devm_clk_hw_register.patch} | 0 ...-v6.2-06-clk-qcom-krait-cc-convert-to-parent_data-API.patch} | 0 ...2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch} | 2 +- ...2-ARM-dts-qcom-add-krait-cache-compatible-for-ipq806x-.patch | 2 +- .../115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch | 2 +- 10 files changed, 3 insertions(+), 3 deletions(-) rename target/linux/ipq806x/patches-6.1/{120-v6.2-clk-qcom-kpss-xcc-register-it-as-clk-provider.patch => 001-v6.2-clk-qcom-kpss-xcc-register-it-as-clk-provider.patch} (100%) rename target/linux/ipq806x/patches-6.1/{121-v6.2-01-clk-qcom-krait-cc-use-devm-variant-for-clk-notifier-.patch => 002-v6.2-01-clk-qcom-krait-cc-use-devm-variant-for-clk-notifier-.patch} (100%) rename target/linux/ipq806x/patches-6.1/{121-v6.2-02-clk-qcom-krait-cc-fix-wrong-parent-order-for-seconda.patch => 002-v6.2-02-clk-qcom-krait-cc-fix-wrong-parent-order-for-seconda.patch} (100%) rename target/linux/ipq806x/patches-6.1/{121-v6.2-03-clk-qcom-krait-cc-also-enable-secondary-mux-and-div-.patch => 002-v6.2-03-clk-qcom-krait-cc-also-enable-secondary-mux-and-div-.patch} (100%) rename target/linux/ipq806x/patches-6.1/{121-v6.2-04-clk-qcom-krait-cc-handle-secondary-mux-sourcing-out-.patch => 002-v6.2-04-clk-qcom-krait-cc-handle-secondary-mux-sourcing-out-.patch} (100%) rename target/linux/ipq806x/patches-6.1/{121-v6.2-05-clk-qcom-krait-cc-convert-to-devm_clk_hw_register.patch => 002-v6.2-05-clk-qcom-krait-cc-convert-to-devm_clk_hw_register.patch} (100%) rename target/linux/ipq806x/patches-6.1/{121-v6.2-06-clk-qcom-krait-cc-convert-to-parent_data-API.patch => 002-v6.2-06-clk-qcom-krait-cc-convert-to-parent_data-API.patch} (100%) rename target/linux/ipq806x/patches-6.1/{131-6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch => 003-v6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch} (98%) diff --git a/target/linux/ipq806x/patches-6.1/120-v6.2-clk-qcom-kpss-xcc-register-it-as-clk-provider.patch b/target/linux/ipq806x/patches-6.1/001-v6.2-clk-qcom-kpss-xcc-register-it-as-clk-provider.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/120-v6.2-clk-qcom-kpss-xcc-register-it-as-clk-provider.patch rename to target/linux/ipq806x/patches-6.1/001-v6.2-clk-qcom-kpss-xcc-register-it-as-clk-provider.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-01-clk-qcom-krait-cc-use-devm-variant-for-clk-notifier-.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-01-clk-qcom-krait-cc-use-devm-variant-for-clk-notifier-.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-01-clk-qcom-krait-cc-use-devm-variant-for-clk-notifier-.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-01-clk-qcom-krait-cc-use-devm-variant-for-clk-notifier-.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-02-clk-qcom-krait-cc-fix-wrong-parent-order-for-seconda.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-02-clk-qcom-krait-cc-fix-wrong-parent-order-for-seconda.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-02-clk-qcom-krait-cc-fix-wrong-parent-order-for-seconda.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-02-clk-qcom-krait-cc-fix-wrong-parent-order-for-seconda.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-03-clk-qcom-krait-cc-also-enable-secondary-mux-and-div-.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-03-clk-qcom-krait-cc-also-enable-secondary-mux-and-div-.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-03-clk-qcom-krait-cc-also-enable-secondary-mux-and-div-.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-03-clk-qcom-krait-cc-also-enable-secondary-mux-and-div-.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-04-clk-qcom-krait-cc-handle-secondary-mux-sourcing-out-.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-04-clk-qcom-krait-cc-handle-secondary-mux-sourcing-out-.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-04-clk-qcom-krait-cc-handle-secondary-mux-sourcing-out-.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-04-clk-qcom-krait-cc-handle-secondary-mux-sourcing-out-.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-05-clk-qcom-krait-cc-convert-to-devm_clk_hw_register.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-05-clk-qcom-krait-cc-convert-to-devm_clk_hw_register.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-05-clk-qcom-krait-cc-convert-to-devm_clk_hw_register.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-05-clk-qcom-krait-cc-convert-to-devm_clk_hw_register.patch diff --git a/target/linux/ipq806x/patches-6.1/121-v6.2-06-clk-qcom-krait-cc-convert-to-parent_data-API.patch b/target/linux/ipq806x/patches-6.1/002-v6.2-06-clk-qcom-krait-cc-convert-to-parent_data-API.patch similarity index 100% rename from target/linux/ipq806x/patches-6.1/121-v6.2-06-clk-qcom-krait-cc-convert-to-parent_data-API.patch rename to target/linux/ipq806x/patches-6.1/002-v6.2-06-clk-qcom-krait-cc-convert-to-parent_data-API.patch diff --git a/target/linux/ipq806x/patches-6.1/131-6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch b/target/linux/ipq806x/patches-6.1/003-v6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch similarity index 98% rename from target/linux/ipq806x/patches-6.1/131-6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch rename to target/linux/ipq806x/patches-6.1/003-v6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch index e542421085..7e65f4cdff 100644 --- a/target/linux/ipq806x/patches-6.1/131-6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch +++ b/target/linux/ipq806x/patches-6.1/003-v6.2-ARM-dts-qcom-ipq8064-disable-mmc-ddr-1_8v-for-sdcc1.patch @@ -18,7 +18,7 @@ Link: https://lore.kernel.org/r/20221024233817.27410-1-ansuelsmth@gmail.com --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -932,7 +932,6 @@ +@@ -756,7 +756,6 @@ non-removable; cap-sd-highspeed; cap-mmc-highspeed; diff --git a/target/linux/ipq806x/patches-6.1/114-02-ARM-dts-qcom-add-krait-cache-compatible-for-ipq806x-.patch b/target/linux/ipq806x/patches-6.1/114-02-ARM-dts-qcom-add-krait-cache-compatible-for-ipq806x-.patch index 3a6c281793..45f05dd423 100644 --- a/target/linux/ipq806x/patches-6.1/114-02-ARM-dts-qcom-add-krait-cache-compatible-for-ipq806x-.patch +++ b/target/linux/ipq806x/patches-6.1/114-02-ARM-dts-qcom-add-krait-cache-compatible-for-ipq806x-.patch @@ -31,7 +31,7 @@ Signed-off-by: Christian Marangi }; opp_table_l2: opp_table_l2 { -@@ -1410,6 +1400,16 @@ +@@ -1409,6 +1399,16 @@ #reset-cells = <1>; }; diff --git a/target/linux/ipq806x/patches-6.1/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch b/target/linux/ipq806x/patches-6.1/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch index a324b6facf..24e0ecf619 100644 --- a/target/linux/ipq806x/patches-6.1/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch +++ b/target/linux/ipq806x/patches-6.1/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch @@ -32,7 +32,7 @@ Signed-off-by: Christian Marangi thermal-zones { sensor0-thermal { polling-delay-passive = <0>; -@@ -1410,6 +1422,13 @@ +@@ -1409,6 +1421,13 @@ operating-points-v2 = <&opp_table_l2>; }; From dac2f07c230af4e8082c15c9be3bbe9a4c1835b7 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 21 Jan 2024 22:42:54 +0100 Subject: [PATCH 174/222] ipq806x: replace tsens patch with upstream version Replace tsens patch with upstream version. Signed-off-by: Christian Marangi --- ...com-tsens-Init-debugfs-only-with-su.patch} | 21 ++++---- ...qcom-tsens-Fix-wrong-version-id-dbg_.patch | 29 ++++++++++ ...qcom-tsens-Rework-debugfs-file-struc.patch | 54 +++++++++++++++++++ ...tsens-simplify-debugfs-init-function.patch | 54 ------------------- 4 files changed, 94 insertions(+), 64 deletions(-) rename target/linux/ipq806x/patches-6.1/{110-01-thermal-qcom-tsens-init-debugfs-only-with-successful.patch => 004-v6.2-01-thermal-drivers-qcom-tsens-Init-debugfs-only-with-su.patch} (52%) create mode 100644 target/linux/ipq806x/patches-6.1/004-v6.2-02-thermal-drivers-qcom-tsens-Fix-wrong-version-id-dbg_.patch create mode 100644 target/linux/ipq806x/patches-6.1/004-v6.2-03-thermal-drivers-qcom-tsens-Rework-debugfs-file-struc.patch delete mode 100644 target/linux/ipq806x/patches-6.1/110-02-thermal-qcom-tsens-simplify-debugfs-init-function.patch diff --git a/target/linux/ipq806x/patches-6.1/110-01-thermal-qcom-tsens-init-debugfs-only-with-successful.patch b/target/linux/ipq806x/patches-6.1/004-v6.2-01-thermal-drivers-qcom-tsens-Init-debugfs-only-with-su.patch similarity index 52% rename from target/linux/ipq806x/patches-6.1/110-01-thermal-qcom-tsens-init-debugfs-only-with-successful.patch rename to target/linux/ipq806x/patches-6.1/004-v6.2-01-thermal-drivers-qcom-tsens-Init-debugfs-only-with-su.patch index c9b20a0222..76df0f5681 100644 --- a/target/linux/ipq806x/patches-6.1/110-01-thermal-qcom-tsens-init-debugfs-only-with-successful.patch +++ b/target/linux/ipq806x/patches-6.1/004-v6.2-01-thermal-drivers-qcom-tsens-Init-debugfs-only-with-su.patch @@ -1,18 +1,20 @@ -From 8f32d48a309246a80bdca505968085a484d54408 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Mon, 19 Apr 2021 03:01:53 +0200 -Subject: [thermal-next PATCH v2 1/2] thermal: qcom: tsens: init debugfs only with +From de48d8766afcd97d147699aaff78a338081c9973 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 22 Oct 2022 14:56:55 +0200 +Subject: [PATCH 1/3] thermal/drivers/qcom/tsens: Init debugfs only with successful probe -calibrate and tsens_register can fail or PROBE_DEFER. This will cause a +Calibrate and tsens_register can fail or PROBE_DEFER. This will cause a double or a wrong init of the debugfs information. Init debugfs only with successful probe fixing warning about directory already present. -Signed-off-by: Ansuel Smith +Signed-off-by: Christian Marangi Acked-by: Thara Gopinath +Link: https://lore.kernel.org/r/20221022125657.22530-2-ansuelsmth@gmail.com +Signed-off-by: Daniel Lezcano --- - drivers/thermal/qcom/tsens.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) + drivers/thermal/qcom/tsens.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -25,13 +27,12 @@ Acked-by: Thara Gopinath err_put_device: put_device(&op->dev); return ret; -@@ -1156,7 +1154,12 @@ static int tsens_probe(struct platform_d +@@ -1156,7 +1154,11 @@ static int tsens_probe(struct platform_d } } - return tsens_register(priv); + ret = tsens_register(priv); -+ + if (!ret) + tsens_debug_init(pdev); + diff --git a/target/linux/ipq806x/patches-6.1/004-v6.2-02-thermal-drivers-qcom-tsens-Fix-wrong-version-id-dbg_.patch b/target/linux/ipq806x/patches-6.1/004-v6.2-02-thermal-drivers-qcom-tsens-Fix-wrong-version-id-dbg_.patch new file mode 100644 index 0000000000..10f1e36b58 --- /dev/null +++ b/target/linux/ipq806x/patches-6.1/004-v6.2-02-thermal-drivers-qcom-tsens-Fix-wrong-version-id-dbg_.patch @@ -0,0 +1,29 @@ +From c7e077e921fa94e0c06c8d14af6c0504c8a5f4bd Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 22 Oct 2022 14:56:56 +0200 +Subject: [PATCH 2/3] thermal/drivers/qcom/tsens: Fix wrong version id + dbg_version_show + +For VER_0 the version was incorrectly reported as 0.1.0. + +Fix that and correctly report the major version for this old tsens +revision. + +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20221022125657.22530-3-ansuelsmth@gmail.com +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/qcom/tsens.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/thermal/qcom/tsens.c ++++ b/drivers/thermal/qcom/tsens.c +@@ -692,7 +692,7 @@ static int dbg_version_show(struct seq_f + return ret; + seq_printf(s, "%d.%d.%d\n", maj_ver, min_ver, step_ver); + } else { +- seq_puts(s, "0.1.0\n"); ++ seq_printf(s, "0.%d.0\n", priv->feat->ver_major); + } + + return 0; diff --git a/target/linux/ipq806x/patches-6.1/004-v6.2-03-thermal-drivers-qcom-tsens-Rework-debugfs-file-struc.patch b/target/linux/ipq806x/patches-6.1/004-v6.2-03-thermal-drivers-qcom-tsens-Rework-debugfs-file-struc.patch new file mode 100644 index 0000000000..63cce7974b --- /dev/null +++ b/target/linux/ipq806x/patches-6.1/004-v6.2-03-thermal-drivers-qcom-tsens-Rework-debugfs-file-struc.patch @@ -0,0 +1,54 @@ +From 89992d95ed1046338c7866ef7bbe6de543a2af91 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 22 Oct 2022 14:56:57 +0200 +Subject: [PATCH 3/3] thermal/drivers/qcom/tsens: Rework debugfs file structure + +The current tsens debugfs structure is composed by: +- a tsens dir in debugfs with a version file +- a directory for each tsens istance with sensors file to dump all the + sensors value. + +This works on the assumption that we have the same version for each +istance but this assumption seems fragile and with more than one tsens +istance results in the version file not tracking each of them. + +A better approach is to just create a subdirectory for each tsens +istance and put there version and sensors debugfs file. + +Using this new implementation results in less code since debugfs entry +are created only on successful tsens probe. + +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20221022125657.22530-4-ansuelsmth@gmail.com +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/qcom/tsens.c | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +--- a/drivers/thermal/qcom/tsens.c ++++ b/drivers/thermal/qcom/tsens.c +@@ -704,21 +704,14 @@ DEFINE_SHOW_ATTRIBUTE(dbg_sensors); + static void tsens_debug_init(struct platform_device *pdev) + { + struct tsens_priv *priv = platform_get_drvdata(pdev); +- struct dentry *root, *file; + +- root = debugfs_lookup("tsens", NULL); +- if (!root) ++ priv->debug_root = debugfs_lookup("tsens", NULL); ++ if (!priv->debug_root) + priv->debug_root = debugfs_create_dir("tsens", NULL); +- else +- priv->debug_root = root; +- +- file = debugfs_lookup("version", priv->debug_root); +- if (!file) +- debugfs_create_file("version", 0444, priv->debug_root, +- pdev, &dbg_version_fops); + + /* A directory for each instance of the TSENS IP */ + priv->debug = debugfs_create_dir(dev_name(&pdev->dev), priv->debug_root); ++ debugfs_create_file("version", 0444, priv->debug, pdev, &dbg_version_fops); + debugfs_create_file("sensors", 0444, priv->debug, pdev, &dbg_sensors_fops); + } + #else diff --git a/target/linux/ipq806x/patches-6.1/110-02-thermal-qcom-tsens-simplify-debugfs-init-function.patch b/target/linux/ipq806x/patches-6.1/110-02-thermal-qcom-tsens-simplify-debugfs-init-function.patch deleted file mode 100644 index 0fbc4bd8ca..0000000000 --- a/target/linux/ipq806x/patches-6.1/110-02-thermal-qcom-tsens-simplify-debugfs-init-function.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 4204f22060f7a5d42c6ccb4d4c25a6a875571099 Mon Sep 17 00:00:00 2001 -From: Ansuel Smith -Date: Mon, 19 Apr 2021 03:08:37 +0200 -Subject: [thermal-next PATCH v2 2/2] thermal: qcom: tsens: simplify debugfs init - function - -Simplify debugfs init function. -- Add check for existing dev directory. -- Fix wrong version in dbg_version_show (with version 0.0.0, 0.1.0 was - incorrectly reported) - -Signed-off-by: Ansuel Smith -Reviewed-by: Thara Gopinath ---- - drivers/thermal/qcom/tsens.c | 16 +++++++--------- - 1 file changed, 7 insertions(+), 9 deletions(-) - ---- a/drivers/thermal/qcom/tsens.c -+++ b/drivers/thermal/qcom/tsens.c -@@ -692,7 +692,7 @@ static int dbg_version_show(struct seq_f - return ret; - seq_printf(s, "%d.%d.%d\n", maj_ver, min_ver, step_ver); - } else { -- seq_puts(s, "0.1.0\n"); -+ seq_printf(s, "0.%d.0\n", priv->feat->ver_major); - } - - return 0; -@@ -704,21 +704,17 @@ DEFINE_SHOW_ATTRIBUTE(dbg_sensors); - static void tsens_debug_init(struct platform_device *pdev) - { - struct tsens_priv *priv = platform_get_drvdata(pdev); -- struct dentry *root, *file; - -- root = debugfs_lookup("tsens", NULL); -- if (!root) -+ priv->debug_root = debugfs_lookup("tsens", NULL); -+ if (!priv->debug_root) - priv->debug_root = debugfs_create_dir("tsens", NULL); -- else -- priv->debug_root = root; - -- file = debugfs_lookup("version", priv->debug_root); -- if (!file) -+ if (!debugfs_lookup("version", priv->debug_root)) - debugfs_create_file("version", 0444, priv->debug_root, - pdev, &dbg_version_fops); - - /* A directory for each instance of the TSENS IP */ -- priv->debug = debugfs_create_dir(dev_name(&pdev->dev), priv->debug_root); -+ priv->debug = debugfs_lookup(dev_name(&pdev->dev), priv->debug_root); - debugfs_create_file("sensors", 0444, priv->debug, pdev, &dbg_sensors_fops); - } - #else From 4d2a82a73c79aea41f14feaaeea319a965041f63 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Mon, 22 Jan 2024 01:28:52 +0100 Subject: [PATCH 175/222] ubox: update to Git HEAD (2024-01-22) b2f6da671f7c kmodloader: Fix NULL pointer dereferences error 202d7c05029a kmodloader: fix memory leak in print_modinfo 6cf7d837ee7e kmodloader: fix TOCTOU problem with scan_builtin_modules Signed-off-by: Christian Marangi --- package/system/ubox/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/system/ubox/Makefile b/package/system/ubox/Makefile index 42987f536b..317055453f 100644 --- a/package/system/ubox/Makefile +++ b/package/system/ubox/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/ubox.git -PKG_SOURCE_DATE:=2024-01-15 -PKG_SOURCE_VERSION:=c006dccecb6f1cf694c9fb9efc6727cbd2ab9ae4 -PKG_MIRROR_HASH:=7919d8d6f06fa50342eec805902d17c61d1224d9d35c392d3c5c36fc782a5c75 +PKG_SOURCE_DATE:=2024-01-22 +PKG_SOURCE_VERSION:=6cf7d837ee7e392ee047aee4f45132f4176b7493 +PKG_MIRROR_HASH:=de63c19f095459dcd08c97f8391b8c735708453da8f31080935ce02c1b1f054a CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 From b66a340837388a159b97c46efb45664f8ec42865 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Mon, 22 Jan 2024 01:46:43 +0100 Subject: [PATCH 176/222] fstools: update to Git HEAD (2024-01-22) 2171f6261556 libfstools: force mkfs when formatting overlay 08cd7083cac4 libfstools: fit: improve fit_volume_find string handling Signed-off-by: Christian Marangi --- package/system/fstools/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/system/fstools/Makefile b/package/system/fstools/Makefile index 87281a0076..717e59f836 100644 --- a/package/system/fstools/Makefile +++ b/package/system/fstools/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/fstools.git -PKG_MIRROR_HASH:=964c3bf2b1d16369380bad1098ab0a1b996f714bb448322bd82ba80aa9acd03f -PKG_SOURCE_DATE:=2024-01-15 -PKG_SOURCE_VERSION:=325d63d67006c5526ab9b0fbc62329da48aa93af +PKG_MIRROR_HASH:=32e39891455b602e9deb367c9ce2d099dc72353fad0bf0433307416925f7b393 +PKG_SOURCE_DATE:=2024-01-22 +PKG_SOURCE_VERSION:=08cd7083cac4bddf88459efa0881ee52858e7d0a CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 From fd46680966e9b9bc282b665282e2e6a22a27c26e Mon Sep 17 00:00:00 2001 From: Tomasz Maciej Nowak Date: Wed, 10 Jan 2024 16:59:48 +0100 Subject: [PATCH 177/222] ramips: mt76x8: enable small_flash feature Some of devices in this target have only 8 MiB space and are closing to borders of usable space. Particularly, TP-Link RE305 v1 already suffers from this issue[1], where with current partition layout, on release images, there's not enough space for overlay. So activate small_flash feature, which will remove some userspace hardening but will gain almost 1 MiB additional flash memory space. Here is small size comparison of similar device (RE365 v1) with default config + LuCI: kernel rootfs sysupgrade current: 2305728 3635044 5964584 small_flash: 1713571 3320132 5047080 1. https://github.com/openwrt/openwrt/issues/14215 Suggested-by: Sander Vanheule Signed-off-by: Tomasz Maciej Nowak --- target/linux/ramips/mt76x8/target.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ramips/mt76x8/target.mk b/target/linux/ramips/mt76x8/target.mk index 862736cb2f..cfc2655cac 100644 --- a/target/linux/ramips/mt76x8/target.mk +++ b/target/linux/ramips/mt76x8/target.mk @@ -4,7 +4,7 @@ SUBTARGET:=mt76x8 BOARDNAME:=MT76x8 based boards -FEATURES+=usb ramdisk +FEATURES+=usb ramdisk small_flash CPU_TYPE:=24kc DEFAULT_PACKAGES += kmod-mt7603 wpad-basic-mbedtls swconfig From 7ad6e8c312d0f46b8c4aca86aee15aaad46f1191 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 22 Jan 2024 13:00:41 +0100 Subject: [PATCH 178/222] scripts/rstrip.sh: ignore /lib/firmware On some platforms, some firmware files might look like executables. These need to be ignored in order to avoid messing them up. Signed-off-by: Felix Fietkau --- scripts/rstrip.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/rstrip.sh b/scripts/rstrip.sh index e47960a941..2aa7e96fda 100755 --- a/scripts/rstrip.sh +++ b/scripts/rstrip.sh @@ -20,7 +20,7 @@ TARGETS=$* exit 1 } -find $TARGETS -type f -a -exec file {} \; | \ +find $TARGETS -not -path \*/lib/firmware/\* -a -type f -a -exec file {} \; | \ sed -n -e 's/^\(.*\):.*ELF.*\(executable\|relocatable\|shared object\).*,.*/\1:\2/p' | \ ( IFS=":" From ad25cfb6b8a282e47344fba59f42af61e115a8df Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Tue, 9 Jan 2024 11:21:11 +0100 Subject: [PATCH 179/222] qualcommax: add SMP affinity script By default Linux will default to most IRQ-s being mapped to core 0 which during high loads will completely swamp the core 0, so lets add the widely used script that has been floating around forums for a long time to try and optimize the IRQ mapping a bit. Signed-off-by: Robert Marko --- .../base-files/etc/init.d/smp_affinity | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100755 target/linux/qualcommax/ipq807x/base-files/etc/init.d/smp_affinity diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/init.d/smp_affinity b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/smp_affinity new file mode 100755 index 0000000000..05d13fff63 --- /dev/null +++ b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/smp_affinity @@ -0,0 +1,36 @@ +#!/bin/sh /etc/rc.common + +START=93 + +enable_affinity_ipq807x() { + set_affinity() { + irq=$(awk "/$1/{ print substr(\$1, 1, length(\$1)-1); exit }" /proc/interrupts) + [ -n "$irq" ] && echo $2 > /proc/irq/$irq/smp_affinity + } + + # assign 4 rx interrupts to each core + set_affinity 'reo2host-destination-ring1' 1 + set_affinity 'reo2host-destination-ring2' 2 + set_affinity 'reo2host-destination-ring3' 4 + set_affinity 'reo2host-destination-ring4' 8 + + # assign 3 tcl completions to last 3 CPUs + set_affinity 'wbm2host-tx-completions-ring1' 2 + set_affinity 'wbm2host-tx-completions-ring2' 4 + set_affinity 'wbm2host-tx-completions-ring3' 8 + + # assign 3 ppdu mac interrupts to last 3 cores + set_affinity 'ppdu-end-interrupts-mac1' 2 + set_affinity 'ppdu-end-interrupts-mac2' 4 + set_affinity 'ppdu-end-interrupts-mac3' 8 + + # assign lan/wan to core 4 + set_affinity 'edma_txcmpl' 8 + set_affinity 'edma_rxfill' 8 + set_affinity 'edma_rxdesc' 8 + set_affinity 'edma_misc' 8 +} + +boot() { + enable_affinity_ipq807x +} From 65fb97b4507bcff3f98739975e9cc7df53137b12 Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Sun, 21 Jan 2024 19:02:33 +0100 Subject: [PATCH 180/222] lantiq: fix boot isues on danube boards Enabling SMP on Danube[1] is incompatible with a patch that adds support for interrupt handling on all cores on other platforms[2]. This patch fixes the mentioned issue. 1. 084c20f6c54180f2dc6b3efc1c5ba9b62afbaf26 ("lantiq: xway: kernel: enable SMP support ") 2. fbd33d61648ae8982fbada7ad3b6d8222b367ab5 ("lantiq: enable interrupts on second VPEs") Fixes: #13934 Fixes: #14283 Signed-off-by: Aleksander Jan Bajkowski --- ...egister-smp_ops-on-non-smp-platforms.patch | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 target/linux/lantiq/patches-5.15/0321-MIPS-lantiq-register-smp_ops-on-non-smp-platforms.patch diff --git a/target/linux/lantiq/patches-5.15/0321-MIPS-lantiq-register-smp_ops-on-non-smp-platforms.patch b/target/linux/lantiq/patches-5.15/0321-MIPS-lantiq-register-smp_ops-on-non-smp-platforms.patch new file mode 100644 index 0000000000..78043545b0 --- /dev/null +++ b/target/linux/lantiq/patches-5.15/0321-MIPS-lantiq-register-smp_ops-on-non-smp-platforms.patch @@ -0,0 +1,33 @@ +From 6e8d8b183accefae42c62f1bd495a405ce454c7d Mon Sep 17 00:00:00 2001 +From: Aleksander Jan Bajkowski +Date: Sun, 21 Jan 2024 18:36:23 +0100 +Subject: [PATCH] MIPS: lantiq: register smp_ops on non-smp platforms + +Lantiq uses a common kernel config for devices with 24Kc and 34Kc cores. +The changes made previously to add support for interrupts on all cores +work on 24Kc platforms with SMP disabled and 34Kc platforms with SMP +enabled. This patch fixes boot issues on Danube (single core 24Kc) with +SMP enabled. + +Fixes: 730320fd770d ("MIPS: lantiq: enable all hardware interrupts on second VPE") +Signed-off-by: Aleksander Jan Bajkowski +--- + arch/mips/lantiq/prom.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/arch/mips/lantiq/prom.c ++++ b/arch/mips/lantiq/prom.c +@@ -123,10 +123,9 @@ void __init prom_init(void) + prom_init_cmdline(); + + #if defined(CONFIG_MIPS_MT_SMP) +- if (cpu_has_mipsmt) { +- lantiq_smp_ops = vsmp_smp_ops; ++ lantiq_smp_ops = vsmp_smp_ops; ++ if (cpu_has_mipsmt) + lantiq_smp_ops.init_secondary = lantiq_init_secondary; +- register_smp_ops(&lantiq_smp_ops); +- } ++ register_smp_ops(&lantiq_smp_ops); + #endif + } From 33f15dd6d41873b02eb8895b8886763659f1390c Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Tue, 23 Jan 2024 09:07:16 +0100 Subject: [PATCH 181/222] jsonfilter: update to Git HEAD (2024-01-23) 013b75ab0598 jsonfilter: drop legacy json-c support 594cfa86469c main: fix spurious premature parse aborts in array mode Fixes: https://bugs.openwrt.org/?task_id=3683 Fixes: https://github.com/openwrt/openwrt/issues/8703 Fixes: https://github.com/openwrt/openwrt/issues/11649 Fixes: https://github.com/openwrt/openwrt/issues/12344 Signed-off-by: Jo-Philipp Wich --- package/utils/jsonfilter/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/utils/jsonfilter/Makefile b/package/utils/jsonfilter/Makefile index 56f96d52b5..fda66bbfb4 100644 --- a/package/utils/jsonfilter/Makefile +++ b/package/utils/jsonfilter/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/jsonpath.git -PKG_SOURCE_DATE:=2018-02-04 -PKG_SOURCE_VERSION:=c7e938d6582a436dddc938539e72dd1320625c54 -PKG_MIRROR_HASH:=0601b4d7aa5ee096e99388a57cb0701673ab58fccd6ed2984a2abbd4f846e045 +PKG_SOURCE_DATE:=2024-01-23 +PKG_SOURCE_VERSION:=594cfa86469c005972ba750614f5b3f1af84d0f6 +PKG_MIRROR_HASH:=70d2e0870b746920af4569631218c38c1dddfee4f5d029ec8ea0a67999bdafcd CMAKE_INSTALL:=1 PKG_MAINTAINER:=Jo-Philipp Wich From 039f8a124133b24a413d747bbee7bb0bee679961 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Tue, 23 Jan 2024 09:19:35 +0100 Subject: [PATCH 182/222] wireguard-tools: avoid redundant jsonfilter calls Use a single jsonfilter expression to yield the list of logical wireguard interface names in shell compatible notation. Supersedes: #12344 Signed-off-by: Jo-Philipp Wich --- package/network/utils/wireguard-tools/Makefile | 2 +- package/network/utils/wireguard-tools/files/wireguard_watchdog | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package/network/utils/wireguard-tools/Makefile b/package/network/utils/wireguard-tools/Makefile index 5b1fab057d..e2a86c97d8 100644 --- a/package/network/utils/wireguard-tools/Makefile +++ b/package/network/utils/wireguard-tools/Makefile @@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=wireguard-tools PKG_VERSION:=1.0.20210914 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=wireguard-tools-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://git.zx2c4.com/wireguard-tools/snapshot/ diff --git a/package/network/utils/wireguard-tools/files/wireguard_watchdog b/package/network/utils/wireguard-tools/files/wireguard_watchdog index 0126f699bb..fc90f4a25b 100644 --- a/package/network/utils/wireguard-tools/files/wireguard_watchdog +++ b/package/network/utils/wireguard-tools/files/wireguard_watchdog @@ -59,7 +59,7 @@ check_peer_activity() { } # query ubus for all active wireguard interfaces -wg_ifaces=$(ubus -S call network.interface dump | jsonfilter -e '@.interface[@.up=true]' | jsonfilter -a -e '@[@.proto="wireguard"].interface' | tr "\n" " ") +eval $(ubus -S call network.interface dump | jsonfilter -e 'wg_ifaces=@.interface[@.up=true && @.proto="wireguard"].interface') # check every peer in every active wireguard interface config_load network From c527073b38bed10479ed258f964a2948d78c6624 Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Sun, 21 Jan 2024 16:51:16 -0500 Subject: [PATCH 183/222] ath79: fix mac address on eap2x5-1port devices Commit e816591e226a ("ath79: qca: convert to nvmem-layout") mistakenly switched the source of the mac address from the 'info' to 'art' partition. This patch updates all devices that share same 'parent' device tree file and was tested to fix the problem for eap225-outdoor-v3 - device that I actually own. Fixes: e816591e226a ("ath79: qca: convert to nvmem-layout") Signed-off-by: Nikolay Martynov [amend commit message] Signed-off-by: Sander Vanheule --- .../ath79/dts/qca9563_tplink_eap225-outdoor-v1.dts | 6 ------ .../ath79/dts/qca9563_tplink_eap225-outdoor-v3.dts | 6 ------ target/linux/ath79/dts/qca9563_tplink_eap225-v1.dts | 6 ------ target/linux/ath79/dts/qca9563_tplink_eap225-v3.dts | 6 ------ target/linux/ath79/dts/qca9563_tplink_eap225-v4.dts | 6 ------ target/linux/ath79/dts/qca9563_tplink_eap245-v1.dts | 6 ------ .../linux/ath79/dts/qca9563_tplink_eap2x5-1port.dtsi | 12 ++++++++++++ 7 files changed, 12 insertions(+), 36 deletions(-) diff --git a/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v1.dts b/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v1.dts index 9c1e82bf98..c3f1a130eb 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v1.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v1.dts @@ -35,12 +35,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - precalibration_ath10k: pre-calibration@5000 { reg = <0x5000 0x2f20>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v3.dts b/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v3.dts index 73700b626f..1fac6082cf 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v3.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap225-outdoor-v3.dts @@ -35,12 +35,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - precalibration_ath10k: pre-calibration@5000 { reg = <0x5000 0x2f20>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap225-v1.dts b/target/linux/ath79/dts/qca9563_tplink_eap225-v1.dts index 1e100b31a7..9d06a49626 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap225-v1.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap225-v1.dts @@ -56,12 +56,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - calibration_ath10k: calibration@5000 { reg = <0x5000 0x844>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap225-v3.dts b/target/linux/ath79/dts/qca9563_tplink_eap225-v3.dts index 32fba98051..5139bc7670 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap225-v3.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap225-v3.dts @@ -35,12 +35,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - precalibration_ath10k: pre-calibration@5000 { reg = <0x5000 0x2f20>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap225-v4.dts b/target/linux/ath79/dts/qca9563_tplink_eap225-v4.dts index 1c48775cdf..6e7ba5fede 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap225-v4.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap225-v4.dts @@ -35,12 +35,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - precalibration_ath10k: pre-calibration@5000 { reg = <0x5000 0x2f20>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap245-v1.dts b/target/linux/ath79/dts/qca9563_tplink_eap245-v1.dts index e7f21fafa5..af133813e7 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap245-v1.dts +++ b/target/linux/ath79/dts/qca9563_tplink_eap245-v1.dts @@ -49,12 +49,6 @@ #address-cells = <1>; #size-cells = <1>; - macaddr_info_8: macaddr@8 { - compatible = "mac-base"; - reg = <0x8 0x6>; - #nvmem-cell-cells = <1>; - }; - calibration_ath10k: calibration@5000 { reg = <0x5000 0x844>; }; diff --git a/target/linux/ath79/dts/qca9563_tplink_eap2x5-1port.dtsi b/target/linux/ath79/dts/qca9563_tplink_eap2x5-1port.dtsi index 9e0b97fcbf..3b36049d5e 100644 --- a/target/linux/ath79/dts/qca9563_tplink_eap2x5-1port.dtsi +++ b/target/linux/ath79/dts/qca9563_tplink_eap2x5-1port.dtsi @@ -55,6 +55,18 @@ label = "info"; reg = <0x030000 0x010000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_info_8: macaddr@8 { + compatible = "mac-base"; + reg = <0x8 0x6>; + #nvmem-cell-cells = <1>; + }; + }; }; partition@40000 { From 135e10762077d96a976c0b00311ce95e77082a5d Mon Sep 17 00:00:00 2001 From: Michel Thill Date: Sun, 7 Jan 2024 19:39:30 +0100 Subject: [PATCH 184/222] realtek: d-link dgs-1210-10p improve sfp support The current dts file of dgs-1210-10p doesn't support link states for the sfp ports (they are always up). This patch tries to give better support for this and was run tested on dgs-1210-10p. It was heavily inspired from Paul Fertser, RaylynnKnight and the author of dgs-1210-10mp-f.dts https://forum.openwrt.org/t/dlink-dgs-1210-10p-with-glc-t-co-sfp/170928 Signed-off-by: Michel Thill --- .../dts-5.15/rtl8382_d-link_dgs-1210-10p.dts | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-10p.dts b/target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-10p.dts index 16934ede3b..1aef88afd4 100644 --- a/target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-10p.dts +++ b/target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-10p.dts @@ -7,6 +7,42 @@ compatible = "d-link,dgs-1210-10p", "realtek,rtl838x-soc"; model = "D-Link DGS-1210-10P"; + /* i2c of the left SFP cage: port 9 */ + i2c0: i2c-gpio-0 { + compatible = "i2c-gpio"; + sda-gpios = <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio1 7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp0: sfp-p9 { + compatible = "sff,sfp"; + i2c-bus = <&i2c0>; + los-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&gpio1 8 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>; + }; + + /* i2c of the right SFP cage: port 10 */ + i2c1: i2c-gpio-1 { + compatible = "i2c-gpio"; + sda-gpios = <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio1 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <2>; + #address-cells = <1>; + #size-cells = <0>; + }; + + sfp1: sfp-p10 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1>; + los-gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>; + }; + keys { compatible = "gpio-keys-polled"; poll-interval = <20>; @@ -86,8 +122,24 @@ SWITCH_PORT(13, 6, internal) SWITCH_PORT(14, 7, internal) SWITCH_PORT(15, 8, internal) - SWITCH_SFP_PORT(24, 9, rgmii-id) - SWITCH_SFP_PORT(26, 10, rgmii-id) + + port@24 { + reg = <24>; + label = "lan9"; + phy-handle = <&phy24>; + phy-mode = "1000base-x"; + managed = "in-band-status"; + sfp = <&sfp0>; + }; + + port@26 { + reg = <26>; + label = "lan10"; + phy-handle = <&phy26>; + phy-mode = "1000base-x"; + managed = "in-band-status"; + sfp = <&sfp1>; + }; port@28 { ethernet = <ðernet0>; From 1b7e62b20b1735fcdc498a35e005afcd775abcf4 Mon Sep 17 00:00:00 2001 From: Chuanhong Guo Date: Tue, 23 Jan 2024 19:20:47 +0800 Subject: [PATCH 185/222] mediatek: drop NMBM layout for Xiaomi WR30U This reverts commit dcdcfc15115a1038e90f21f5aa41726d9c7e2fe5. This is a firmware for third-party u-boot mod, which should not be carried here by us. Signed-off-by: Chuanhong Guo --- .../uboot-envtools/files/mediatek_filogic | 1 - ...7981b-xiaomi-mi-router-wr30u-112m-nmbm.dts | 22 ------------------- .../filogic/base-files/etc/board.d/01_leds | 1 - .../filogic/base-files/etc/board.d/02_network | 2 -- target/linux/mediatek/image/filogic.mk | 17 -------------- 5 files changed, 43 deletions(-) delete mode 100644 target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-112m-nmbm.dts diff --git a/package/boot/uboot-envtools/files/mediatek_filogic b/package/boot/uboot-envtools/files/mediatek_filogic index cae761b4f9..4c483ca614 100644 --- a/package/boot/uboot-envtools/files/mediatek_filogic +++ b/package/boot/uboot-envtools/files/mediatek_filogic @@ -101,7 +101,6 @@ ubnt,unifi-6-plus) ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x80000" "0x10000" ;; xiaomi,mi-router-ax3000t|\ -xiaomi,mi-router-wr30u-112m-nmbm|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,redmi-router-ax6000-stock) ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x10000" "0x20000" diff --git a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-112m-nmbm.dts b/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-112m-nmbm.dts deleted file mode 100644 index 7244cdfd61..0000000000 --- a/target/linux/mediatek/dts/mt7981b-xiaomi-mi-router-wr30u-112m-nmbm.dts +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -/dts-v1/; -#include "mt7981b-xiaomi-mi-router-wr30u.dtsi" - -/ { - model = "Xiaomi Mi Router WR30U (112M UBI with NMBM-Enabled layout)"; - compatible = "xiaomi,mi-router-wr30u-112m-nmbm", "mediatek,mt7981"; -}; - -&spi_nand { - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; -}; - -&partitions { - partition@600000 { - label = "ubi"; - reg = <0x600000 0x7000000>; - }; -}; diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds index 51654ae87f..b9fac1bebf 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/01_leds @@ -33,7 +33,6 @@ routerich,ax3000) ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" "link tx rx" ucidef_set_led_netdev "wan-off" "wan-off" "red:wan" "wan" "link" ;; -xiaomi,mi-router-wr30u-112m-nmbm|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,mi-router-wr30u-ubootmod) ucidef_set_led_netdev "wan" "wan" "blue:wan" "wan" "link tx rx" diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network index 47e7be971e..a198fb98c9 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network @@ -76,7 +76,6 @@ mediatek_setup_interfaces() ;; xiaomi,mi-router-ax3000t|\ xiaomi,mi-router-ax3000t-ubootmod|\ - xiaomi,mi-router-wr30u-112m-nmbm|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,mi-router-wr30u-ubootmod|\ xiaomi,redmi-router-ax6000-stock|\ @@ -164,7 +163,6 @@ mediatek_setup_macs() ;; xiaomi,mi-router-ax3000t|\ xiaomi,mi-router-ax3000t-ubootmod|\ - xiaomi,mi-router-wr30u-112m-nmbm|\ xiaomi,mi-router-wr30u-stock|\ xiaomi,mi-router-wr30u-ubootmod|\ xiaomi,redmi-router-ax6000-stock|\ diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index 8a8879ca32..c64a46fe24 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -799,23 +799,6 @@ endif endef TARGET_DEVICES += xiaomi_mi-router-ax3000t-ubootmod -define Device/xiaomi_mi-router-wr30u-112m-nmbm - DEVICE_VENDOR := Xiaomi - DEVICE_MODEL := Mi Router WR30U (112M UBI with NMBM-Enabled layout) - DEVICE_DTS := mt7981b-xiaomi-mi-router-wr30u-112m-nmbm - DEVICE_DTS_DIR := ../dts - UBINIZE_OPTS := -E 5 - BLOCKSIZE := 128k - PAGESIZE := 2048 - DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware -ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) - ARTIFACTS := initramfs-factory.ubi - ARTIFACT/initramfs-factory.ubi := append-image-stage initramfs-kernel.bin | ubinize-kernel -endif - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata -endef -TARGET_DEVICES += xiaomi_mi-router-wr30u-112m-nmbm - define Device/xiaomi_mi-router-wr30u-stock DEVICE_VENDOR := Xiaomi DEVICE_MODEL := Mi Router WR30U (stock layout) From b34e6de7da33073c9a846963852d5597d1d58097 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Wed, 24 Jan 2024 13:08:36 +0100 Subject: [PATCH 186/222] ubox: update to Git HEAD (2024-01-24) 2c5887cb4688 kmodloader: fix invalid read outside mapped region Signed-off-by: Christian Marangi --- package/system/ubox/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/system/ubox/Makefile b/package/system/ubox/Makefile index 317055453f..e74ae00b3f 100644 --- a/package/system/ubox/Makefile +++ b/package/system/ubox/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/ubox.git -PKG_SOURCE_DATE:=2024-01-22 -PKG_SOURCE_VERSION:=6cf7d837ee7e392ee047aee4f45132f4176b7493 -PKG_MIRROR_HASH:=de63c19f095459dcd08c97f8391b8c735708453da8f31080935ce02c1b1f054a +PKG_SOURCE_DATE:=2024-01-24 +PKG_SOURCE_VERSION:=2c5887cb46883a28d69071c4349c3dabbbe3972c +PKG_MIRROR_HASH:=0ded95382fd3a2e9751ea5fdd16c2afb7dcc52499f6ab47951c5db9525a4faa9 CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 From d82930c7c776d974e717ec958ca0c1019fea3b8f Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Wed, 24 Jan 2024 13:09:40 +0100 Subject: [PATCH 187/222] libxml2: update to 2.12.4 Release Notes: - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.12.4 Signed-off-by: Nick Hainke --- package/libs/libxml2/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/libs/libxml2/Makefile b/package/libs/libxml2/Makefile index 9e70a0bd0a..030f7e45e8 100644 --- a/package/libs/libxml2/Makefile +++ b/package/libs/libxml2/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libxml2 -PKG_VERSION:=2.12.3 +PKG_VERSION:=2.12.4 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@GNOME/libxml2/$(basename $(PKG_VERSION)) -PKG_HASH:=8c8f1092340a89ff32bc44ad5c9693aff9bc8a7a3e161bb239666e5d15ac9aaa +PKG_HASH:=497360e423cf0bd99eacdb7c6215dea92e6d6e89ee940393c2bae0e77cb9b7d0 PKG_LICENSE:=MIT PKG_LICENSE_FILES:=COPYING From 3cf1fe5508ee8a2a2c6e33a829bfb6c81381ccd0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 24 Jan 2024 09:23:12 +0100 Subject: [PATCH 188/222] bmips: bcm6368-enetsw: Bump max MTU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The safe max frame size for this ethernet switch is 1532 bytes, excluding the DSA TAG and extra VLAN header, so the maximum outgoing frame is 1542 bytes. The available overhead is needed when using the DSA switch with a cascaded Marvell DSA switch, which is something that exist in real products, in this case the Inteno XG6846. Use defines at the top of the size for max MTU so it is clear how we think about this, add comments. We need to adjust the RX buffer size to fit the new max frame size, which is 1542 when the DSA tag (6 bytes) and VLAN header (4 extra bytes) is added. We also drop this default MTU: #define ENETSW_TAG_SIZE (6 + VLAN_HLEN) ndev->mtu = ETH_DATA_LEN + ENETSW_TAG_SIZE; in favor of just: ndev->mtu = ETH_DATA_LEN; I don't know why the default MTU is trying to second guess the overhead required by DSA and VLAN but the framework will also try to bump the MTU for e.g. DSA tags, and the VLAN overhead is not supposed to be included in the MTU, so this is clearly not right. Before this patch (on the lan1 DSA port in this case): dsa_slave_change_mtu: master->max_mtu = 9724, dev->max_mtu = 10218, DSA overhead = 8 dsa_slave_change_mtu: master = extsw, dev = lan1 dsa_slave_change_mtu: master->max_mtu = 1510, dev->max_mtu = 9724, DSA overhead = 6 dsa_slave_change_mtu: master = eth0, dev = extsw dsa_slave_change_mtu new_master_mtu 1514 > mtu_limit 1510 mdio_mux-0.1:00: nonfatal error -34 setting MTU to 1500 on port 0 My added debug prints before the nonfatal error: the first switch from the top is the Marvell switch, the second in the bcm6368-enetsw with its 1510 limit. After this patch the error is gone. OpenWrt adds a VLAN to each port so we get VLAN tags on all frames. On this setup we even have 4 more bytes left after the two DSA tags and VLAN so we can go all the way up to 1532 as MTU. Testing the new 1532 MTU: eth0 ext1 enp7s0 .--------. .-----------. cable .------. | enetsw | <-> | mv88e6152 | <-----> | host | `--------´ `-----------´ `------´ On the router we set the max MTU for test: ifconfig eth0 mtu 1520 ifconfig br-wan mtu 1520 ifconfig ext1 mtu 1506 An MTU of 1506 on ext1 is a logic consequence of the above setup: this is the max bytes actually transferred. The framing added will be: - 18 bytes standard ethernet header - 4 bytes VLAN header - 6 bytes DSA tag for enetsw - 8 bytes DSA tag for mv88e6152 Sum: 1506 + 18 + 4 + 6 + 8 = 1542 which is out max frame size. Test pinging from host: ping -s 1478 -M do 192.168.1.220 PING 192.168.1.220 (192.168.1.220) 1478(1506) bytes of data. 1486 bytes from 192.168.1.220: icmp_seq=1 ttl=64 time=0.696 ms 1486 bytes from 192.168.1.220: icmp_seq=2 ttl=64 time=0.615 ms Test pinging from router: PING 192.168.1.2 (192.168.1.2): 1478 data bytes 1486 bytes from 192.168.1.2: seq=0 ttl=64 time=0.931 ms 1486 bytes from 192.168.1.2: seq=1 ttl=64 time=0.810 ms The max IP packet without headers is 1478, the outgoing ICMP packet is 1506 bytes. Then the DSA, VLAN and ethernet overhead is added. Let us verify the contents of the resulting ethernet frame of 1542 bytes. Ping packet on router side as viewed with tcpdump: 00:54:51.900869 AF Unknown (1429722180), length 1538: 0x0000: 3d93 bcae c56b a83d 8874 0300 0004 8100 =....k.=.t...... 0x0010: 0000 dada 0000 c020 0fff 0800 4500 05e2 ............E... 0x0020: 0000 4000 4001 b0ec c0a8 0102 c0a8 01dc ..@.@........... 0x0030: 0800 7628 00c3 0001 f5da 1d65 0000 0000 ..v(.......e.... 0x0040: ce65 0a00 0000 0000 1011 1213 1415 1617 .e.............. 0x0050: 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 .........!"#$%&' 0x0060: 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 ()*+,-./0123456 (...) - 3d93 = First four bytes are the last two bytes of the destination ethernet address I don't know why the first four are missing, but it sure explains why the paket is 1538 bytes and not 1542 which is the actual max frame size. - bcae c56b a83b = source ethernet address - 8874 0300 0004 = Broadcom enetsw DSA tag - 8100 0000 = VLAN 802.1Q header - dada 0000 c020 0fff = EDSA tag for the Marvell (outer) switch, - 0800 is the ethertype (part of the EDSA tag technically) - Next follows the contents of the ping packet as it appears if we dump it on the DSA interface such as tcpdump -i lan1 etc, there we get the stripped out packet, 1506 bytes. - At the end 4 bytes of FCS. This clearly illustrates that the DSA tag is included in the MTU which we set up in Linux, but the VLAN tag and ethernet headers and checksum is not. Tested-by: Paul Donald Signed-off-by: Linus Walleij Signed-off-by: Álvaro Fernández Rojas --- .../net/ethernet/broadcom/bcm6368-enetsw.c | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/target/linux/bmips/files/drivers/net/ethernet/broadcom/bcm6368-enetsw.c b/target/linux/bmips/files/drivers/net/ethernet/broadcom/bcm6368-enetsw.c index 321e95dbbb..b72a788378 100644 --- a/target/linux/bmips/files/drivers/net/ethernet/broadcom/bcm6368-enetsw.c +++ b/target/linux/bmips/files/drivers/net/ethernet/broadcom/bcm6368-enetsw.c @@ -22,10 +22,19 @@ #include #include -/* MTU */ -#define ENETSW_TAG_SIZE (6 + VLAN_HLEN) -#define ENETSW_MTU_OVERHEAD (VLAN_ETH_HLEN + VLAN_HLEN + \ - ENETSW_TAG_SIZE) +/* TODO: Bigger frames may work but we do not trust that they are safe on all + * platforms so more research is needed, a max frame size of 2048 has been + * tested. We use the safe frame size 1542 which is 1532 plus DSA and VLAN + * overhead. + */ +#define ENETSW_MAX_FRAME 1542 +#define ENETSW_DSA_TAG_SIZE 6 +/* The MTU in Linux does not include ethernet or VLAN headers, but it DOES + * include the DSA overhead (the framework will increase the MTU to fit + * any DSA header). + */ +#define ENETSW_MAX_MTU (ENETSW_MAX_FRAME - VLAN_ETH_HLEN - \ + VLAN_HLEN) #define ENETSW_FRAG_SIZE(x) (SKB_DATA_ALIGN(NET_SKB_PAD + x + \ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))) @@ -1006,7 +1015,7 @@ static int bcm6368_enetsw_probe(struct platform_device *pdev) dev_info(dev, "random mac\n"); } - priv->rx_buf_size = ALIGN(ndev->mtu + ENETSW_MTU_OVERHEAD, + priv->rx_buf_size = ALIGN(ENETSW_MAX_FRAME, ENETSW_DMA_MAXBURST * 4); priv->rx_frag_size = ENETSW_FRAG_SIZE(priv->rx_buf_size); @@ -1066,8 +1075,8 @@ static int bcm6368_enetsw_probe(struct platform_device *pdev) /* register netdevice */ ndev->netdev_ops = &bcm6368_enetsw_ops; ndev->min_mtu = ETH_ZLEN; - ndev->mtu = ETH_DATA_LEN + ENETSW_TAG_SIZE; - ndev->max_mtu = ETH_DATA_LEN + ENETSW_TAG_SIZE; + ndev->mtu = ETH_DATA_LEN; + ndev->max_mtu = ENETSW_MAX_MTU; #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0) netif_napi_add(ndev, &priv->napi, bcm6368_enetsw_poll); #else From 6fbe36a618566fae2d12486c0aac2a81dc6c8c48 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Wed, 24 Jan 2024 13:18:53 +0100 Subject: [PATCH 189/222] tools/cpio: update to 2.15 Release Notes: https://lists.gnu.org/archive/html/info-gnu/2024-01/msg00006.html Signed-off-by: Nick Hainke --- tools/cpio/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/cpio/Makefile b/tools/cpio/Makefile index 1550785ddc..bd6e258980 100644 --- a/tools/cpio/Makefile +++ b/tools/cpio/Makefile @@ -3,11 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=cpio PKG_CPE_ID:=cpe:/a:gnu:cpio -PKG_VERSION:=2.14 +PKG_VERSION:=2.15 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=@GNU/cpio -PKG_HASH:=fcdc15d60f7267a6fc7efcd6b9db7b6c8966c4f2fbbb964c24d41336fd3f2c12 +PKG_HASH:=937610b97c329a1ec9268553fb780037bcfff0dcffe9725ebc4fd9c1aa9075db include $(INCLUDE_DIR)/host-build.mk From ae7a7ef5da250d59953f4365ce0ccf014dd89d14 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Wed, 24 Jan 2024 13:26:31 +0100 Subject: [PATCH 190/222] tools/mkimage: update to 2024.01 Update to latest version. Refresh patch: - 030-allow-to-use-different-magic.patch Signed-off-by: Nick Hainke --- tools/mkimage/Makefile | 4 ++-- tools/mkimage/patches/030-allow-to-use-different-magic.patch | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/mkimage/Makefile b/tools/mkimage/Makefile index 5dceb9a471..ae744f9bf3 100644 --- a/tools/mkimage/Makefile +++ b/tools/mkimage/Makefile @@ -7,14 +7,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mkimage -PKG_VERSION:=2023.10 +PKG_VERSION:=2024.01 PKG_SOURCE:=u-boot-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:= \ https://mirror.cyberbits.eu/u-boot \ https://ftp.denx.de/pub/u-boot \ ftp://ftp.denx.de/pub/u-boot -PKG_HASH:=e00e6c6f014e046101739d08d06f328811cebcf5ae101348f409cbbd55ce6900 +PKG_HASH:=b99611f1ed237bf3541bdc8434b68c96a6e05967061f992443cb30aabebef5b3 HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/u-boot-$(PKG_VERSION) diff --git a/tools/mkimage/patches/030-allow-to-use-different-magic.patch b/tools/mkimage/patches/030-allow-to-use-different-magic.patch index 3689fcb531..f2f57965f6 100644 --- a/tools/mkimage/patches/030-allow-to-use-different-magic.patch +++ b/tools/mkimage/patches/030-allow-to-use-different-magic.patch @@ -50,7 +50,7 @@ This patch makes it possible to set a custom image magic. break; --- a/tools/default_image.c +++ b/tools/default_image.c -@@ -68,7 +68,7 @@ static int image_verify_header(unsigned +@@ -67,7 +67,7 @@ static int image_verify_header(unsigned */ memcpy(hdr, ptr, sizeof(struct legacy_img_hdr)); @@ -59,7 +59,7 @@ This patch makes it possible to set a custom image magic. debug("%s: Bad Magic Number: \"%s\" is no valid image\n", params->cmdname, params->imagefile); return -FDT_ERR_BADMAGIC; -@@ -147,7 +147,7 @@ static void image_set_header(void *ptr, +@@ -146,7 +146,7 @@ static void image_set_header(void *ptr, } /* Build new header */ From 6f90118533cf25d816653cffda8a66976995d71d Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Wed, 24 Jan 2024 13:45:27 +0100 Subject: [PATCH 191/222] iproute2: update to 6.7.0 Release Notes: https://lwn.net/Articles/957171/ Remove patch "100-configure.patch" because support for ATM was dropped [0]. Manually refresh: - 200-drop_libbsd_dependency.patch Automatic refresh: - 130-no_netem_tipc_dcb_man_vdpa.patch - 140-keep_libmnl_optional.patch - 145-keep_libelf_optional.patch - 150-keep_libcap_optional.patch - 155-keep_tirpc_optional.patch - 190-fix-nls-rpath-link.patch - 300-selinux-configurable.patch [0] - https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/commit/?id=a66a73af6db74fdb64439316c69aa0e35dd02c47 Signed-off-by: Nick Hainke --- package/network/utils/iproute2/Makefile | 4 ++-- .../utils/iproute2/patches/100-configure.patch | 12 ------------ .../patches/130-no_netem_tipc_dcb_man_vdpa.patch | 2 +- .../iproute2/patches/140-keep_libmnl_optional.patch | 2 +- .../iproute2/patches/145-keep_libelf_optional.patch | 2 +- .../iproute2/patches/150-keep_libcap_optional.patch | 2 +- .../iproute2/patches/155-keep_tirpc_optional.patch | 2 +- .../iproute2/patches/190-fix-nls-rpath-link.patch | 4 ++-- .../patches/200-drop_libbsd_dependency.patch | 6 +++--- .../iproute2/patches/300-selinux-configurable.patch | 2 +- 10 files changed, 13 insertions(+), 25 deletions(-) delete mode 100644 package/network/utils/iproute2/patches/100-configure.patch diff --git a/package/network/utils/iproute2/Makefile b/package/network/utils/iproute2/Makefile index c21b78916b..2f9d2f2bc9 100644 --- a/package/network/utils/iproute2/Makefile +++ b/package/network/utils/iproute2/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iproute2 -PKG_VERSION:=6.6.0 +PKG_VERSION:=6.7.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2 -PKG_HASH:=8738c804afd09f0bf756937f0c3de23117832a98d8cbbf50386cf5005cd613ce +PKG_HASH:=ff942dd9828d7d1f867f61fe72ce433078c31e5d8e4a78e20f02cb5892e8841d PKG_BUILD_PARALLEL:=1 PKG_BUILD_DEPENDS:=iptables PKG_LICENSE:=GPL-2.0 diff --git a/package/network/utils/iproute2/patches/100-configure.patch b/package/network/utils/iproute2/patches/100-configure.patch deleted file mode 100644 index 2d4fb7b9b3..0000000000 --- a/package/network/utils/iproute2/patches/100-configure.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/configure -+++ b/configure -@@ -36,7 +36,8 @@ int main(int argc, char **argv) { - } - EOF - -- if $CC -I$INCLUDE -o $TMPDIR/atmtest $TMPDIR/atmtest.c -latm >/dev/null 2>&1; then -+# OpenWrt: disable ATM support even if present on host system -+ if [ 1 -eq 0 ]; then - echo "TC_CONFIG_ATM:=y" >>$CONFIG - echo yes - else diff --git a/package/network/utils/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch b/package/network/utils/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch index ba6ca4c9b2..8c70c14489 100644 --- a/package/network/utils/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch +++ b/package/network/utils/iproute2/patches/130-no_netem_tipc_dcb_man_vdpa.patch @@ -1,6 +1,6 @@ --- a/Makefile +++ b/Makefile -@@ -67,9 +67,9 @@ WFLAGS += -Wmissing-declarations -Wold-s +@@ -68,9 +68,9 @@ WFLAGS += -Wmissing-declarations -Wold-s CFLAGS := $(WFLAGS) $(CCOPTS) -I../include -I../include/uapi $(DEFINES) $(CFLAGS) YACCFLAGS = -d -t -v diff --git a/package/network/utils/iproute2/patches/140-keep_libmnl_optional.patch b/package/network/utils/iproute2/patches/140-keep_libmnl_optional.patch index a8cdd103ba..0d22875751 100644 --- a/package/network/utils/iproute2/patches/140-keep_libmnl_optional.patch +++ b/package/network/utils/iproute2/patches/140-keep_libmnl_optional.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -411,7 +411,7 @@ check_tirpc() +@@ -391,7 +391,7 @@ check_tirpc() check_mnl() { diff --git a/package/network/utils/iproute2/patches/145-keep_libelf_optional.patch b/package/network/utils/iproute2/patches/145-keep_libelf_optional.patch index 0c5c3f59ed..bffacddb21 100644 --- a/package/network/utils/iproute2/patches/145-keep_libelf_optional.patch +++ b/package/network/utils/iproute2/patches/145-keep_libelf_optional.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -266,7 +266,7 @@ EOF +@@ -246,7 +246,7 @@ EOF check_elf() { diff --git a/package/network/utils/iproute2/patches/150-keep_libcap_optional.patch b/package/network/utils/iproute2/patches/150-keep_libcap_optional.patch index 4cce2c3ca6..570e9c7038 100644 --- a/package/network/utils/iproute2/patches/150-keep_libcap_optional.patch +++ b/package/network/utils/iproute2/patches/150-keep_libcap_optional.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -469,7 +469,7 @@ EOF +@@ -449,7 +449,7 @@ EOF check_cap() { diff --git a/package/network/utils/iproute2/patches/155-keep_tirpc_optional.patch b/package/network/utils/iproute2/patches/155-keep_tirpc_optional.patch index 28ba7e5217..4d7fb76308 100644 --- a/package/network/utils/iproute2/patches/155-keep_tirpc_optional.patch +++ b/package/network/utils/iproute2/patches/155-keep_tirpc_optional.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -398,7 +398,7 @@ check_selinux() +@@ -378,7 +378,7 @@ check_selinux() check_tirpc() { diff --git a/package/network/utils/iproute2/patches/190-fix-nls-rpath-link.patch b/package/network/utils/iproute2/patches/190-fix-nls-rpath-link.patch index c7fceb2e22..765e4ad2e8 100644 --- a/package/network/utils/iproute2/patches/190-fix-nls-rpath-link.patch +++ b/package/network/utils/iproute2/patches/190-fix-nls-rpath-link.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -290,7 +290,7 @@ int main(int argc, char **argv) { +@@ -270,7 +270,7 @@ int main(int argc, char **argv) { } EOF @@ -9,7 +9,7 @@ local ret=$? rm -f $TMPDIR/libbpf_test.c $TMPDIR/libbpf_test -@@ -308,7 +308,7 @@ int main(int argc, char **argv) { +@@ -288,7 +288,7 @@ int main(int argc, char **argv) { } EOF diff --git a/package/network/utils/iproute2/patches/200-drop_libbsd_dependency.patch b/package/network/utils/iproute2/patches/200-drop_libbsd_dependency.patch index d1948860e8..92bf5cb66d 100644 --- a/package/network/utils/iproute2/patches/200-drop_libbsd_dependency.patch +++ b/package/network/utils/iproute2/patches/200-drop_libbsd_dependency.patch @@ -1,12 +1,12 @@ --- a/configure +++ b/configure -@@ -455,14 +455,8 @@ EOF +@@ -435,14 +435,8 @@ EOF if $CC -I$INCLUDE -o $TMPDIR/strtest $TMPDIR/strtest.c >/dev/null 2>&1; then echo "no" else - if ${PKG_CONFIG} libbsd --exists; then -- echo 'CFLAGS += -DHAVE_LIBBSD' `${PKG_CONFIG} libbsd --cflags` >>$CONFIG -- echo 'LDLIBS +=' `${PKG_CONFIG} libbsd --libs` >> $CONFIG +- echo 'CFLAGS += -DHAVE_LIBBSD' "$(${PKG_CONFIG} libbsd --cflags)" >>$CONFIG +- echo 'LDLIBS +=' "$(${PKG_CONFIG} libbsd --libs)" >> $CONFIG - echo "no" - else - echo 'CFLAGS += -DNEED_STRLCPY' >>$CONFIG diff --git a/package/network/utils/iproute2/patches/300-selinux-configurable.patch b/package/network/utils/iproute2/patches/300-selinux-configurable.patch index 817abf7d17..a611ba75f0 100644 --- a/package/network/utils/iproute2/patches/300-selinux-configurable.patch +++ b/package/network/utils/iproute2/patches/300-selinux-configurable.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -385,7 +385,7 @@ check_libbpf() +@@ -365,7 +365,7 @@ check_libbpf() check_selinux() # SELinux is a compile time option in the ss utility { From 409052eadefaad018944819d67f343b5e1c259bf Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Thu, 25 Jan 2024 16:17:27 +0100 Subject: [PATCH 192/222] libtraceevent: update to 1.8.2 Changelog: 6f6d580 libtraceevent: 1.8.2 b29b192 kbuffer: Update kbuf->next in kbuffer_refresh 4b2286c kbuffer: Always walk the events to calculate timestamp in kbuffer_read_buffer() ce0acec libtraceevent meson: Add libdl dependency to meson 15a0121 libtraceevent Documentation: Fix tep_kbuffer() prototype 85a2078 libtraceevent: 1.8.1 6b21b4c libtraceevent: Add tep_get_sub_buffer_data_size() 8cf5315 libtraceevent: 1.8 7a4d5b2 kbuffer: Add kbuffer_refresh() API 33bad32 kbuffer: Add kbuffer_subbuffer() API f6bdff7 kbuffer: Add kbuffer_dup() 0582118 kbuffer: Add kbuffer_read_buffer() 014ca24 libtraceevent: Fix tep_kbuffer() to have kbuf assign long_size afead9a libtraceevent: Add tep_get_sub_buffer_commit_offset() 3152506 libtraceevent plugins: Parse sched_switch "prev_state" field for state info 4be92aa libtraceevent: Bump meson version to >=0.58.0 9b2e543 libtraceevent: sync state char array with the kernel 5b89385 libtraceevent: Add option to disable documentation a496a39 libtraceevent: Add tep_record_is_event() API Signed-off-by: Nick Hainke --- package/libs/libtraceevent/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/libs/libtraceevent/Makefile b/package/libs/libtraceevent/Makefile index bcba7eaf43..54e8652192 100644 --- a/package/libs/libtraceevent/Makefile +++ b/package/libs/libtraceevent/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libtraceevent -PKG_VERSION:=1.7.3 +PKG_VERSION:=1.8.2 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/snapshot/ -PKG_HASH:=097b72e0d907f3107825fb2edf0188324bf70dc9da360f6efa68dc484ffde541 +PKG_HASH:=919f0c024c7b5059eace52d854d4df00ae7e361a4033e1b4d6fe01d97064a1b9 PKG_MAINTAINER:=Nick Hainke From aa06f68c5202f6a4c55197fb78ed9cd24fc78bed Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Thu, 25 Jan 2024 16:23:07 +0100 Subject: [PATCH 193/222] libtracefs: update to 1.8 Changes: 67f3b2a libtracefs: version 1.8 8a1322f libtracefs utest: Add tests to use mapping if supported 0a65b79 libtracefs: Add tracefs_mapped_is_supported() API 805f650 libtracefs: Call mmap ioctl if a refresh happens cf7e2a5 libtracefs: Fix tracefs_mmap() kbuf usage 3a26b26 libtracefs: Have nonblock tracefs_cpu reads set errno EAGAIN 2b5bb09 libtracefs: Have tracefs_mmap_read() include subbuf meta data dee0448 libtracefs: Have mapping work with the other tracefs_cpu* functions 28eebc1 libtracefs: Have tracefs_cpu_flush(_buf)() use mapping 065d914 libtracefs: Use mmapping for iterating raw events 1124e0e libtracefs: Use tracefs_cpu_*_buf() calls for iterator f43b293 libtracefs: Unmap mmap mapping on tracefs_cpu close 0d24516 libtracefs Documentation: Fix tracefs_cpu_snapshot_open() man pages 5ff31c0 libtracefs Documentation: Add tracefs_follow_events_clear() to main man page 0c7d9f7 libtracefs: Add man pages for tracefs_snapshot_*() functions b2dc3e0 libtracefs sql: Rename TIMESTAMP_USECS_DELTA to TIMESTAMP_DELTA_USECS 585ec77 libtracefs: Force off trace mmapping 2ed14b5 libtracefs: Add ring buffer memory mapping APIs 173ffc0 libtracefs meson: Add option to disable samples a55e2e8 libtracefs meson: Add option to disable documentation 93e20af libtracefs: Fix tracefs_instance_reset to clear synthetic events a1ecbff libtracefs utest: Add more tests to test tracefs_sql() 975c37c libtracefs utest: Add matches to trace_sql() tests 0567e2d libtracefs synthetic: Handle hashed name variables fcb3a83 libtracefs synthetic: Remove multiple adding of action in tracefs_synth_save() a9dae65 libtracefs: Fix sqlhist used uninitialized error fe7a467 libtracefs: Add updating and reading snapshot buffers 1ad57ab libtracefs: Add PID filtering API d8726bf libtracefs: Also clear max_graph_depth on reset eb4dd60 libtracefs: Add TIMESTAMP_USECS_DELTA to simplify SQL timestamp compares 8c57eb4 libtracefs: Add tracefs_instance_set/get_subbuf_size() 9bafb21 libtracefs: Add API to extract ring buffer statistics 141d25e libtracefs: Add tracefs_load_headers() API ef3fae7 libtracefs: Add kerneldoc comments to tracefs_instance_set_buffer_size() 31acfe1 libtracefs utest: Add test to test tracefs_instance_set/get_buffer_percent() 3e6d975 libtracefs: Add tracefs_instance_clear() API c4efaaf libtracefs: Add tracefs_instance_get/set_buffer_percent() 1e1cc54 libtracefs: Add API to read tracefs_cpu and return a kbuffer 7d395b1 libtracefs: Add tracefs_instance_file_write_number() e34cbd8 libtracefs: Increase splice to use pipe max size 1f50965 libtracefs: Add API to remove followers from an instance or toplevel 576ee0b libtracefs: Reset tracing before and after unit tests 118b694 libtracefs: Free dynamic event list in utest 5159973 libtracefs: Free tracing_dir in case of remount df563eb libtracefs: Free buf in clear_func_filter() 3cbac37 libtracefs: Free "missed_followers" of instance 0cbe56e libtracefs testing: Use one tep handle for most tests adac30f libtracefs Documentation: Fix tracefs_event_file_exists() issues 07ab199 libtracefs: Pass enum value where expected instead of int bb299b4 libtracefs: fix cscope makefile rule 420d677 libtracefs: Free "followers" when freeing instance 3f436fc libtracefs: Fix documentation of tracefs_trace_pipe_stream() flags 1fde9df libtracefs: Add explicit pthread dependency to meson d1989ae tracefs-perf: Add missing headers for syscall() and SYS_* defines Signed-off-by: Nick Hainke --- package/libs/libtracefs/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/libs/libtracefs/Makefile b/package/libs/libtracefs/Makefile index eb879ee66d..0496f5983e 100644 --- a/package/libs/libtracefs/Makefile +++ b/package/libs/libtracefs/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libtracefs -PKG_VERSION:=1.7.0 +PKG_VERSION:=1.8.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/snapshot/ -PKG_HASH:=411fcbf3434ecbaefa6c2b1bf092266293a672e2d7ee46fdd6b402753cb8bd16 +PKG_HASH:=f92475d5c4cb509983697fb359ee615bef4f08ed8bdc9c690f6118ba68886de0 PKG_MAINTAINER:=Nick Hainke From 195cf4b58d2722a6cf3fd47538e51bd717db8dd7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 25 Jan 2024 15:04:31 +0100 Subject: [PATCH 194/222] hostapd: remove obsolete function Leftover from authsae, which was removed a long time ago Signed-off-by: Felix Fietkau --- package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh | 2 +- package/network/services/hostapd/files/hostapd.sh | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index 6572999fbc..ed52822568 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -1038,7 +1038,7 @@ mac80211_set_noscan() { } drv_mac80211_cleanup() { - hostapd_common_cleanup + : } mac80211_reset_config() { diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index 271c1f7bec..c3fbf1e0b2 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -1592,7 +1592,3 @@ EOF fi return 0 } - -hostapd_common_cleanup() { - killall meshd-nl80211 -} From cdc4c551755115e0e1047a0c90a658e6238e96ee Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Manzano Date: Mon, 22 Jan 2024 13:46:14 +0100 Subject: [PATCH 195/222] hostapd: fix 11r defaults when using WPA 802.11r can not be used when selecting WPA. It needs at least WPA2. This is because 802.11r advertises FT support in-part through the Authentication and Key Management (AKM) suites in the Robust Security Network (RSN) Information Element, which was included in the 802.11i amendment and WPA2 certification program. Pre-standard WPA did not include the RSN IE, but the WPA IE. This IE can not advertise the AKM suite for FT. Signed-off-by: Jesus Fernandez Manzano --- .../network/services/hostapd/files/hostapd.sh | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index c3fbf1e0b2..058d0f404b 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -43,7 +43,7 @@ hostapd_append_wpa_key_mgmt() { case "$auth_type" in psk|eap) append wpa_key_mgmt "WPA-$auth_type_l" - [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-${auth_type_l}" + [ "${wpa:-2}" -ge 2 ] && [ "${ieee80211r:-0}" -gt 0 ] && append wpa_key_mgmt "FT-${auth_type_l}" [ "${ieee80211w:-0}" -gt 0 ] && append wpa_key_mgmt "WPA-${auth_type_l}-SHA256" ;; eap192) @@ -897,10 +897,21 @@ hostapd_set_bss_options() { } fi + json_get_vars ieee80211r + set_default ieee80211r 0 if [ "$wpa" -ge "1" ]; then - json_get_vars ieee80211r - set_default ieee80211r 0 + if [ "$fils" -gt 0 ]; then + json_get_vars fils_realm + set_default fils_realm "$(echo "$ssid" | md5sum | head -c 8)" + fi + append bss_conf "wpa_disable_eapol_key_retries=$wpa_disable_eapol_key_retries" "$N" + + hostapd_append_wpa_key_mgmt + [ -n "$wpa_key_mgmt" ] && append bss_conf "wpa_key_mgmt=$wpa_key_mgmt" "$N" + fi + + if [ "$wpa" -ge "2" ]; then if [ "$ieee80211r" -gt "0" ]; then json_get_vars mobility_domain ft_psk_generate_local ft_over_ds reassociation_deadline @@ -950,18 +961,7 @@ hostapd_set_bss_options() { done fi fi - if [ "$fils" -gt 0 ]; then - json_get_vars fils_realm - set_default fils_realm "$(echo "$ssid" | md5sum | head -c 8)" - fi - append bss_conf "wpa_disable_eapol_key_retries=$wpa_disable_eapol_key_retries" "$N" - - hostapd_append_wpa_key_mgmt - [ -n "$wpa_key_mgmt" ] && append bss_conf "wpa_key_mgmt=$wpa_key_mgmt" "$N" - fi - - if [ "$wpa" -ge "2" ]; then if [ -n "$network_bridge" -a "$rsn_preauth" = 1 ]; then set_default auth_cache 1 append bss_conf "rsn_preauth=1" "$N" From e2f6bfb833a1ba099e1dcf0e569e4ef11c31c391 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Manzano Date: Mon, 22 Jan 2024 13:52:18 +0100 Subject: [PATCH 196/222] hostapd: fix 11r defaults when using SAE When using WPA3-SAE or WPA2/WPA3 Personal Mixed, we can not use ft_psk_generate_local because it will break FT for SAE. Instead use the r0kh and r1kh configuration approach. Signed-off-by: Jesus Fernandez Manzano --- package/network/services/hostapd/files/hostapd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index 058d0f404b..ca95fcf70f 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -920,7 +920,7 @@ hostapd_set_bss_options() { set_default reassociation_deadline 1000 case "$auth_type" in - psk|sae|psk-sae) + psk) set_default ft_psk_generate_local 1 ;; *) From 59f67b2010d30049c71e578b93043fb457eecee5 Mon Sep 17 00:00:00 2001 From: Rany Hany Date: Fri, 5 Jan 2024 19:01:40 +0200 Subject: [PATCH 197/222] hostapd: fail R0KH and R1KH derivation when wpa_psk_file is used When wpa_psk_file is used, there is a chance that no PSK is set. This means that the FT key will be generated using only the mobility domain which could be considered a security vulnerability but only for a very specific and niche config. Signed-off-by: Rany Hany --- package/network/services/hostapd/files/hostapd.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh index ca95fcf70f..1a664abbf2 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -943,6 +943,10 @@ hostapd_set_bss_options() { set_default pmk_r1_push 0 [ -n "$r0kh" -a -n "$r1kh" ] || { + if [ -z "$auth_secret" -a -z "$key" ]; then + wireless_setup_vif_failed FT_KEY_CANT_BE_DERIVED + return 1 + fi ft_key=`echo -n "$mobility_domain/${auth_secret:-${key}}" | md5sum | awk '{print $1}'` set_default r0kh "ff:ff:ff:ff:ff:ff,*,$ft_key" From 53f338be43e050a49087ae87a8c410bcb4b34782 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Thu, 25 Jan 2024 21:42:49 +0100 Subject: [PATCH 198/222] generic: 6.1: add pending patch for ipq4019 MDIO MDC rate fix Add pending patch for ipq4019 MDIO MDC rate fix. The divisor was never actually set resulting in the MDC rate running at a very low speed. The same MDIO is used on ipq807x where Aquantia PHY are commonly used where MDIO is used to load the PHY firmware. Running at higher speed is required to make the firmware load faster as it does reduce load time from 60+ second to 5-6 seconds. Add as pending as upstream there seems to be some conflicts with quic and me and it might take lots of time before this is effectively merged upstream. Signed-off-by: Christian Marangi --- ...ipq4019-mdio-document-now-supported-.patch | 42 ++++ ...-add-support-for-clock-frequency-pro.patch | 204 ++++++++++++++++++ ...pq8074-add-clock-frequency-to-MDIO-n.patch | 25 +++ 3 files changed, 271 insertions(+) create mode 100644 target/linux/generic/pending-6.1/713-01-dt-bindings-net-ipq4019-mdio-document-now-supported-.patch create mode 100644 target/linux/generic/pending-6.1/713-02-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch create mode 100644 target/linux/generic/pending-6.1/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch diff --git a/target/linux/generic/pending-6.1/713-01-dt-bindings-net-ipq4019-mdio-document-now-supported-.patch b/target/linux/generic/pending-6.1/713-01-dt-bindings-net-ipq4019-mdio-document-now-supported-.patch new file mode 100644 index 0000000000..35258d8541 --- /dev/null +++ b/target/linux/generic/pending-6.1/713-01-dt-bindings-net-ipq4019-mdio-document-now-supported-.patch @@ -0,0 +1,42 @@ +From 85e2038891989e41bc62f6a4625fd5865da8a1a2 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 24 Jan 2024 19:17:02 +0100 +Subject: [PATCH 1/3] dt-bindings: net: ipq4019-mdio: document now supported + clock-frequency + +Document support for clock-frequency and add details on why this +property is needed and what values are supported. + +From internal documentation, while other values are supported, the +correct function of the MDIO bus is not assured hence add only the +suggested supported values to the property enum. + +Signed-off-by: Christian Marangi +--- + .../bindings/net/qcom,ipq4019-mdio.yaml | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/Documentation/devicetree/bindings/net/qcom,ipq4019-mdio.yaml ++++ b/Documentation/devicetree/bindings/net/qcom,ipq4019-mdio.yaml +@@ -38,6 +38,21 @@ properties: + MDIO clock source frequency fixed to 100MHZ, this clock should be specified + by the platform IPQ807x, IPQ60xx and IPQ50xx. + ++ clock-frequency: ++ description: ++ The MDIO bus clock that must be output by the MDIO bus hardware, if ++ absent, the default hardware values are used. ++ ++ MDC rate is feed by an external clock (fixed 100MHz) and is divider ++ internally. The default divider is /256 resulting in the default rate ++ applied of 390KHz. ++ ++ To follow 802.3 standard that instruct up to 2.5MHz by default, if ++ this property is not declared and the divider is set to /256, by ++ default 1.5625Mhz is select. ++ enum: [ 390625, 781250, 1562500, 3125000, 6250000, 12500000 ] ++ default: 1562500 ++ + required: + - compatible + - reg diff --git a/target/linux/generic/pending-6.1/713-02-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch b/target/linux/generic/pending-6.1/713-02-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch new file mode 100644 index 0000000000..809d7a0441 --- /dev/null +++ b/target/linux/generic/pending-6.1/713-02-net-mdio-ipq4019-add-support-for-clock-frequency-pro.patch @@ -0,0 +1,204 @@ +From eacf1d2505dfecd3599d558cdade1a2da47fe06d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 24 Jan 2024 18:52:33 +0100 +Subject: [PATCH 2/3] net: mdio: ipq4019: add support for clock-frequency + property + +The IPQ4019 MDIO internally divide the clock feed by AHB based on the +MDIO_MODE reg. On reset or power up, the default value for the +divider is 0xff that reflect the divider set to /256. + +This makes the MDC run at a very low rate, that is, considering AHB is +always fixed to 100Mhz, a value of 390KHz. + +This hasn't have been a problem as MDIO wasn't used for time sensitive +operation, it is now that on IPQ807x is usually mounted with PHY that +requires MDIO to load their firmware (example Aquantia PHY). + +To handle this problem and permit to set the correct designed MDC +frequency for the SoC add support for the standard "clock-frequency" +property for the MDIO node. + +The divider supports value from /1 to /256 and the common value are to +set it to /16 to reflect 6.25Mhz or to /8 on newer platform to reflect +12.5Mhz. + +To scan if the requested rate is supported by the divider, loop with +each supported divider and stop when the requested rate match the final +rate with the current divider. An error is returned if the rate doesn't +match any value. + +On MDIO reset, the divider is restored to the requested value to prevent +any kind of downclocking caused by the divider reverting to a default +value. + +To follow 802.3 spec of 2.5MHz of default value, if divider is set at +/256 and "clock-frequency" is not set in DT, assume nobody set the +divider and try to find the closest MDC rate to 2.5MHz. (in the case of +AHB set to 100MHz, it's 1.5625MHz) + +While at is also document other bits of the MDIO_MODE reg to have a +clear idea of what is actually applied there. + +Documentation of some BITs is skipped as they are marked as reserved and +their usage is not clear (RES 11:9 GENPHY 16:13 RES1 19:17) + +Signed-off-by: Christian Marangi +--- + drivers/net/mdio/mdio-ipq4019.c | 109 ++++++++++++++++++++++++++++++-- + 1 file changed, 103 insertions(+), 6 deletions(-) + +--- a/drivers/net/mdio/mdio-ipq4019.c ++++ b/drivers/net/mdio/mdio-ipq4019.c +@@ -14,6 +14,20 @@ + #include + + #define MDIO_MODE_REG 0x40 ++#define MDIO_MODE_MDC_MODE BIT(12) ++/* 0 = Clause 22, 1 = Clause 45 */ ++#define MDIO_MODE_C45 BIT(8) ++#define MDIO_MODE_DIV_MASK GENMASK(7, 0) ++#define MDIO_MODE_DIV(x) FIELD_PREP(MDIO_MODE_DIV_MASK, (x) - 1) ++#define MDIO_MODE_DIV_1 0x0 ++#define MDIO_MODE_DIV_2 0x1 ++#define MDIO_MODE_DIV_4 0x3 ++#define MDIO_MODE_DIV_8 0x7 ++#define MDIO_MODE_DIV_16 0xf ++#define MDIO_MODE_DIV_32 0x1f ++#define MDIO_MODE_DIV_64 0x3f ++#define MDIO_MODE_DIV_128 0x7f ++#define MDIO_MODE_DIV_256 0xff + #define MDIO_ADDR_REG 0x44 + #define MDIO_DATA_WRITE_REG 0x48 + #define MDIO_DATA_READ_REG 0x4c +@@ -26,9 +40,6 @@ + #define MDIO_CMD_ACCESS_CODE_C45_WRITE 1 + #define MDIO_CMD_ACCESS_CODE_C45_READ 2 + +-/* 0 = Clause 22, 1 = Clause 45 */ +-#define MDIO_MODE_C45 BIT(8) +- + #define IPQ4019_MDIO_TIMEOUT 10000 + #define IPQ4019_MDIO_SLEEP 10 + +@@ -41,6 +52,7 @@ struct ipq4019_mdio_data { + void __iomem *membase; + void __iomem *eth_ldo_rdy; + struct clk *mdio_clk; ++ unsigned int mdc_rate; + }; + + static int ipq4019_mdio_wait_busy(struct mii_bus *bus) +@@ -179,6 +191,38 @@ static int ipq4019_mdio_write(struct mii + return 0; + } + ++static int ipq4019_mdio_set_div(struct ipq4019_mdio_data *priv) ++{ ++ unsigned long ahb_rate; ++ int div; ++ u32 val; ++ ++ /* If we don't have a clock for AHB use the fixed value */ ++ ahb_rate = IPQ_MDIO_CLK_RATE; ++ if (priv->mdio_clk) ++ ahb_rate = clk_get_rate(priv->mdio_clk); ++ ++ /* MDC rate is ahb_rate/(MDIO_MODE_DIV + 1) ++ * While supported, internal documentation doesn't ++ * assure correct functionality of the MDIO bus ++ * with divider of 1, 2 or 4. ++ */ ++ for (div = 8; div <= 256; div *= 2) { ++ /* The requested rate is supported by the div */ ++ if (priv->mdc_rate == DIV_ROUND_UP(ahb_rate, div)) { ++ val = readl(priv->membase + MDIO_MODE_REG); ++ val &= ~MDIO_MODE_DIV_MASK; ++ val |= MDIO_MODE_DIV(div); ++ writel(val, priv->membase + MDIO_MODE_REG); ++ ++ return 0; ++ } ++ } ++ ++ /* The requested rate is not supported */ ++ return -EINVAL; ++} ++ + static int ipq_mdio_reset(struct mii_bus *bus) + { + struct ipq4019_mdio_data *priv = bus->priv; +@@ -201,10 +245,58 @@ static int ipq_mdio_reset(struct mii_bus + return ret; + + ret = clk_prepare_enable(priv->mdio_clk); +- if (ret == 0) +- mdelay(10); ++ if (ret) ++ return ret; ++ ++ mdelay(10); + +- return ret; ++ /* Restore MDC rate */ ++ return ipq4019_mdio_set_div(priv); ++} ++ ++static void ipq4019_mdio_select_mdc_rate(struct platform_device *pdev, ++ struct ipq4019_mdio_data *priv) ++{ ++ unsigned long ahb_rate; ++ int div; ++ u32 val; ++ ++ /* MDC rate defined in DT, we don't have to decide a default value */ ++ if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency", ++ &priv->mdc_rate)) ++ return; ++ ++ /* If we don't have a clock for AHB use the fixed value */ ++ ahb_rate = IPQ_MDIO_CLK_RATE; ++ if (priv->mdio_clk) ++ ahb_rate = clk_get_rate(priv->mdio_clk); ++ ++ /* Check what is the current div set */ ++ val = readl(priv->membase + MDIO_MODE_REG); ++ div = FIELD_GET(MDIO_MODE_DIV_MASK, val); ++ ++ /* div is not set to the default value of /256 ++ * Probably someone changed that (bootloader, other drivers) ++ * Keep this and doesn't overwrite it. ++ */ ++ if (div != MDIO_MODE_DIV_256) { ++ priv->mdc_rate = DIV_ROUND_UP(ahb_rate, div + 1); ++ return; ++ } ++ ++ /* If div is /256 assume nobody have set this value and ++ * try to find one MDC rate that is close the 802.3 spec of ++ * 2.5MHz ++ */ ++ for (div = 256; div >= 8; div /= 2) { ++ /* Stop as soon as we found a divider that ++ * reached the closest value to 2.5MHz ++ */ ++ if (DIV_ROUND_UP(ahb_rate, div) > 2500000) ++ break; ++ ++ priv->mdc_rate = DIV_ROUND_UP(ahb_rate, div); ++ } + } + + static int ipq4019_mdio_probe(struct platform_device *pdev) +@@ -228,6 +320,11 @@ static int ipq4019_mdio_probe(struct pla + if (IS_ERR(priv->mdio_clk)) + return PTR_ERR(priv->mdio_clk); + ++ ipq4019_mdio_select_mdc_rate(pdev, priv); ++ ret = ipq4019_mdio_set_div(priv); ++ if (ret) ++ return ret; ++ + /* The platform resource is provided on the chipset IPQ5018 */ + /* This resource is optional */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); diff --git a/target/linux/generic/pending-6.1/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch b/target/linux/generic/pending-6.1/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch new file mode 100644 index 0000000000..55f116ec5f --- /dev/null +++ b/target/linux/generic/pending-6.1/713-03-arm64-dts-qcom-ipq8074-add-clock-frequency-to-MDIO-n.patch @@ -0,0 +1,25 @@ +From 3b5a603bf66236b956287909556fd7ad4904450c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 24 Jan 2024 19:38:01 +0100 +Subject: [PATCH 3/3] arm64: dts: qcom: ipq8074: add clock-frequency to MDIO + node + +Add clock-frequency to MDIO node to set the MDC rate to 6.25Mhz instead +of using the default value of 390KHz from MDIO default divider. + +Signed-off-by: Christian Marangi +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -263,6 +263,8 @@ + clocks = <&gcc GCC_MDIO_AHB_CLK>; + clock-names = "gcc_mdio_ahb_clk"; + ++ clock-frequency = <6250000>; ++ + status = "disabled"; + }; + From 7ed1cca8d6ddc4c74694ca6323ee340895becba0 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Thu, 25 Jan 2024 22:20:27 +0100 Subject: [PATCH 199/222] ipq807x: add support for loading Aquantia FW from NVMEM for NBG7815 Add support for loading Aquantia FW from NVMEM for Zyxel NBG7815 restoring correct functionality of the 10g port. Signed-off-by: Christian Marangi --- .../arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts index 5fb8f3b4de..1e8e50875f 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8074-nbg7815.dts @@ -234,6 +234,15 @@ label = "0:ethphyfw"; reg = <0x650000 0x80000>; read-only; + + nvmem-layout { + compatible = "fixed-layout"; + + aqr_fw: aqr-fw@0 { + /* Skip the QCOM MBN Header of 40 bytes */ + reg = <0x28 0x5f402>; + }; + }; }; partition@6d0000 { @@ -292,6 +301,9 @@ compatible = "ethernet-phy-ieee802.3-c45"; reg = <8>; reset-gpios = <&tlmm 63 GPIO_ACTIVE_LOW>; + + nvmem-cells = <&aqr_fw>; + nvmem-cell-names = "firmware"; }; }; From 9f4708f76cb0d1392323d6a700b786f73f765fa2 Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Thu, 4 Jan 2024 01:22:26 +0100 Subject: [PATCH 200/222] ath79: ubnt-bullet-m-xw: set PHY max-speed to 100Mbps Onboard AR8035 PHY supports 1000Base-T operation, but onboard Ethernet magnetics do not. Reduce advertised link speeds to 100Mbps and lower. Signed-off-by: Lech Perczak --- target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts index 8c7d1dc918..16d27dc016 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts @@ -13,6 +13,7 @@ phy4: ethernet-phy@4 { phy-mode = "rgmii"; reg = <4>; + max-speed = <100>; }; }; From e405b96fe774fbad9c4c465f41ad853a970439bf Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Mon, 22 Jan 2024 00:14:16 +0100 Subject: [PATCH 201/222] ath79: ubnt-bullet-m-xw: fix Ethernet PHY traffic Since commit 6f2e1b7485f0 ("ath79: disable delays on AT803X config init") Ubiquiti XW boards equipped with AR8035 PHY suffered from lack of outbound traffic on the Ethernet port. This was caused by the fact, the U-boot has set this during boot and it wasn't reset by the PHY driver, and the corresponding setting in device tree was wrong. Set the 'phy-mode = "rgmii-txid"' at the ð0, and drop this property from PHY node, as it is not parsed there. This causes the device to connect using Ethernet once again. Fixes: db4b6535f837 ("ath79: Add support for Ubiquity Bullet M (XW)") Fixes: 6f2e1b7485f0 ("ath79: disable delays on AT803X config init") Signed-off-by: Lech Perczak --- target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts b/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts index 16d27dc016..ee73428625 100644 --- a/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts +++ b/target/linux/ath79/dts/ar9342_ubnt_bullet-m-xw.dts @@ -11,7 +11,6 @@ status = "okay"; phy4: ethernet-phy@4 { - phy-mode = "rgmii"; reg = <4>; max-speed = <100>; }; @@ -20,7 +19,7 @@ ð0 { status = "okay"; - phy-mode = "rgmii"; + phy-mode = "rgmii-txid"; phy-handle = <&phy4>; gmac-config { From 65f599223d6d24fa68059066c6fa85b862841632 Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Mon, 22 Jan 2024 00:34:34 +0100 Subject: [PATCH 202/222] ath79: add Ubiquiti Rocket M XW as alternate name to Bullet M XW Ubiquiti Rocket M XW is a single-band, 2x2:2 external Wi-Fi AP, with optional GPS receiver, with two external RP-SMA antenna connections, based on AR9342 SoC. Two band variants exists, for 2.4GHz and 5GHz band, usable with the same image. Specs: - CPU: Atheros AR9342 MIPS SoC at 535MHz - RAM: 64MB DDR400 - ROM: 8MB SPI-NOR in SO16W package, MX25L6408E - Wi-Fi Atheros AR9342 built-in 2x2:2 radio - Ethernet: Atheros AR8035 PHY, limited to 100Mbps speeds due to magnetics - Power: 24V passive PoE input. Installation: please refer to Ubiquiti Bullet M2HP for documentation. The device runs with exactly same image as the Bullet, and after fixes in preceding commit, is fully functional again. Add the alternative name to the build system. Signed-off-by: Lech Perczak --- target/linux/ath79/image/generic-ubnt.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/linux/ath79/image/generic-ubnt.mk b/target/linux/ath79/image/generic-ubnt.mk index 179de961be..a4d118456f 100644 --- a/target/linux/ath79/image/generic-ubnt.mk +++ b/target/linux/ath79/image/generic-ubnt.mk @@ -28,6 +28,9 @@ TARGET_DEVICES += ubnt_bullet-ac define Device/ubnt_bullet-m-xw $(Device/ubnt-xw) DEVICE_MODEL := Bullet M + DEVICE_ALT0_VENDOR := Ubiquiti + DEVICE_ALT0_MODEL := Rocket M + DEVICE_ALT0_VARIANT := XW DEVICE_PACKAGES += rssileds SUPPORTED_DEVICES += bullet-m-xw endef From 2e715fb4fc8014eefddf5d9232105740f10e06ba Mon Sep 17 00:00:00 2001 From: Marty Jones Date: Thu, 18 Jan 2024 16:23:52 -0500 Subject: [PATCH 203/222] bcm27xx: update 6.1 patches to latest version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for BCM2712 (Raspberry Pi 5). https://github.com/raspberrypi/linux/commit/3bb5880ab3dd31f75c07c3c33bf29c5d469b28f3 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 [Remove applied and reverted patches, squash patches and config commits] Signed-off-by: Álvaro Fernández Rojas --- target/linux/bcm27xx/bcm2708/config-6.1 | 7 +- target/linux/bcm27xx/bcm2709/config-6.1 | 7 +- target/linux/bcm27xx/bcm2710/config-6.1 | 10 +- target/linux/bcm27xx/bcm2711/config-6.1 | 10 +- ...ci_sync-Add-fallback-bd-address-prop.patch | 41 - ...-fix-binning-and-rate_factor-for-480.patch | 306 + ...7xx-Read-modem-line-state-at-startup.patch | 28 + ...m2835_unicam-Improve-frame-sequence-.patch | 79 + ...itft-28-35-overlays-for-6.1-driver-c.patch | 41 + ...-imx477-Re-enable-temperature-sensor.patch | 23 + ...lo-katana-dac-audio-Reduce-I2C-clock.patch | 25 + ...ys-jedec-spi-nor-Add-speed-parameter.patch | 308 + ...-constraints-for-E-AC3-DTS-HD-and-ML.patch | 137 + ...fix-channel-info-for-compressed-form.patch | 86 + ...m_64mp-Modify-the-line-length-of-128.patch | 44 + ...rducam_64mp-Add-8000x6000-resolution.patch | 105 + ...ia-i2c-arducam_64mp-Add-PDAF-support.patch | 163 + ...remap-Document-CM4-40-41-restriction.patch | 24 + ...ow-mac-address-to-be-set-in-smsc95xx.patch | 120 + ...hip-debian-certificates-as-hex-files.patch | 1455 ++++ ...t-for-all-the-downstream-rpi-sound-c.patch | 329 + ...62-Set-the-pre_enable_upstream_first.patch | 21 + ...-cards-Fix-Codec-Zero-rate-switching.patch | 48 + ...trickle-voltage-mv-parameter-to-RTCs.patch | 68 + ...mx296-Add-standby-delay-during-probe.patch | 25 + ...ays-Add-bmp380-to-i2c-sensor-overlay.patch | 78 + ...odule-parameter-for-maximum-pdu-size.patch | 162 + ...x296-Updated-imx296-driver-for-exter.patch | 40 + ...s-imx258-Fix-alternate-compatible-st.patch | 26 + ...-vc_mem-Fix-preprocessor-conditional.patch | 21 + ...ers-dwc_otg-Fix-fallthrough-warnings.patch | 32 + ...-sm-cma-Switch-one-bit-bitfields-to-.patch | 61 + ...311-Fix-uninitialized-variable-usage.patch | 21 + ...fault-values-for-Waveshare-7.9-inch-.patch | 29 + ...2c-bus-overrides-to-edt-ft5406-overl.patch | 102 + ...overlays-Fix-README-text-for-i2c-fan.patch | 25 + ...-irqchip-irq-bcm2835-Concurrency-fix.patch | 50 + ...s-Add-drm-option-to-piscreen-overlay.patch | 58 + ...Resolve-clash-in-spi_device_id-names.patch | 36 + ...46-Add-missing-spi_device_id-strings.patch | 50 + ...codec-Downgrade-the-level-for-a-debu.patch | 27 + ...-functions-into-a-more-logical-order.patch | 286 + ...ework-the-atomic-vs-non-atomic-split.patch | 192 + ...d-NULL-pointer-dereference-in-f2fs_i.patch | 63 + ...ng-iproc-rng200-Add-BCM2838-support.patch} | 22 +- ...t-for-100ms-following-PERST-deassert.patch | 39 + ...0-0850-overlays-Add-a-sample-hat_map.patch | 47 + ...-usb-phy-generic-Get-the-vbus-supply.patch | 26 + ...0853-dts-2712-Update-for-device-tree.patch | 7672 +++++++++++++++++ ...mstb-Allow-to-build-for-ARCH_BCM2835.patch | 282 + ...-Allow-RESET_BRCMSTB-on-ARCH_BCM2835.patch | 20 + ...nctrl-bcm2712-pinctrl-pinconf-driver.patch | 1324 +++ ...-mmc-brcmstb-add-support-for-BCM2712.patch | 498 ++ .../950-0860-sdhci-Add-SD-Express-hook.patch | 90 + ...river-though-not-yet-the-Makesfiles-.patch | 3788 ++++++++ ...q-bcm2712-mip-Support-for-2712-s-MIP.patch | 386 + ...et-brcmstb-rescal-Support-shared-use.patch | 47 + ...-net-macb-Also-set-DMA-coherent-mask.patch | 418 + ...wc3-Set-DMA-and-coherent-masks-early.patch | 384 + ...rrypi-touchscreen-Insert-more-delays.patch | 37 + ...0867-PCI-brcmstb-Add-BCM2712-support.patch | 1108 +++ ...V4L2-Add-PiSP-opaque-formats-to-V4L2.patch | 42 + ...-Add-PiSP-compressed-formats-to-V4L2.patch | 39 + ...mfd-Add-binding-for-Raspberry-Pi-RP1.patch | 249 + .../950-0872-mfd-Add-rp1-driver.patch | 442 + ...ck-Add-bindings-for-Raspberry-Pi-RP1.patch | 65 + .../950-0874-clk-Add-rp1-clock-driver.patch | 2208 +++++ ...trl-Add-bindings-for-Raspberry-Pi-RP.patch | 60 + .../950-0876-pinctrl-Add-rp1-driver.patch | 1666 ++++ ...0-0877-serial-pl011-rp1-uart-support.patch | 129 + ...f-dwcmshc-define-sdio-timeout-clocks.patch | 83 + ...mc-sdhci-of-dwcmshc-rp1-sdio-changes.patch | 83 + ...950-0880-clk-rp1-Add-sdio-clk-driver.patch | 641 ++ ...ware-Add-SMBUS-quick-command-support.patch | 76 + ...-dmaengine-dw-axi-dmac-Fixes-for-RP1.patch | 355 + ...w-Handle-combined-tx-and-rx-messages.patch | 64 + ...950-0884-pwm-Add-support-for-RP1-PWM.patch | 292 + .../950-0885-drm-Add-RP1-DSI-driver.patch | 2678 ++++++ .../950-0886-drm-Add-RP1-DPI-driver.patch | 1552 ++++ .../950-0887-drm-Add-RP1-VEC-driver.patch | 3078 +++++++ ...p-compression-format-support-to-v4l2.patch | 75 + ...rp1-Add-CFE-Camera-Front-End-support.patch | 4527 ++++++++++ ...-net-cdns-macb-AXI-tuning-properties.patch | 38 + ...-dwc-list-all-supported-sample-sizes.patch | 29 + ...0892-ASoC-dwc-Support-set_bclk_ratio.patch | 59 + ...950-0893-ASoC-dwc-Add-DMACR-handling.patch | 81 + ...0-0894-ASOC-dwc-Improve-DMA-shutdown.patch | 128 + ...5-ASOC-dwc-Fix-16-bit-audio-handling.patch | 88 + ...bcm-Remove-dependency-on-BCM2835-I2S.patch | 304 + ...n-Add-RP1-ADC-and-temperature-driver.patch | 343 + ...d-bcm2835-pm-Add-support-for-BCM2712.patch | 69 + ...cm2835-power-Add-support-for-BCM2712.patch | 76 + ...spi-gpio-to-correctly-implement-sck-.patch | 150 + ...lement-spidelay-when-requested-bit-r.patch | 55 + ...ix-up-register-addresses-for-V3D-7.x.patch | 672 ++ ...UAPI-to-match-user-space-for-V3D-7.x.patch | 24 + ...-2712-v3d-as-a-compatible-V3D-device.patch | 19 + ...Improve-MMU-support-for-larger-pages.patch | 64 + ...v3d-Add-BCM2712-to-compatibility-lis.patch | 19 + ...vers-char-add-generic-gpiomem-driver.patch | 328 + ...-drivers-char-delete-bcm2835-gpiomem.patch | 301 + ...1-adc-check-conversion-validity-befo.patch | 34 + ...maengine-bcm2835-Add-BCM2712-support.patch | 36 + ...m2835-HACK-Support-DMA-Lite-channels.patch | 57 + .../950-0913-clk-bcm-rpi-Add-disp-clock.patch | 46 + ...-optionally-enable-link-down-powersa.patch | 26 + ...5-Rename-to_bcm2711_cbaddr-to-to_40b.patch | 75 + ...cm2835-Fix-dma-driver-for-BCM2835-38.patch | 77 + ...0917-drivers-iommu-Add-BCM2712-IOMMU.patch | 855 ++ ...stb-l2-Add-config-for-2711-controlle.patch | 73 + ...d-simple-RTC-driver-for-Raspberry-Pi.patch | 237 + ...new-binding-for-Raspberry-Pi-RTC-dri.patch | 35 + ...m-fan-Add-fan-speed-register-support.patch | 164 + ...t-Add-bindings-for-raspberrypi-butto.patch | 63 + ...t-Add-bindings-for-raspberrypi-butto.patch | 27 + ...d-raspberrypi-button-firmware-driver.patch | 197 + ...6-dt-bindings-update-rpi-rtc-binding.patch | 29 + ...add-battery-charge-circuit-control-a.patch | 153 + ...-Avoid-panic-when-booted-with-no-kms.patch | 29 + ...ero-sized-destination-as-full-screen.patch | 28 + ...-for-when-the-YUV-chroma-planes-are-.patch | 50 + ...-drm-vc4-hdmi-Enable-the-audio-clock.patch | 39 + ...n-if-writing-to-an-unknown-HDMI-regi.patch | 31 + ...vs-More-logging-for-dlist-generation.patch | 41 + ...Print-error-if-we-fail-an-allocation.patch | 66 + ...dd-more-debugging-for-LBM-allocation.patch | 36 + ...-Use-return-variable-in-atomic_check.patch | 31 + ...-Move-assigned_channel-to-a-variable.patch | 47 + ...vc4-Introduce-generation-number-enum.patch | 1029 +++ ...-paths-unavailable-on-any-generation.patch | 577 ++ ...switch-statement-to-simplify-vc4_hvs.patch | 125 + ...switch-statement-to-simplify-enablin.patch | 74 + ...st-if-the-EOF-interrupts-are-enabled.patch | 100 + ...-drm-vc4-hvs-Create-hw_init-function.patch | 188 + ...drm-vc4-hvs-Create-cob_init-function.patch | 167 + ...945-drm-vc4-hvs-Rename-hvs_regs-list.patch | 38 + ...plane-Change-ptr0_offset-to-an-array.patch | 103 + ...947-drm-vc4-hvs-Rework-LBM-alignment.patch | 45 + ...ge-prototype-of-__vc4_hvs_alloc-to-p.patch | 93 + ...s-vertical-scaling-must-always-be-en.patch | 30 + ...id-hang-with-debug-registers-when-su.patch | 39 + ...-buffer-offset-out-of-the-vc4_plane_.patch | 154 + ...t-debug-not-resetting-the-next-entry.patch | 33 + ...ncorrect-limit-from-hvs_dlist-debugf.patch | 57 + ...m-vc4-hvs-Remove-ABORT_ON_EMPTY-flag.patch | 50 + ...ble-SCALER_CONTROL-early-in-HVS-init.patch | 59 + ...gs-display-Add-BCM2712-HDMI-bindings.patch | 26 + ...ngs-display-Add-BCM2712-HVS-bindings.patch | 34 + ...play-Add-BCM2712-PixelValve-bindings.patch | 28 + ...ngs-display-Add-BCM2712-MOP-bindings.patch | 28 + ...-display-Add-BCM2712-MOPLET-bindings.patch | 25 + ...play-Add-BCM2712-KMS-driver-bindings.patch | 23 + ...950-0962-drm-vc4-drv-Support-BCM2712.patch | 47 + ...0963-drm-vc4-hvs-Support-BCM2712-HVS.patch | 2139 +++++ ...-Add-support-for-BCM2712-PixelValves.patch | 144 + ...-support-for-BCM2712-HDMI-controller.patch | 1057 +++ ...oduce-structure-to-deal-with-revisio.patch | 117 + ...rm-vc4-txp-Rename-TXP-data-structure.patch | 66 + ...m-vc4-txp-Add-byte-enable-toggle-bit.patch | 56 + ...horizontal-and-vertical-size-offset-.patch | 59 + ...vc4-txp-Handle-40-bits-DMA-Addresses.patch | 59 + ...-the-encoder-type-in-the-variant-str.patch | 44 + ...m-vc4-txp-Add-a-new-TXP-encoder-type.patch | 475 + ...-vc4-txp-Add-support-for-BCM2712-MOP.patch | 64 + ...m-vc4-txp-Add-BCM2712-MOPLET-support.patch | 42 + ...-0975-drm-vc4-Add-additional-warn_on.patch | 240 + ...Switch-generation-mockup-to-a-switch.patch | 47 + ...op-drm-parameter-for-vc4_find_crtc_f.patch | 63 + ...c4-tests-Return-the-allocated-output.patch | 174 + ...rm-vc4-tests-Add-BCM2712-mock-driver.patch | 87 + ...d-tests-for-BCM2712-PixelValve-Muxin.patch | 138 + ...-fkms-Rename-plane-related-functions.patch | 64 + ...ests-Use-custom-plane-state-for-mock.patch | 95 + ...d-function-to-lookup-a-plane-for-a-C.patch | 36 + ...d-helper-to-add-a-new-plane-to-a-sta.patch | 62 + ...sts-Support-a-few-more-plane-formats.patch | 26 + ...Introduce-a-test-for-LBM-buffer-size.patch | 358 + ...d-setting-core-and-disp-clocks-for-h.patch | 40 + ...ssign-LBM-memory-during-atomic_flush.patch | 240 + ...-Alter-the-timing-for-the-Pi-7-DSI-d.patch | 33 + ...eshare-Fix-up-timings-for-10.1-panel.patch | 33 + ...-Fix-locking-in-imx477_init_controls.patch | 34 + ...-0994-overlays-Fix-vc4-kms-dsi-7inch.patch | 57 + ...dec-Fix-broken-channel-map-reporting.patch | 56 + ...fe-Fix-use-of-freed-memory-on-errors.patch | 48 + ...ix-width-height-in-cfe_start_channel.patch | 88 + ...edia-rp1-csi2-Fix-missing-reg-writes.patch | 36 + ...-0-not-1-when-working-with-unsigned-.patch | 33 + ...edia-rp1-cfe-Fix-verbose-debug-print.patch | 26 + ...ename-xxx_dbg_irq-to-xxx_dbg_verbose.patch | 227 + ...-rp1-Add-back-reg-write-debug-prints.patch | 41 + ...e-Add-verbose-debug-module-parameter.patch | 23 + ...05-media-rp1-csi2-Track-CSI-2-errors.patch | 245 + ...1006-media-rp1-cfe-Drop-unused-field.patch | 31 + ...1-csi2-Set-values-for-enum-csi2_mode.patch | 30 + ...8-media-rp1-fe-Fix-default-mbus-code.patch | 27 + ...-cfe-Fix-default-meta-format-s-field.patch | 25 + ...il-streaming-if-FE_CONFIG-node-is-no.patch | 31 + ...config-entry-for-IMX477-to-the-camer.patch | 51 + ...alias-for-the-displays-to-use-as-the.patch | 109 + ...dt-Add-DSI1-and-DSI2-aliases-to-2712.patch | 24 + ...e-the-clear-of-SCALER_DISPBKGND_FILL.patch | 64 + ...rcmstb-Use-dynamic-GPIO-base-numbers.patch | 117 + ...-rpivid-Allow-use-of-iommu-in-rpivid.patch | 57 + ...1019-dts-bcm2712-Add-iommu-to-rpivid.patch | 22 + ...1_cfe-Remove-PISP-specific-MBUS-form.patch | 117 + ...m2835-codec-Correct-alignment-requir.patch | 53 + ...n-edt-ft5x06-Suppress-bogus-data-on-.patch | 96 + ...7-allow-specification-of-the-i2c-bus.patch | 97 + ...-Set-default-I2C-baudrates-to-100kHz.patch | 46 + ...e-DMA-memcpy-support-from-bcm2708_fb.patch | 345 + ...address-offset-for-planes-with-src_-.patch | 48 + ...1_cfe-Fix-link-validate-test-for-pix.patch | 69 + ...4-dts-bcm2712-Use-the-new-model-name.patch | 23 + ...nt-to-request-a-particular-dev-fbN-n.patch | 93 + ...ok-up-preferred-fbdev-node-number-fr.patch | 41 + ...-for-drm-framebuffer-allocations-on-.patch | 72 + ...ange-DRM-card-alias-from-underscore-.patch | 26 + ...r-alias-names-from-_-to-for-drm_dsiN.patch | 24 + ...ange-query-for-FB-designation-from-d.patch | 28 + ...ames-from-_-to-for-drm_fbN_-override.patch | 43 + .../950-1044-Typo-in-overlays-README.patch | 21 + ...-dts-bcm2712-Add-the-krnbt-parameter.patch | 23 + ...-up-interrupt-handler-for-both-2835-.patch | 109 + ...2-firmware-kms-node-to-using-the-271.patch | 25 + ...vers-media-imx477-Disable-the-scaler.patch | 35 + ...-Add-drm_fbN_vc4-overrides-for-Pi0-4.patch | 37 + ...cp23017-allow-specification-of-the-i.patch | 95 + ...sp_be-Add-back-V4L2_PIX_FMT_RPI_BE-f.patch | 54 + ...brcmstb-add-optional-property-brcm-t.patch | 32 + ...stb-optionally-extend-Tperst_clk-tim.patch | 71 + ...arams-for-PCIe-reset-timing-override.patch | 59 + ...on-t-unconditionally-enable-MPS-read.patch | 35 + ...x477-Set-horizontal-binning-when-dis.patch | 39 + ...-Add-Revision-Serial-Model-to-cpuinf.patch | 25 + ...0-rpi-zero-2-w-Remove-WLAN-firmwares.patch | 35 + ...e-Set-the-CSI-2-link-frequency-corre.patch | 111 + ...2712-rpi-5-b-Create-some-dummy-nodes.patch | 42 + ...-rp1-Add-spi6-fix-spi1-address-cells.patch | 49 + ...art-n-pi5-Add-the-pinctrl-0-property.patch | 67 + ...mx477-Add-V4L2_CID_LINK_FREQ-control.patch | 51 + ...x477-Correctly-set-IMX477_PIXEL_RATE.patch | 24 + ...ect-logic-on-stopping-an-HVS-channel.patch | 52 + ...p-WARN-for-HVS-FIFOs-not-being-empty.patch | 30 + ...-stale-dlists-if-channel-is-disabled.patch | 85 + ...dd-hvs_dlist_allocs-debugfs-function.patch | 64 + ...size-of-the-dlist-allocation-that-wa.patch | 23 + ...port-odd-horizontal-timings-on-BCM27.patch | 104 + ...t-the-last-DMA-scoop-out-of-the-FIFO.patch | 41 + ...mc-sdhci-add-SPURIOUS_INT_RESP-quirk.patch | 62 + ...sdhci-of-dwcmhsc-Add-Raspberry-Pi-RP.patch | 42 + ...i-of-dwcmshc-add-RP1-dt-ID-and-quirk.patch | 41 + ...P1-SDHCI-controller-compatible-strin.patch | 104 + ...dioinjector_octo-Add-soundcard-owner.patch | 22 + ...x708-Adjust-broken-line-correction-p.patch | 139 + ...media-cfe-Don-t-confuse-MHz-and-Mbps.patch | 96 + ...Fix-cam-port-override-for-regulators.patch | 25 + ...v5647-Regularise-vcm-node-label-name.patch | 32 + ...ov5647-cam0-mode-should-use-cam0_reg.patch | 27 + .../950-1150-w1-Disable-kernel-log-spam.patch | 25 + ...s-Add-a-media-bus-format-enum-for-16.patch | 21 + ...2-Add-additional-pixel-formats-for-u.patch | 73 + ...e-Add-16-bit-and-compressed-mono-for.patch | 52 + ...sp_be-Add-mono-and-48-bit-RGB-pixel-.patch | 72 + ...ove-check-in-set_bclk_ratio-handling.patch | 32 + ...lays-README-Fix-cut-and-paste-errors.patch | 39 + ...-Switch-from-V4L2_CID_GAIN-to-V4L2_C.patch | 38 + ...lanes-that-are-completely-off-screen.patch | 63 + ...play-connector-Select-DRM_KMS_HELPER.patch | 29 + ...-dlist-alloc-immediately-if-it-never.patch | 56 + ...-Include-I2C-details-in-names-for-th.patch | 48 + ...lude-I2C-details-in-names-for-the-de.patch | 52 + ...iotlb-bounce-buffers-being-imported-.patch | 84 + ...rlays-i2c-sensor-Add-adt7410-support.patch | 75 + ...overlays-hat_map-Add-pisound-mapping.patch | 26 + ...argins-on-the-composite-connector-st.patch | 47 + ...070me05000-Add-prepare_upstream_firs.patch | 26 + ...e-Find-the-source-pads-on-the-sensor.patch | 55 + ...ption-for-cam0-to-camera-mux-Nport-o.patch | 101 + ...dwc-Permit-sample-rates-up-to-384kHz.patch | 26 + ...0-1176-ASoC-dwc-Fix-full-duplex-mode.patch | 63 + ...2x-Adds-bindings-for-TAS575x-devices.patch | 45 + ...rt-for-TAS575x-to-the-pcm512x-driver.patch | 102 + .../950-1182-drm-panel-add-panel-dsi.patch | 176 + ...-bindings-display-panel-dsi-bindings.patch | 136 + ...e-overlay-for-using-panel-dsi-on-RPi.patch | 176 + ...5-allow-specification-of-the-i2c-bus.patch | 159 + ...ts-bcm2712-put-usb-under-axi-not-soc.patch | 59 + ...rect-HVS-muxing-setup-for-the-moplet.patch | 26 + ...moplet-have-different-register-offse.patch | 68 + ...orrect-the-size-of-the-register-rang.patch | 25 + ...CCI-register-access-helper-functions.patch | 388 + ...a-dt-bindings-Add-OmniVision-OV64A40.patch | 114 + ...ndings-i2c-Add-Rohm-BU64754-bindings.patch | 83 + ...2c-Add-driver-for-OmniVision-OV64A40.patch | 3763 ++++++++ ...HM-BU64754-Camera-Autofocus-Actuator.patch | 368 + ...rlay-for-the-OV64A40-Arducam-Camera-.patch | 426 + ...edia-rp1-cfe-Fix-verbose-debug-print.patch | 26 + ...ia-rp1-cfe-Expose-find_format_by_pix.patch | 33 + ...201-media-rp1-cfe-Add-missing-remaps.patch | 43 + ...p1-cfe-Add-missing-compressed-remaps.patch | 43 + ...d-cfe_find_16bit_code-and-cfe_find_c.patch | 74 + ...-media-rp1-csi2-Fix-csi2_pad_set_fmt.patch | 95 + ...media-rp1-fe-Fix-pisp_fe_pad_set_fmt.patch | 104 + ...se-get_frame_desc-to-get-CSI-2-VC-an.patch | 146 + ...1207-media-rp1-cfe-Add-is_image_node.patch | 91 + ...dia-rp1-cfe-Dual-purpose-video-nodes.patch | 621 ++ .../950-1209-media-rp1-Drop-LE-handling.patch | 127 + ...-rp1-csi2-Use-standard-link_validate.patch | 75 + ...ia-rp1-fe-Use-standard-link_validate.patch | 70 + ...Improve-link-validation-for-metadata.patch | 61 + ...pinctrl-bcm-Kconfig-Fix-BCM2712-help.patch | 24 + ...panel-fix-waveshare-panel-software-r.patch | 41 + ...-Pass-given-partition-number-through.patch | 33 + ...2712-rpi-5-b-Enable-warm-reboot-mode.patch | 23 + ...c-imx296-imx477-Configure-tigger_mod.patch | 85 + ...ays-on-parameter-to-imx477-and-imx29.patch | 99 + ...06-Correct-prefix-length-in-snprintf.patch | 29 + ...712-rpi-5-b-Allow-RTC-to-be-disabled.patch | 38 + ...designware-Look-for-CNT-values-in-DT.patch | 57 + .../950-1227-dts-rp1-Add-I2C-timings.patch | 103 + ...sp_be-pisp_fe-Update-UAPI-header-lic.patch | 58 + ...dia-cfe-Add-more-robust-ISR-handlers.patch | 207 + ...fer-bclk_ratio-handling-to-hw_params.patch | 89 + ...x-reading-of-frame-count-on-GEN5-Pi4.patch | 79 + ...2712-rpi-5-b-Add-eth_ledx-parameters.patch | 56 + ...m2712-rpi-5-b-Add-fan-speed-dtparams.patch | 71 + ...n-t-check-if-plane-state-fb-state-fb.patch | 93 + ...-Support-spi0-0cs-and-SPI_NO_CS-mode.patch | 42 + ...mx519-Add-V4L2_CID_LINK_FREQ-control.patch | 51 + ...ducam_64mp-Add-V4L2_CID_LINK_FREQ-co.patch | 56 + ...panel-Modify-the-DSI-mode-to-fix-the.patch | 25 + ...panel-Modified-the-timing-of-11.9inc.patch | 22 + ...12-support-to-vc4_plane_async_set_fb.patch | 88 + ...ic_async_check-to-call-the-right-mod.patch | 38 + ...Allow-non-standard-modes-with-variou.patch | 343 + ...M-pl011-Add-rs485-to-the-RP1-support.patch | 24 + ...q-bcm2712-mip-Support-for-2712-s-MIP.patch | 38 + .../960-hwrng-iproc-set-quality-to-1000.patch | 2 +- target/linux/generic/config-6.1 | 22 + 340 files changed, 69558 insertions(+), 75 deletions(-) delete mode 100644 target/linux/bcm27xx/patches-6.1/950-0699-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0790-media-i2c-imx219-fix-binning-and-rate_factor-for-480.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0791-serial-sc16is7xx-Read-modem-line-state-at-startup.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0792-drivers-media-bcm2835_unicam-Improve-frame-sequence-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0793-dtoverlays-Fix-pitft-28-35-overlays-for-6.1-driver-c.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0795-driver-media-i2c-imx477-Re-enable-temperature-sensor.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0796-overlays-allo-katana-dac-audio-Reduce-I2C-clock.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0797-overlays-jedec-spi-nor-Add-speed-parameter.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0798-ALSA-pcm-fix-ELD-constraints-for-E-AC3-DTS-HD-and-ML.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0799-ASoC-hdmi-codec-fix-channel-info-for-compressed-form.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0800-media-i2c-arducam_64mp-Modify-the-line-length-of-128.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0801-media-i2c-arducam_64mp-Add-8000x6000-resolution.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0802-media-i2c-arducam_64mp-Add-PDAF-support.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0803-overlays-audremap-Document-CM4-40-41-restriction.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0804-fixup-Allow-mac-address-to-be-set-in-smsc95xx.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0809-cfg80211-ship-debian-certificates-as-hex-files.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0810-fixup-Add-support-for-all-the-downstream-rpi-sound-c.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0815-fixup-drm-tc358762-Set-the-pre_enable_upstream_first.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0816-rpi-sound-cards-Fix-Codec-Zero-rate-switching.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0818-overlays-Add-trickle-voltage-mv-parameter-to-RTCs.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0819-drivers-media-imx296-Add-standby-delay-during-probe.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0820-overlays-Add-bmp380-to-i2c-sensor-overlay.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0821-can-isotp-add-module-parameter-for-maximum-pdu-size.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0822-drivers-media-imx296-Updated-imx296-driver-for-exter.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0823-media-dt-bindings-imx258-Fix-alternate-compatible-st.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0825-char-broadcom-vc_mem-Fix-preprocessor-conditional.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0826-drivers-dwc_otg-Fix-fallthrough-warnings.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0827-vc04_services-vc-sm-cma-Switch-one-bit-bitfields-to-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0828-media-i2c-ov2311-Fix-uninitialized-variable-usage.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0830-drm-panel-Fix-default-values-for-Waveshare-7.9-inch-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0831-dtoverlays-Add-i2c-bus-overrides-to-edt-ft5406-overl.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0832-dtoverlays-Fix-README-text-for-i2c-fan.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0833-drivers-irqchip-irq-bcm2835-Concurrency-fix.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0835-dtoverlays-Add-drm-option-to-piscreen-overlay.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0836-drm-ili9486-Resolve-clash-in-spi_device_id-names.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0837-input-ads7846-Add-missing-spi_device_id-strings.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0838-staging-bcm2835-codec-Downgrade-the-level-for-a-debu.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0840-gpio-fsm-Sort-functions-into-a-more-logical-order.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0841-gpio_fsm-Rework-the-atomic-vs-non-atomic-split.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0842-f2fs-fix-to-avoid-NULL-pointer-dereference-in-f2fs_i.patch rename target/linux/bcm27xx/patches-6.1/{950-0177-hwrng-iproc-rng200-Add-BCM2838-support.patch => 950-0846-hwrng-iproc-rng200-Add-BCM2838-support.patch} (88%) create mode 100644 target/linux/bcm27xx/patches-6.1/950-0847-PCI-brcmstb-Wait-for-100ms-following-PERST-deassert.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0850-overlays-Add-a-sample-hat_map.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0851-Revert-usb-phy-generic-Get-the-vbus-supply.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0853-dts-2712-Update-for-device-tree.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0855-gpio_brcmstb-Allow-to-build-for-ARCH_BCM2835.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0856-Allow-RESET_BRCMSTB-on-ARCH_BCM2835.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0857-pinctrl-bcm2712-pinctrl-pinconf-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0859-mmc-brcmstb-add-support-for-BCM2712.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0860-sdhci-Add-SD-Express-hook.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0861-Add-new-pispbe-driver-though-not-yet-the-Makesfiles-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0862-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0863-reset-reset-brcmstb-rescal-Support-shared-use.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0864-net-macb-Also-set-DMA-coherent-mask.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0865-usb-dwc3-Set-DMA-and-coherent-masks-early.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0866-drm-panel-raspberrypi-touchscreen-Insert-more-delays.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0867-PCI-brcmstb-Add-BCM2712-support.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0868-V4L2-Add-PiSP-opaque-formats-to-V4L2.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0869-V4L2-Add-PiSP-compressed-formats-to-V4L2.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0871-dt-binding-mfd-Add-binding-for-Raspberry-Pi-RP1.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0872-mfd-Add-rp1-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0873-dt-bindings-clock-Add-bindings-for-Raspberry-Pi-RP1.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0874-clk-Add-rp1-clock-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0875-dt-bindings-pinctrl-Add-bindings-for-Raspberry-Pi-RP.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0876-pinctrl-Add-rp1-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0877-serial-pl011-rp1-uart-support.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0878-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0879-mmc-sdhci-of-dwcmshc-rp1-sdio-changes.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0880-clk-rp1-Add-sdio-clk-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0881-i2c-designware-Add-SMBUS-quick-command-support.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0882-dmaengine-dw-axi-dmac-Fixes-for-RP1.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0883-spi-dw-Handle-combined-tx-and-rx-messages.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0884-pwm-Add-support-for-RP1-PWM.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0885-drm-Add-RP1-DSI-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0886-drm-Add-RP1-DPI-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0887-drm-Add-RP1-VEC-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0888-v4l2-Add-pisp-compression-format-support-to-v4l2.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0889-media-rp1-Add-CFE-Camera-Front-End-support.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0890-dt-bindings-net-cdns-macb-AXI-tuning-properties.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0891-ASoC-dwc-list-all-supported-sample-sizes.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0892-ASoC-dwc-Support-set_bclk_ratio.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0893-ASoC-dwc-Add-DMACR-handling.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0894-ASOC-dwc-Improve-DMA-shutdown.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0895-ASOC-dwc-Fix-16-bit-audio-handling.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0896-ASoC-bcm-Remove-dependency-on-BCM2835-I2S.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0897-hwmon-Add-RP1-ADC-and-temperature-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0898-mfd-bcm2835-pm-Add-support-for-BCM2712.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0899-soc-bcm-bcm2835-power-Add-support-for-BCM2712.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0900-drivers-spi-Fix-spi-gpio-to-correctly-implement-sck-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0901-spi-spi-gpio-Implement-spidelay-when-requested-bit-r.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0902-drm-v3d-fix-up-register-addresses-for-V3D-7.x.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0903-drm-v3d-update-UAPI-to-match-user-space-for-V3D-7.x.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0904-drm-v3d-add-brcm-2712-v3d-as-a-compatible-V3D-device.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0905-drm-v3d-Improve-MMU-support-for-larger-pages.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0906-dt-bindings-gpu-v3d-Add-BCM2712-to-compatibility-lis.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0907-drivers-char-add-generic-gpiomem-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0909-drivers-char-delete-bcm2835-gpiomem.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0910-drivers-hwmon-rp1-adc-check-conversion-validity-befo.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0911-dmaengine-bcm2835-Add-BCM2712-support.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0912-dmaengine-bcm2835-HACK-Support-DMA-Lite-channels.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0913-clk-bcm-rpi-Add-disp-clock.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0914-net-phy-broadcom-optionally-enable-link-down-powersa.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0915-dmaengine-bcm2835-Rename-to_bcm2711_cbaddr-to-to_40b.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0916-dmaengine-bcm2835-Fix-dma-driver-for-BCM2835-38.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0917-drivers-iommu-Add-BCM2712-IOMMU.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0918-irqchip-irq-brcmstb-l2-Add-config-for-2711-controlle.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0919-rtc-rtc-rpi-Add-simple-RTC-driver-for-Raspberry-Pi.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0920-dt-bindings-rtc-new-binding-for-Raspberry-Pi-RTC-dri.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0921-hwmon-pwm-fan-Add-fan-speed-register-support.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0923-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0924-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0925-Input-Add-raspberrypi-button-firmware-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0926-dt-bindings-update-rpi-rtc-binding.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0927-drivers-rtc-rpi-add-battery-charge-circuit-control-a.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0928-vc4_drv-Avoid-panic-when-booted-with-no-kms.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0929-drm-vc4-Treat-zero-sized-destination-as-full-screen.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0930-drm-vc4-Fix-FKMS-for-when-the-YUV-chroma-planes-are-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0931-drm-vc4-hdmi-Enable-the-audio-clock.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0932-drm-vc4-hdmi-Warn-if-writing-to-an-unknown-HDMI-regi.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0933-drm-vc4-hvs-More-logging-for-dlist-generation.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0934-drm-vc4-hvs-Print-error-if-we-fail-an-allocation.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0935-drm-vc4-plane-Add-more-debugging-for-LBM-allocation.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0936-drm-vc4-plane-Use-return-variable-in-atomic_check.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0937-drm-vc4-crtc-Move-assigned_channel-to-a-variable.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0938-drm-vc4-Introduce-generation-number-enum.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0939-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0940-drm-vc4-hvs-Use-switch-statement-to-simplify-vc4_hvs.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0941-drm-vc4-hvs-Use-switch-statement-to-simplify-enablin.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0942-drm-vc4-hvs-Test-if-the-EOF-interrupts-are-enabled.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0943-drm-vc4-hvs-Create-hw_init-function.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0944-drm-vc4-hvs-Create-cob_init-function.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0945-drm-vc4-hvs-Rename-hvs_regs-list.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0946-drm-vc4-plane-Change-ptr0_offset-to-an-array.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0947-drm-vc4-hvs-Rework-LBM-alignment.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0948-drm-vc4-hvs-Change-prototype-of-__vc4_hvs_alloc-to-p.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0949-drm-vc4-UV-planes-vertical-scaling-must-always-be-en.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0950-drm-vc4-hdmi-Avoid-hang-with-debug-registers-when-su.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0951-drm-vc4-Move-the-buffer-offset-out-of-the-vc4_plane_.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0952-drm-vc4-Fix-dlist-debug-not-resetting-the-next-entry.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0953-drm-vc4-Remove-incorrect-limit-from-hvs_dlist-debugf.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0954-drm-vc4-hvs-Remove-ABORT_ON_EMPTY-flag.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0955-drm-vc4-Enable-SCALER_CONTROL-early-in-HVS-init.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0956-dt-bindings-display-Add-BCM2712-HDMI-bindings.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0957-dt-bindings-display-Add-BCM2712-HVS-bindings.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0958-dt-bindings-display-Add-BCM2712-PixelValve-bindings.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0959-dt-bindings-display-Add-BCM2712-MOP-bindings.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0960-dt-bindings-display-Add-BCM2712-MOPLET-bindings.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0961-dt-bindings-display-Add-BCM2712-KMS-driver-bindings.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0962-drm-vc4-drv-Support-BCM2712.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0963-drm-vc4-hvs-Support-BCM2712-HVS.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0964-drm-vc4-crtc-Add-support-for-BCM2712-PixelValves.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0965-drm-vc4-hdmi-Add-support-for-BCM2712-HDMI-controller.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0966-drm-vc4-txp-Introduce-structure-to-deal-with-revisio.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0967-drm-vc4-txp-Rename-TXP-data-structure.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0968-drm-vc4-txp-Add-byte-enable-toggle-bit.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0969-drm-vc4-txp-Add-horizontal-and-vertical-size-offset-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0970-drm-vc4-txp-Handle-40-bits-DMA-Addresses.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0971-drm-vc4-txp-Move-the-encoder-type-in-the-variant-str.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0972-drm-vc4-txp-Add-a-new-TXP-encoder-type.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0973-drm-vc4-txp-Add-support-for-BCM2712-MOP.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0974-drm-vc4-txp-Add-BCM2712-MOPLET-support.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0975-drm-vc4-Add-additional-warn_on.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0976-drm-vc4-tests-Switch-generation-mockup-to-a-switch.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0977-drm-vc4-tests-Drop-drm-parameter-for-vc4_find_crtc_f.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0978-drm-vc4-tests-Return-the-allocated-output.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0979-drm-vc4-tests-Add-BCM2712-mock-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0980-drm-vc4-tests-Add-tests-for-BCM2712-PixelValve-Muxin.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0981-drm-vc4-fkms-Rename-plane-related-functions.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0982-drm-vc4-tests-Use-custom-plane-state-for-mock.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0983-drm-vc4-tests-Add-function-to-lookup-a-plane-for-a-C.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0984-drm-vc4-tests-Add-helper-to-add-a-new-plane-to-a-sta.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0985-drm-vc4-tests-Support-a-few-more-plane-formats.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0986-drm-vc4-tests-Introduce-a-test-for-LBM-buffer-size.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0987-drm-vc4-kms-Avoid-setting-core-and-disp-clocks-for-h.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0988-drm-vc4-Assign-LBM-memory-during-atomic_flush.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0989-drm-panel-simple-Alter-the-timing-for-the-Pi-7-DSI-d.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0990-drm-panel-waveshare-Fix-up-timings-for-10.1-panel.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0991-media-i2c-imx477-Fix-locking-in-imx477_init_controls.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0994-overlays-Fix-vc4-kms-dsi-7inch.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0996-ASoC-hdmi-codec-Fix-broken-channel-map-reporting.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0997-media-rp1-cfe-Fix-use-of-freed-memory-on-errors.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0998-media-rp1-cfe-Fix-width-height-in-cfe_start_channel.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-0999-media-rp1-csi2-Fix-missing-reg-writes.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1000-media-rp1-fe-Use-0-not-1-when-working-with-unsigned-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1001-media-rp1-cfe-Fix-verbose-debug-print.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1002-media-rp1-cfe-Rename-xxx_dbg_irq-to-xxx_dbg_verbose.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1003-media-rp1-Add-back-reg-write-debug-prints.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1004-media-rp1-cfe-Add-verbose-debug-module-parameter.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1005-media-rp1-csi2-Track-CSI-2-errors.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1006-media-rp1-cfe-Drop-unused-field.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1007-media-rp1-csi2-Set-values-for-enum-csi2_mode.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1008-media-rp1-fe-Fix-default-mbus-code.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1009-media-rp1-cfe-Fix-default-meta-format-s-field.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1010-media-rp1-cfe-Fail-streaming-if-FE_CONFIG-node-is-no.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1011-media-i2c-Move-Kconfig-entry-for-IMX477-to-the-camer.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1013-drm-Look-for-an-alias-for-the-displays-to-use-as-the.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1014-dt-Add-DSI1-and-DSI2-aliases-to-2712.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1015-vc4-drm-Remove-the-clear-of-SCALER_DISPBKGND_FILL.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1017-gpio-brcmstb-Use-dynamic-GPIO-base-numbers.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1018-media-rpivid-Allow-use-of-iommu-in-rpivid.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1019-dts-bcm2712-Add-iommu-to-rpivid.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1020-drivers-media-rp1_cfe-Remove-PISP-specific-MBUS-form.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1022-vc04_services-bcm2835-codec-Correct-alignment-requir.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1025-input-touchscreen-edt-ft5x06-Suppress-bogus-data-on-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1029-overlays-mcp23017-allow-specification-of-the-i2c-bus.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1030-dts-bcm2712-Set-default-I2C-baudrates-to-100kHz.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1031-vc_mem-Add-the-DMA-memcpy-support-from-bcm2708_fb.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1032-drm-vc4-Correct-address-offset-for-planes-with-src_-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1033-drivers-media-rp1_cfe-Fix-link-validate-test-for-pix.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1034-dts-bcm2712-Use-the-new-model-name.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1035-fbdev-Allow-client-to-request-a-particular-dev-fbN-n.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1036-drm-fb-helper-Look-up-preferred-fbdev-node-number-fr.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1037-dt-Add-overrides-for-drm-framebuffer-allocations-on-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1039-drm-connector-Change-DRM-card-alias-from-underscore-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1040-dt-Alter-alias-names-from-_-to-for-drm_dsiN.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1041-drm-fb_helper-Change-query-for-FB-designation-from-d.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1042-dt-Alter-alias-names-from-_-to-for-drm_fbN_-override.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1044-Typo-in-overlays-README.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1045-dts-bcm2712-Add-the-krnbt-parameter.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1047-drm-vc4_fkms-Fix-up-interrupt-handler-for-both-2835-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1048-dt-Switch-bcm2712-firmware-kms-node-to-using-the-271.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1049-drivers-media-imx477-Disable-the-scaler.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1050-dt-Add-drm_fbN_vc4-overrides-for-Pi0-4.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1051-fixup-overlays-mcp23017-allow-specification-of-the-i.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1052-drivers-media-pisp_be-Add-back-V4L2_PIX_FMT_RPI_BE-f.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1053-dt-bindings-PCI-brcmstb-add-optional-property-brcm-t.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1054-drivers-pci-brcmstb-optionally-extend-Tperst_clk-tim.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1055-arm-dt-add-dtparams-for-PCIe-reset-timing-override.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1056-arm-dt-bcm2712-don-t-unconditionally-enable-MPS-read.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1057-drivers-media-imx477-Set-horizontal-binning-when-dis.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1058-fixup-arch-arm64-Add-Revision-Serial-Model-to-cpuinf.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1060-dts-bcm2710-rpi-zero-2-w-Remove-WLAN-firmwares.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1061-drivers-media-cfe-Set-the-CSI-2-link-frequency-corre.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1062-dts-bcm2712-rpi-5-b-Create-some-dummy-nodes.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1063-dts-rp1-Add-spi6-fix-spi1-address-cells.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1064-overlays-uart-n-pi5-Add-the-pinctrl-0-property.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1065-drivers-media-imx477-Add-V4L2_CID_LINK_FREQ-control.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1066-drivers-media-imx477-Correctly-set-IMX477_PIXEL_RATE.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1067-drm-vc4-Correct-logic-on-stopping-an-HVS-channel.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1068-drm-vc4-Drop-WARN-for-HVS-FIFOs-not-being-empty.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1069-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1070-drm-vc4-Add-hvs_dlist_allocs-debugfs-function.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1071-drm-vc4-Log-the-size-of-the-dlist-allocation-that-wa.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1072-drm-vc4-crtc-Support-odd-horizontal-timings-on-BCM27.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1073-spi-dw-dma-Get-the-last-DMA-scoop-out-of-the-FIFO.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1075-drivers-mmc-sdhci-add-SPURIOUS_INT_RESP-quirk.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1076-dt-bindings-mmc-sdhci-of-dwcmhsc-Add-Raspberry-Pi-RP.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1077-drivers-mmc-sdhci-of-dwcmshc-add-RP1-dt-ID-and-quirk.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1078-arm-dts-change-RP1-SDHCI-controller-compatible-strin.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1079-ASoC-bcm-audioinjector_octo-Add-soundcard-owner.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1080-drivers-media-imx708-Adjust-broken-line-correction-p.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1082-drivers-media-cfe-Don-t-confuse-MHz-and-Mbps.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1083-overlays-imx296-Fix-cam-port-override-for-regulators.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1148-overlays-ov5647-Regularise-vcm-node-label-name.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1149-overlays-ov5647-cam0-mode-should-use-cam0_reg.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1150-w1-Disable-kernel-log-spam.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1151-include-uapi-mbus-Add-a-media-bus-format-enum-for-16.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1152-include-uapi-v4l2-Add-additional-pixel-formats-for-u.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1153-drivers-media-cfe-Add-16-bit-and-compressed-mono-for.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1154-drivers-media-pisp_be-Add-mono-and-48-bit-RGB-pixel-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1155-ASoC-dwc-Remove-check-in-set_bclk_ratio-handling.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1159-overlays-README-Fix-cut-and-paste-errors.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1160-media-i2c-ov7251-Switch-from-V4L2_CID_GAIN-to-V4L2_C.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1161-drm-vc4-Drop-planes-that-are-completely-off-screen.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1162-drm-bridge-display-connector-Select-DRM_KMS_HELPER.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1163-drm-vc4-Free-the-dlist-alloc-immediately-if-it-never.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1164-input-edt-ft5x06-Include-I2C-details-in-names-for-th.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1165-input-goodix-Include-I2C-details-in-names-for-the-de.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1166-drm-vc4-Block-swiotlb-bounce-buffers-being-imported-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1167-overlays-i2c-sensor-Add-adt7410-support.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1168-overlays-hat_map-Add-pisound-mapping.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1169-drm-vc4-Set-TV-margins-on-the-composite-connector-st.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1170-drm-panel-jdi-lt070me05000-Add-prepare_upstream_firs.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1172-drivers-media-cfe-Find-the-source-pads-on-the-sensor.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1173-dtoverlays-Add-option-for-cam0-to-camera-mux-Nport-o.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1174-ASoC-dwc-Permit-sample-rates-up-to-384kHz.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1176-ASoC-dwc-Fix-full-duplex-mode.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1179-ASoC-pcm512x-Adds-bindings-for-TAS575x-devices.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1180-ASoC-Adds-support-for-TAS575x-to-the-pcm512x-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1183-dt-bindings-display-panel-dsi-bindings.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1184-overlays-example-overlay-for-using-panel-dsi-on-RPi.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1185-overlays-ADS1115-allow-specification-of-the-i2c-bus.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1186-dts-bcm2712-put-usb-under-axi-not-soc.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1187-drm-vc4-Correct-HVS-muxing-setup-for-the-moplet.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1188-drm-vc4-Mop-and-moplet-have-different-register-offse.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1189-arm-dt-bcm2712-Correct-the-size-of-the-register-rang.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1192-media-Add-MIPI-CCI-register-access-helper-functions.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1193-media-dt-bindings-Add-OmniVision-OV64A40.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1194-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1196-media-i2c-Add-ROHM-BU64754-Camera-Autofocus-Actuator.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1197-overlays-Add-overlay-for-the-OV64A40-Arducam-Camera-.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1199-media-rp1-cfe-Fix-verbose-debug-print.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1200-media-rp1-cfe-Expose-find_format_by_pix.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1201-media-rp1-cfe-Add-missing-remaps.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1202-media-rp1-cfe-Add-missing-compressed-remaps.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1203-media-rp1-cfe-Add-cfe_find_16bit_code-and-cfe_find_c.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1204-media-rp1-csi2-Fix-csi2_pad_set_fmt.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1205-media-rp1-fe-Fix-pisp_fe_pad_set_fmt.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1206-media-rp1-csi2-Use-get_frame_desc-to-get-CSI-2-VC-an.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1207-media-rp1-cfe-Add-is_image_node.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1208-media-rp1-cfe-Dual-purpose-video-nodes.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1209-media-rp1-Drop-LE-handling.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1210-media-rp1-csi2-Use-standard-link_validate.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1211-media-rp1-fe-Use-standard-link_validate.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1212-media-rp1-cfe-Improve-link-validation-for-metadata.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1214-drivers-pinctrl-bcm-Kconfig-Fix-BCM2712-help.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1216-drivers-gpu-drm-panel-fix-waveshare-panel-software-r.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1217-firmware-psci-Pass-given-partition-number-through.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1218-dts-bcm2712-rpi-5-b-Enable-warm-reboot-mode.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1222-drivers-media-i2c-imx296-imx477-Configure-tigger_mod.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1223-overlays-Add-always-on-parameter-to-imx477-and-imx29.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1224-input-edt-ft5x06-Correct-prefix-length-in-snprintf.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1225-ARM-dts-bcm2712-rpi-5-b-Allow-RTC-to-be-disabled.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1226-i2c-designware-Look-for-CNT-values-in-DT.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1227-dts-rp1-Add-I2C-timings.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1228-drivers-media-pisp_be-pisp_fe-Update-UAPI-header-lic.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1229-drivers-media-cfe-Add-more-robust-ISR-handlers.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1231-ASoC-dwc-Defer-bclk_ratio-handling-to-hw_params.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1232-drm-vc4-Fix-reading-of-frame-count-on-GEN5-Pi4.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1233-ARM-dts-bcm2712-rpi-5-b-Add-eth_ledx-parameters.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1234-ARM-dts-bcm2712-rpi-5-b-Add-fan-speed-dtparams.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1235-drm-vc4-don-t-check-if-plane-state-fb-state-fb.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1236-spi-bcm2835-Support-spi0-0cs-and-SPI_NO_CS-mode.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1237-drivers-media-imx519-Add-V4L2_CID_LINK_FREQ-control.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1238-drivers-media-arducam_64mp-Add-V4L2_CID_LINK_FREQ-co.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1239-drivers-gpu-drm-panel-Modify-the-DSI-mode-to-fix-the.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1240-drivers-gpu-drm-panel-Modified-the-timing-of-11.9inc.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1241-drm-vc4-Add-2712-support-to-vc4_plane_async_set_fb.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1242-drm-vc4-Fix-atomic_async_check-to-call-the-right-mod.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1244-drm-rp1-rp1-vec-Allow-non-standard-modes-with-variou.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1245-ARM-pl011-Add-rs485-to-the-RP1-support.patch create mode 100644 target/linux/bcm27xx/patches-6.1/950-1246-fixup-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch diff --git a/target/linux/bcm27xx/bcm2708/config-6.1 b/target/linux/bcm27xx/bcm2708/config-6.1 index c5d604e6bc..cef17940a3 100644 --- a/target/linux/bcm27xx/bcm2708/config-6.1 +++ b/target/linux/bcm27xx/bcm2708/config-6.1 @@ -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 diff --git a/target/linux/bcm27xx/bcm2709/config-6.1 b/target/linux/bcm27xx/bcm2709/config-6.1 index ec2e7f3fa6..15bbaabd74 100644 --- a/target/linux/bcm27xx/bcm2709/config-6.1 +++ b/target/linux/bcm27xx/bcm2709/config-6.1 @@ -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 diff --git a/target/linux/bcm27xx/bcm2710/config-6.1 b/target/linux/bcm27xx/bcm2710/config-6.1 index b0abd49c7f..50b3f87d7d 100644 --- a/target/linux/bcm27xx/bcm2710/config-6.1 +++ b/target/linux/bcm27xx/bcm2710/config-6.1 @@ -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 diff --git a/target/linux/bcm27xx/bcm2711/config-6.1 b/target/linux/bcm27xx/bcm2711/config-6.1 index 1912b653e5..0441305067 100644 --- a/target/linux/bcm27xx/bcm2711/config-6.1 +++ b/target/linux/bcm27xx/bcm2711/config-6.1 @@ -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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0699-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch b/target/linux/bcm27xx/patches-6.1/950-0699-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch deleted file mode 100644 index d4c5a0183e..0000000000 --- a/target/linux/bcm27xx/patches-6.1/950-0699-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch +++ /dev/null @@ -1,41 +0,0 @@ -From dffb648dffeab7246040a30b7d1669387d1e767e Mon Sep 17 00:00:00 2001 -From: Phil Elwell -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 ---- - 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 || diff --git a/target/linux/bcm27xx/patches-6.1/950-0790-media-i2c-imx219-fix-binning-and-rate_factor-for-480.patch b/target/linux/bcm27xx/patches-6.1/950-0790-media-i2c-imx219-fix-binning-and-rate_factor-for-480.patch new file mode 100644 index 0000000000..276e51d2d9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0790-media-i2c-imx219-fix-binning-and-rate_factor-for-480.patch @@ -0,0 +1,306 @@ +From 3ad8e28669e0058e3cec482a47215e50e33f2574 Mon Sep 17 00:00:00 2001 +From: Vinay Varma +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 +--- + 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); diff --git a/target/linux/bcm27xx/patches-6.1/950-0791-serial-sc16is7xx-Read-modem-line-state-at-startup.patch b/target/linux/bcm27xx/patches-6.1/950-0791-serial-sc16is7xx-Read-modem-line-state-at-startup.patch new file mode 100644 index 0000000000..c93ebf3e7e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0791-serial-sc16is7xx-Read-modem-line-state-at-startup.patch @@ -0,0 +1,28 @@ +From 52039b6ffb6e78c2f77319b167dceab9aa51d13f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +Signed-off-by: Phil Elwell +--- + 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); diff --git a/target/linux/bcm27xx/patches-6.1/950-0792-drivers-media-bcm2835_unicam-Improve-frame-sequence-.patch b/target/linux/bcm27xx/patches-6.1/950-0792-drivers-media-bcm2835_unicam-Improve-frame-sequence-.patch new file mode 100644 index 0000000000..6de340c2a9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0792-drivers-media-bcm2835_unicam-Improve-frame-sequence-.patch @@ -0,0 +1,79 @@ +From 6ef818eed60db70e9caf6bdf74cc1f9943994226 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +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 +--- + .../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); diff --git a/target/linux/bcm27xx/patches-6.1/950-0793-dtoverlays-Fix-pitft-28-35-overlays-for-6.1-driver-c.patch b/target/linux/bcm27xx/patches-6.1/950-0793-dtoverlays-Fix-pitft-28-35-overlays-for-6.1-driver-c.patch new file mode 100644 index 0000000000..d8307f9009 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0793-dtoverlays-Fix-pitft-28-35-overlays-for-6.1-driver-c.patch @@ -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 +--- + 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; diff --git a/target/linux/bcm27xx/patches-6.1/950-0795-driver-media-i2c-imx477-Re-enable-temperature-sensor.patch b/target/linux/bcm27xx/patches-6.1/950-0795-driver-media-i2c-imx477-Re-enable-temperature-sensor.patch new file mode 100644 index 0000000000..2255efd988 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0795-driver-media-i2c-imx477-Re-enable-temperature-sensor.patch @@ -0,0 +1,23 @@ +From 713a7ef9d73fca0f7fed122cb854d930b7a6ba5a Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +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 +--- + 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}, diff --git a/target/linux/bcm27xx/patches-6.1/950-0796-overlays-allo-katana-dac-audio-Reduce-I2C-clock.patch b/target/linux/bcm27xx/patches-6.1/950-0796-overlays-allo-katana-dac-audio-Reduce-I2C-clock.patch new file mode 100644 index 0000000000..43f63a1c63 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0796-overlays-allo-katana-dac-audio-Reduce-I2C-clock.patch @@ -0,0 +1,25 @@ +From d4c3133378b377ee519ea50247339cd61221fc47 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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>; diff --git a/target/linux/bcm27xx/patches-6.1/950-0797-overlays-jedec-spi-nor-Add-speed-parameter.patch b/target/linux/bcm27xx/patches-6.1/950-0797-overlays-jedec-spi-nor-Add-speed-parameter.patch new file mode 100644 index 0000000000..66c147837d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0797-overlays-jedec-spi-nor-Add-speed-parameter.patch @@ -0,0 +1,308 @@ +From 76c457e7e2920342637b1955fbaadf2aae282f05 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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,= +-Params: flash-spi- Enables flash device on SPI, CS#. +- flash-fastr-spi- Enables flash device with fast read capability +- on SPI, CS#. ++Params: spi- Enable flash device on SPI, CS# ++ fastr Add fast read capability to the flash device ++ speed Maximum SPI frequency (Hz) ++ flash-spi- Same as spi- (deprecated) ++ flash-fastr-spi- Same as spi->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- - Enables flash device on SPI, CS#. + // flash-fastr-spi- - Enables flash device with fast read capability on SPI, CS#. ++// 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"; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0798-ALSA-pcm-fix-ELD-constraints-for-E-AC3-DTS-HD-and-ML.patch b/target/linux/bcm27xx/patches-6.1/950-0798-ALSA-pcm-fix-ELD-constraints-for-E-AC3-DTS-HD-and-ML.patch new file mode 100644 index 0000000000..a35e7f4d1b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0798-ALSA-pcm-fix-ELD-constraints-for-E-AC3-DTS-HD-and-ML.patch @@ -0,0 +1,137 @@ +From e866f9fc7c6dd6af1e74ce6fa50db9ba21acae5e Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +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 +Link: https://lore.kernel.org/r/20230624165216.5719-1-hias@horus.com +Signed-off-by: Takashi Iwai +--- + 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 + #include ++#include + #include + #include + #include + ++#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)); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-0799-ASoC-hdmi-codec-fix-channel-info-for-compressed-form.patch b/target/linux/bcm27xx/patches-6.1/950-0799-ASoC-hdmi-codec-fix-channel-info-for-compressed-form.patch new file mode 100644 index 0000000000..31a351a4e8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0799-ASoC-hdmi-codec-fix-channel-info-for-compressed-form.patch @@ -0,0 +1,86 @@ +From 3f388718331b5ce2acd34730448db001759868aa Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +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 +Link: https://lore.kernel.org/r/20230624165232.5751-1-hias@horus.com +Signed-off-by: Takashi Iwai +--- + 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; + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0800-media-i2c-arducam_64mp-Modify-the-line-length-of-128.patch b/target/linux/bcm27xx/patches-6.1/950-0800-media-i2c-arducam_64mp-Modify-the-line-length-of-128.patch new file mode 100644 index 0000000000..a423b8061b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0800-media-i2c-arducam_64mp-Modify-the-line-length-of-128.patch @@ -0,0 +1,44 @@ +From 9c5a7f04cab6b020389d7c5af155b1ee7f46537d Mon Sep 17 00:00:00 2001 +From: Lee Jackson +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 +--- + 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, diff --git a/target/linux/bcm27xx/patches-6.1/950-0801-media-i2c-arducam_64mp-Add-8000x6000-resolution.patch b/target/linux/bcm27xx/patches-6.1/950-0801-media-i2c-arducam_64mp-Add-8000x6000-resolution.patch new file mode 100644 index 0000000000..475ae634ad --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0801-media-i2c-arducam_64mp-Add-8000x6000-resolution.patch @@ -0,0 +1,105 @@ +From 7b3d0124c5cf462d5be0b0d4e558002b74750911 Mon Sep 17 00:00:00 2001 +From: Lee Jackson +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 +--- + 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, diff --git a/target/linux/bcm27xx/patches-6.1/950-0802-media-i2c-arducam_64mp-Add-PDAF-support.patch b/target/linux/bcm27xx/patches-6.1/950-0802-media-i2c-arducam_64mp-Add-PDAF-support.patch new file mode 100644 index 0000000000..8f96b33baa --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0802-media-i2c-arducam_64mp-Add-PDAF-support.patch @@ -0,0 +1,163 @@ +From b9d2d1862aa5b798cecb87a95d970ad34a4aebc0 Mon Sep 17 00:00:00 2001 +From: Lee Jackson +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 +--- + 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 */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0803-overlays-audremap-Document-CM4-40-41-restriction.patch b/target/linux/bcm27xx/patches-6.1/950-0803-overlays-audremap-Document-CM4-40-41-restriction.patch new file mode 100644 index 0000000000..bf1646322b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0803-overlays-audremap-Document-CM4-40-41-restriction.patch @@ -0,0 +1,24 @@ +From 6f4106f7a7fdcbc03290008713915b4122988c90 Mon Sep 17 00:00:00 2001 +From: James Hughes +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) + diff --git a/target/linux/bcm27xx/patches-6.1/950-0804-fixup-Allow-mac-address-to-be-set-in-smsc95xx.patch b/target/linux/bcm27xx/patches-6.1/950-0804-fixup-Allow-mac-address-to-be-set-in-smsc95xx.patch new file mode 100644 index 0000000000..9265e931fa --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0804-fixup-Allow-mac-address-to-be-set-in-smsc95xx.patch @@ -0,0 +1,120 @@ +From 1d15e6a34222cc8d8eb1050e7a3e276b0348be41 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +[lukas: fix netif_dbg() indentation as well, wordsmith commit message] +Signed-off-by: Lukas Wunner + +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 + +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 +[lukas: leave 2nd function parameter unchanged, wordsmith commit message] +Signed-off-by: Lukas Wunner +--- + 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); diff --git a/target/linux/bcm27xx/patches-6.1/950-0809-cfg80211-ship-debian-certificates-as-hex-files.patch b/target/linux/bcm27xx/patches-6.1/950-0809-cfg80211-ship-debian-certificates-as-hex-files.patch new file mode 100644 index 0000000000..593c95e2a2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0809-cfg80211-ship-debian-certificates-as-hex-files.patch @@ -0,0 +1,1455 @@ +From a2d2745c311baa588fb0fffbe38076294f06b7c0 Mon Sep 17 00:00:00 2001 +From: Nicolai Buchwitz +Date: Wed, 12 Jul 2023 11:30:42 +0200 +Subject: [PATCH] cfg80211: ship debian certificates as hex files + +Loading the regulatory database from the debian files fails with + +"loaded regulatory.db is malformed or signature is missing/invalid" + +due to missing certificates. Add these debian-specific certificates +from upstream to fix this error. See #5536 for details. + +The certificates have been imported as following: + +patch -p1 <<<$( +curl https://salsa.debian.org/kernel-team/linux/-/raw/\ +master/debian/patches/debian/\ +wireless-add-debian-wireless-regdb-certificates.patch +) + +Signed-off-by: Nicolai Buchwitz +--- + net/wireless/certs/debian.hex | 1426 +++++++++++++++++++++++++++++++++ + 1 file changed, 1426 insertions(+) + create mode 100644 net/wireless/certs/debian.hex + +--- /dev/null ++++ b/net/wireless/certs/debian.hex +@@ -0,0 +1,1426 @@ ++0x30, ++0x82, ++0x02, ++0xbd, ++0x30, ++0x82, ++0x01, ++0xa5, ++0x02, ++0x14, ++0x57, ++0x7e, ++0x02, ++0x1c, ++0xb9, ++0x80, ++0xe0, ++0xe8, ++0x20, ++0x82, ++0x1b, ++0xa7, ++0xb5, ++0x4b, ++0x49, ++0x61, ++0xb8, ++0xb4, ++0xfa, ++0xdf, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x0b, ++0x05, ++0x00, ++0x30, ++0x1a, ++0x31, ++0x18, ++0x30, ++0x16, ++0x06, ++0x03, ++0x55, ++0x04, ++0x03, ++0x0c, ++0x0f, ++0x62, ++0x65, ++0x6e, ++0x68, ++0x40, ++0x64, ++0x65, ++0x62, ++0x69, ++0x61, ++0x6e, ++0x2e, ++0x6f, ++0x72, ++0x67, ++0x30, ++0x20, ++0x17, ++0x0d, ++0x32, ++0x30, ++0x30, ++0x31, ++0x33, ++0x30, ++0x31, ++0x33, ++0x32, ++0x36, ++0x31, ++0x33, ++0x5a, ++0x18, ++0x0f, ++0x32, ++0x31, ++0x32, ++0x30, ++0x30, ++0x31, ++0x30, ++0x36, ++0x31, ++0x33, ++0x32, ++0x36, ++0x31, ++0x33, ++0x5a, ++0x30, ++0x1a, ++0x31, ++0x18, ++0x30, ++0x16, ++0x06, ++0x03, ++0x55, ++0x04, ++0x03, ++0x0c, ++0x0f, ++0x62, ++0x65, ++0x6e, ++0x68, ++0x40, ++0x64, ++0x65, ++0x62, ++0x69, ++0x61, ++0x6e, ++0x2e, ++0x6f, ++0x72, ++0x67, ++0x30, ++0x82, ++0x01, ++0x22, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x01, ++0x05, ++0x00, ++0x03, ++0x82, ++0x01, ++0x0f, ++0x00, ++0x30, ++0x82, ++0x01, ++0x0a, ++0x02, ++0x82, ++0x01, ++0x01, ++0x00, ++0x9d, ++0xe1, ++0x77, ++0xa0, ++0x24, ++0xa0, ++0xd5, ++0x79, ++0x65, ++0x3a, ++0x07, ++0x90, ++0xc9, ++0xf6, ++0xa5, ++0xa6, ++0x1f, ++0x84, ++0x1c, ++0x23, ++0x07, ++0x4b, ++0x4f, ++0xa5, ++0x03, ++0xc6, ++0x0f, ++0xf7, ++0x54, ++0xd5, ++0x8b, ++0x7e, ++0x79, ++0x81, ++0x00, ++0xd2, ++0xe9, ++0x3d, ++0xf4, ++0x97, ++0xfe, ++0x84, ++0xcd, ++0x55, ++0xbd, ++0xc9, ++0x8f, ++0x21, ++0x57, ++0x88, ++0x06, ++0x39, ++0x90, ++0x66, ++0x41, ++0x26, ++0x79, ++0x2c, ++0xca, ++0x3f, ++0x95, ++0x87, ++0x01, ++0x11, ++0x2f, ++0x2f, ++0xb0, ++0xe1, ++0x0b, ++0x43, ++0xfc, ++0x5f, ++0x2f, ++0x4f, ++0x67, ++0x04, ++0xdb, ++0x4d, ++0xb7, ++0x72, ++0x4d, ++0xd1, ++0xc5, ++0x76, ++0x73, ++0x4d, ++0x91, ++0x69, ++0xb0, ++0x71, ++0x17, ++0x36, ++0xea, ++0xab, ++0x0a, ++0x3a, ++0xcd, ++0x95, ++0x9b, ++0x76, ++0x1b, ++0x8e, ++0x21, ++0x17, ++0x8f, ++0xc5, ++0x02, ++0xbf, ++0x24, ++0xc7, ++0xc0, ++0x40, ++0xb1, ++0x3b, ++0xc4, ++0x80, ++0x7c, ++0x71, ++0xa5, ++0x51, ++0xdc, ++0xf7, ++0x3a, ++0x58, ++0x7f, ++0xb1, ++0x07, ++0x81, ++0x8a, ++0x10, ++0xd1, ++0xf6, ++0x93, ++0x17, ++0x71, ++0xe0, ++0xfa, ++0x51, ++0x79, ++0x15, ++0xd4, ++0xd7, ++0x8f, ++0xad, ++0xbd, ++0x6f, ++0x38, ++0xe1, ++0x26, ++0x7d, ++0xbc, ++0xf0, ++0x3e, ++0x80, ++0x89, ++0xb4, ++0xec, ++0x8e, ++0x69, ++0x90, ++0xdb, ++0x97, ++0x8a, ++0xf0, ++0x23, ++0x23, ++0x83, ++0x82, ++0x3b, ++0x6a, ++0xb1, ++0xac, ++0xeb, ++0xe7, ++0x99, ++0x74, ++0x2a, ++0x35, ++0x8e, ++0xa9, ++0x64, ++0xfd, ++0x46, ++0x9e, ++0xe8, ++0xe5, ++0x48, ++0x61, ++0x31, ++0x6e, ++0xe6, ++0xfc, ++0x19, ++0x18, ++0x54, ++0xc3, ++0x1b, ++0x4f, ++0xd6, ++0x00, ++0x44, ++0x87, ++0x1c, ++0x37, ++0x45, ++0xea, ++0xf5, ++0xc9, ++0xcb, ++0x0f, ++0x0c, ++0x55, ++0xec, ++0xcf, ++0x6a, ++0xc2, ++0x45, ++0x26, ++0x23, ++0xa2, ++0x31, ++0x52, ++0x4d, ++0xee, ++0x21, ++0x7d, ++0xfd, ++0x58, ++0x72, ++0xc2, ++0x28, ++0xc5, ++0x8e, ++0xa9, ++0xd0, ++0xee, ++0x01, ++0x77, ++0x08, ++0xa5, ++0xf0, ++0x22, ++0x2b, ++0x47, ++0x79, ++0x2b, ++0xcf, ++0x9a, ++0x46, ++0xb5, ++0x8f, ++0xfd, ++0x64, ++0xa2, ++0xb5, ++0xed, ++0x02, ++0x03, ++0x01, ++0x00, ++0x01, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x0b, ++0x05, ++0x00, ++0x03, ++0x82, ++0x01, ++0x01, ++0x00, ++0x20, ++0x44, ++0xfe, ++0xa9, ++0x9e, ++0xdd, ++0x9b, ++0xea, ++0xce, ++0x25, ++0x75, ++0x08, ++0xf0, ++0x2b, ++0x53, ++0xf7, ++0x5a, ++0x36, ++0x1c, ++0x4a, ++0x23, ++0x7f, ++0xd0, ++0x41, ++0x3c, ++0x12, ++0x2b, ++0xb9, ++0x80, ++0x4e, ++0x8a, ++0x15, ++0x5d, ++0x1f, ++0x40, ++0xa7, ++0x26, ++0x28, ++0x32, ++0xc3, ++0x5b, ++0x06, ++0x28, ++0x2d, ++0x3d, ++0x08, ++0x09, ++0x1e, ++0x01, ++0xe9, ++0x67, ++0xe3, ++0x33, ++0xe6, ++0x15, ++0x45, ++0x39, ++0xee, ++0x17, ++0x83, ++0xdb, ++0x42, ++0xff, ++0x7f, ++0x35, ++0xf4, ++0xac, ++0x16, ++0xdb, ++0xba, ++0xb8, ++0x1a, ++0x20, ++0x21, ++0x41, ++0xff, ++0xf3, ++0x92, ++0xff, ++0x65, ++0x6e, ++0x29, ++0x16, ++0xd0, ++0xbf, ++0x8d, ++0xdf, ++0x48, ++0x2c, ++0x73, ++0x36, ++0x7f, ++0x22, ++0xe6, ++0xee, ++0x78, ++0xb4, ++0x63, ++0x83, ++0x0e, ++0x39, ++0xeb, ++0xaf, ++0x10, ++0x2a, ++0x90, ++0xd3, ++0xfc, ++0xe6, ++0xc3, ++0x8f, ++0x97, ++0x5b, ++0x76, ++0xbf, ++0x9b, ++0xf5, ++0x98, ++0xd2, ++0x53, ++0x06, ++0x8b, ++0xf8, ++0xa4, ++0x04, ++0x9b, ++0x1b, ++0x62, ++0x6a, ++0x9d, ++0xac, ++0xe6, ++0x4b, ++0x0d, ++0xc9, ++0xd7, ++0x56, ++0x63, ++0x15, ++0x01, ++0x38, ++0x8c, ++0xbe, ++0xf1, ++0x44, ++0xc4, ++0x38, ++0x27, ++0xe0, ++0xcf, ++0x72, ++0xd6, ++0x3d, ++0xe4, ++0xf7, ++0x4b, ++0x3b, ++0xd2, ++0xb1, ++0x0c, ++0xd5, ++0x83, ++0x6d, ++0x1e, ++0x10, ++0x04, ++0x69, ++0x29, ++0x88, ++0x69, ++0xe0, ++0x7d, ++0xd7, ++0xdb, ++0xb4, ++0x59, ++0x72, ++0x8d, ++0x9d, ++0x3c, ++0x43, ++0xaf, ++0xc6, ++0x7d, ++0xb7, ++0x21, ++0x15, ++0x52, ++0x8a, ++0xe9, ++0x9b, ++0x6b, ++0x2e, ++0xe8, ++0x27, ++0x3c, ++0x3f, ++0x2d, ++0x84, ++0xfb, ++0x9a, ++0x22, ++0x0a, ++0x9f, ++0x6a, ++0x25, ++0xe6, ++0x39, ++0xe4, ++0x74, ++0x73, ++0xb6, ++0x2a, ++0x70, ++0xaa, ++0x1d, ++0xcb, ++0xcc, ++0xd4, ++0xa0, ++0x1b, ++0x26, ++0x71, ++0x63, ++0x04, ++0xc5, ++0x12, ++0x21, ++0x48, ++0xba, ++0x92, ++0x27, ++0x06, ++0xa8, ++0x3e, ++0x6d, ++0xa1, ++0x43, ++0xa5, ++0xd2, ++0x2a, ++0xf7, ++0xca, ++0xc4, ++0x26, ++0xe8, ++0x5b, ++0x1f, ++0xe4, ++0xdc, ++0x89, ++0xdc, ++0x1f, ++0x04, ++0x79, ++0x3f, ++0x30, ++0x82, ++0x02, ++0xcd, ++0x30, ++0x82, ++0x01, ++0xb5, ++0x02, ++0x14, ++0x3a, ++0xbb, ++0xc6, ++0xec, ++0x14, ++0x6e, ++0x09, ++0xd1, ++0xb6, ++0x01, ++0x6a, ++0xb9, ++0xd6, ++0xcf, ++0x71, ++0xdd, ++0x23, ++0x3f, ++0x03, ++0x28, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x0b, ++0x05, ++0x00, ++0x30, ++0x22, ++0x31, ++0x20, ++0x30, ++0x1e, ++0x06, ++0x03, ++0x55, ++0x04, ++0x03, ++0x0c, ++0x17, ++0x72, ++0x6f, ++0x6d, ++0x61, ++0x69, ++0x6e, ++0x2e, ++0x70, ++0x65, ++0x72, ++0x69, ++0x65, ++0x72, ++0x40, ++0x67, ++0x6d, ++0x61, ++0x69, ++0x6c, ++0x2e, ++0x63, ++0x6f, ++0x6d, ++0x30, ++0x20, ++0x17, ++0x0d, ++0x32, ++0x30, ++0x30, ++0x32, ++0x32, ++0x34, ++0x31, ++0x39, ++0x30, ++0x31, ++0x34, ++0x34, ++0x5a, ++0x18, ++0x0f, ++0x32, ++0x31, ++0x32, ++0x30, ++0x30, ++0x31, ++0x33, ++0x31, ++0x31, ++0x39, ++0x30, ++0x31, ++0x34, ++0x34, ++0x5a, ++0x30, ++0x22, ++0x31, ++0x20, ++0x30, ++0x1e, ++0x06, ++0x03, ++0x55, ++0x04, ++0x03, ++0x0c, ++0x17, ++0x72, ++0x6f, ++0x6d, ++0x61, ++0x69, ++0x6e, ++0x2e, ++0x70, ++0x65, ++0x72, ++0x69, ++0x65, ++0x72, ++0x40, ++0x67, ++0x6d, ++0x61, ++0x69, ++0x6c, ++0x2e, ++0x63, ++0x6f, ++0x6d, ++0x30, ++0x82, ++0x01, ++0x22, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x01, ++0x05, ++0x00, ++0x03, ++0x82, ++0x01, ++0x0f, ++0x00, ++0x30, ++0x82, ++0x01, ++0x0a, ++0x02, ++0x82, ++0x01, ++0x01, ++0x00, ++0xf0, ++0xb8, ++0x4f, ++0x3f, ++0x70, ++0x78, ++0xf8, ++0x74, ++0x45, ++0xa2, ++0x28, ++0xaf, ++0x04, ++0x75, ++0x04, ++0xa3, ++0xf3, ++0xa7, ++0xc7, ++0x04, ++0xac, ++0xb6, ++0xe1, ++0xfc, ++0xe1, ++0xc0, ++0x3d, ++0xe0, ++0x26, ++0x90, ++0x8a, ++0x45, ++0x60, ++0xc4, ++0x75, ++0xf3, ++0x1a, ++0x33, ++0x37, ++0x56, ++0x7d, ++0x30, ++0x07, ++0x75, ++0x0e, ++0xa6, ++0x79, ++0x06, ++0x95, ++0x9d, ++0x17, ++0x3c, ++0x09, ++0xa9, ++0x7f, ++0xab, ++0x95, ++0x5d, ++0xed, ++0xe0, ++0x75, ++0x26, ++0x2f, ++0x65, ++0x65, ++0xcd, ++0x61, ++0xb1, ++0x33, ++0x27, ++0x67, ++0x41, ++0xa1, ++0x01, ++0x13, ++0xe9, ++0x13, ++0x6a, ++0x6d, ++0x4e, ++0x98, ++0xe1, ++0x9e, ++0x7b, ++0x0b, ++0x5b, ++0x44, ++0xef, ++0x68, ++0x5a, ++0x6f, ++0x7d, ++0x97, ++0xa1, ++0x33, ++0x22, ++0x97, ++0x12, ++0x21, ++0x09, ++0x8f, ++0x90, ++0xe0, ++0x25, ++0x94, ++0xdd, ++0x8a, ++0x3a, ++0xf7, ++0x4a, ++0x60, ++0x04, ++0x26, ++0x6d, ++0x00, ++0x82, ++0xe4, ++0xcf, ++0x64, ++0x1c, ++0x79, ++0x15, ++0x24, ++0xf2, ++0x42, ++0x86, ++0xf5, ++0x10, ++0x86, ++0xac, ++0x20, ++0x88, ++0x90, ++0x87, ++0xdf, ++0x8c, ++0x37, ++0x7c, ++0xbf, ++0x35, ++0xd5, ++0x6f, ++0x9f, ++0x77, ++0xc3, ++0xcd, ++0x69, ++0x25, ++0x06, ++0xc2, ++0x65, ++0x51, ++0x71, ++0x89, ++0x7f, ++0x6e, ++0x4d, ++0xe5, ++0xd5, ++0x8a, ++0x36, ++0x1a, ++0xad, ++0xc1, ++0x18, ++0xd6, ++0x14, ++0x42, ++0x87, ++0xf0, ++0x93, ++0x83, ++0xf1, ++0x99, ++0x74, ++0xc4, ++0x13, ++0xaa, ++0x3b, ++0x66, ++0x85, ++0x6f, ++0xe0, ++0xbc, ++0x5f, ++0xb6, ++0x40, ++0xa6, ++0x41, ++0x06, ++0x0a, ++0xba, ++0x0e, ++0xe9, ++0x32, ++0x44, ++0x10, ++0x39, ++0x53, ++0xcd, ++0xbf, ++0xf3, ++0xd3, ++0x26, ++0xf6, ++0xb6, ++0x2b, ++0x40, ++0x2e, ++0xb9, ++0x88, ++0xc1, ++0xf4, ++0xe3, ++0xa0, ++0x28, ++0x77, ++0x4f, ++0xba, ++0xa8, ++0xca, ++0x9c, ++0x05, ++0xba, ++0x88, ++0x96, ++0x99, ++0x54, ++0x89, ++0xa2, ++0x8d, ++0xf3, ++0x73, ++0xa1, ++0x8c, ++0x4a, ++0xa8, ++0x71, ++0xee, ++0x2e, ++0xd2, ++0x83, ++0x14, ++0x48, ++0xbd, ++0x98, ++0xc6, ++0xce, ++0xdc, ++0xa8, ++0xa3, ++0x97, ++0x2e, ++0x40, ++0x16, ++0x2f, ++0x02, ++0x03, ++0x01, ++0x00, ++0x01, ++0x30, ++0x0d, ++0x06, ++0x09, ++0x2a, ++0x86, ++0x48, ++0x86, ++0xf7, ++0x0d, ++0x01, ++0x01, ++0x0b, ++0x05, ++0x00, ++0x03, ++0x82, ++0x01, ++0x01, ++0x00, ++0x76, ++0x5d, ++0x03, ++0x3d, ++0xb6, ++0x96, ++0x00, ++0x1b, ++0x6e, ++0x0c, ++0xdd, ++0xbb, ++0xc8, ++0xdf, ++0xbc, ++0xeb, ++0x6c, ++0x01, ++0x40, ++0x1a, ++0x2b, ++0x07, ++0x60, ++0xa1, ++0x1a, ++0xe1, ++0x43, ++0x57, ++0xfa, ++0xbe, ++0xde, ++0xbb, ++0x8f, ++0x73, ++0xf3, ++0x92, ++0xa2, ++0xaa, ++0x83, ++0x01, ++0xc1, ++0x17, ++0xe4, ++0x9d, ++0x09, ++0x41, ++0xe0, ++0x32, ++0x33, ++0x97, ++0x4b, ++0xf2, ++0xdc, ++0x0f, ++0x8b, ++0xa8, ++0xb8, ++0x5a, ++0x04, ++0x86, ++0xf6, ++0x71, ++0xa1, ++0x97, ++0xd0, ++0x54, ++0x56, ++0x10, ++0x8e, ++0x54, ++0x99, ++0x0d, ++0x2a, ++0xa9, ++0xaf, ++0x1b, ++0x55, ++0x59, ++0x06, ++0x2b, ++0xa4, ++0x5f, ++0xb1, ++0x54, ++0xa6, ++0xec, ++0xc7, ++0xd6, ++0x43, ++0xee, ++0x86, ++0x2c, ++0x9b, ++0x18, ++0x9d, ++0x8f, ++0x00, ++0x82, ++0xc1, ++0x88, ++0x61, ++0x16, ++0x85, ++0x3c, ++0x17, ++0x56, ++0xfe, ++0x6a, ++0xa0, ++0x7a, ++0x68, ++0xc5, ++0x7b, ++0x3d, ++0x3c, ++0xb6, ++0x13, ++0x18, ++0x99, ++0x6d, ++0x74, ++0x65, ++0x13, ++0x67, ++0xb7, ++0xfc, ++0x5a, ++0x44, ++0x48, ++0x72, ++0xa0, ++0x73, ++0xb8, ++0xff, ++0x02, ++0x9d, ++0x7c, ++0x5b, ++0xf9, ++0x7c, ++0x75, ++0x0a, ++0x3c, ++0x81, ++0x80, ++0x3c, ++0x41, ++0xf2, ++0xd5, ++0xfa, ++0x3d, ++0x1f, ++0xe3, ++0xda, ++0x8c, ++0xa5, ++0x17, ++0x1f, ++0x53, ++0x1a, ++0x75, ++0xad, ++0x4e, ++0x11, ++0x1c, ++0x07, ++0xec, ++0x0a, ++0x69, ++0xfd, ++0x33, ++0xfa, ++0x32, ++0x7e, ++0x66, ++0xf5, ++0x29, ++0xe8, ++0x4d, ++0x8a, ++0xfa, ++0x0d, ++0x4b, ++0x68, ++0xc3, ++0x95, ++0x11, ++0xba, ++0x6f, ++0x1e, ++0x07, ++0x8c, ++0x85, ++0xc7, ++0xc7, ++0xc9, ++0xc1, ++0x30, ++0xa3, ++0x70, ++0xb0, ++0xa1, ++0xe0, ++0xd5, ++0x85, ++0x15, ++0x94, ++0x77, ++0xc1, ++0x1c, ++0x91, ++0xf1, ++0x5f, ++0x50, ++0xcd, ++0x2c, ++0x57, ++0x4b, ++0x22, ++0x4f, ++0xee, ++0x95, ++0xd7, ++0xa7, ++0xa4, ++0x59, ++0x62, ++0xae, ++0xb9, ++0xbf, ++0xd7, ++0x63, ++0x5a, ++0x04, ++0xfc, ++0x24, ++0x11, ++0xae, ++0x34, ++0x4b, ++0xf4, ++0x0c, ++0x9f, ++0x0b, ++0x59, ++0x7d, ++0x27, ++0x39, ++0x54, ++0x69, ++0x4f, ++0xfd, ++0x6e, ++0x44, ++0x9f, ++0x21, diff --git a/target/linux/bcm27xx/patches-6.1/950-0810-fixup-Add-support-for-all-the-downstream-rpi-sound-c.patch b/target/linux/bcm27xx/patches-6.1/950-0810-fixup-Add-support-for-all-the-downstream-rpi-sound-c.patch new file mode 100644 index 0000000000..87097d2bbf --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0810-fixup-Add-support-for-all-the-downstream-rpi-sound-c.patch @@ -0,0 +1,329 @@ +From 3ece03b1575b0c3a0989e372aaaa4557ae74dc89 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* 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 + #include + +-/* 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. + diff --git a/target/linux/bcm27xx/patches-6.1/950-0815-fixup-drm-tc358762-Set-the-pre_enable_upstream_first.patch b/target/linux/bcm27xx/patches-6.1/950-0815-fixup-drm-tc358762-Set-the-pre_enable_upstream_first.patch new file mode 100644 index 0000000000..22bca6c7f4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0815-fixup-drm-tc358762-Set-the-pre_enable_upstream_first.patch @@ -0,0 +1,21 @@ +From 2addf7045f2b4866ab819f48e4d32f5734a32134 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +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); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0816-rpi-sound-cards-Fix-Codec-Zero-rate-switching.patch b/target/linux/bcm27xx/patches-6.1/950-0816-rpi-sound-cards-Fix-Codec-Zero-rate-switching.patch new file mode 100644 index 0000000000..82a3c9ea5b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0816-rpi-sound-cards-Fix-Codec-Zero-rate-switching.patch @@ -0,0 +1,48 @@ +From b84b8a9ad2046a855a7044b6368def01ddd5de6e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 = { diff --git a/target/linux/bcm27xx/patches-6.1/950-0818-overlays-Add-trickle-voltage-mv-parameter-to-RTCs.patch b/target/linux/bcm27xx/patches-6.1/950-0818-overlays-Add-trickle-voltage-mv-parameter-to-RTCs.patch new file mode 100644 index 0000000000..0539b19cf5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0818-overlays-Add-trickle-voltage-mv-parameter-to-RTCs.patch @@ -0,0 +1,68 @@ +From 31822340129e3c4030500d7f30ce4d19bbf9dd40 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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?", diff --git a/target/linux/bcm27xx/patches-6.1/950-0819-drivers-media-imx296-Add-standby-delay-during-probe.patch b/target/linux/bcm27xx/patches-6.1/950-0819-drivers-media-imx296-Add-standby-delay-during-probe.patch new file mode 100644 index 0000000000..f10c0f03b5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0819-drivers-media-imx296-Add-standby-delay-during-probe.patch @@ -0,0 +1,25 @@ +From 5fb3b300557d6a6902e7321f42fdabb8c09eef54 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +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 +--- + 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", diff --git a/target/linux/bcm27xx/patches-6.1/950-0820-overlays-Add-bmp380-to-i2c-sensor-overlay.patch b/target/linux/bcm27xx/patches-6.1/950-0820-overlays-Add-bmp380-to-i2c-sensor-overlay.patch new file mode 100644 index 0000000000..535511eb93 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0820-overlays-Add-bmp380-to-i2c-sensor-overlay.patch @@ -0,0 +1,78 @@ +From e1016d61e3dcb058932e8ec5072f2c4bbb05fcb7 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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,= + 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"; diff --git a/target/linux/bcm27xx/patches-6.1/950-0821-can-isotp-add-module-parameter-for-maximum-pdu-size.patch b/target/linux/bcm27xx/patches-6.1/950-0821-can-isotp-add-module-parameter-for-maximum-pdu-size.patch new file mode 100644 index 0000000000..d5cce9a433 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0821-can-isotp-add-module-parameter-for-maximum-pdu-size.patch @@ -0,0 +1,162 @@ +From 4b729a06b15fc5ee3694dcc62346dcb718ae4290 Mon Sep 17 00:00:00 2001 +From: Oliver Hartkopp +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 +Link: https://lore.kernel.org/all/20230326115911.15094-1-socketcan@hartkopp.net +Signed-off-by: Marc Kleine-Budde +--- + 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) diff --git a/target/linux/bcm27xx/patches-6.1/950-0822-drivers-media-imx296-Updated-imx296-driver-for-exter.patch b/target/linux/bcm27xx/patches-6.1/950-0822-drivers-media-imx296-Updated-imx296-driver-for-exter.patch new file mode 100644 index 0000000000..ee4079cd64 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0822-drivers-media-imx296-Updated-imx296-driver-for-exter.patch @@ -0,0 +1,40 @@ +From e1b03ea9e84320e6bf36a1486abaebbceadd7fc7 Mon Sep 17 00:00:00 2001 +From: Ben Benson +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 +--- + 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 + #include + ++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 */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0823-media-dt-bindings-imx258-Fix-alternate-compatible-st.patch b/target/linux/bcm27xx/patches-6.1/950-0823-media-dt-bindings-imx258-Fix-alternate-compatible-st.patch new file mode 100644 index 0000000000..f45b68f154 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0823-media-dt-bindings-imx258-Fix-alternate-compatible-st.patch @@ -0,0 +1,26 @@ +From 74bc238e86e62109c74d8f229dc105bf3818b4a7 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0825-char-broadcom-vc_mem-Fix-preprocessor-conditional.patch b/target/linux/bcm27xx/patches-6.1/950-0825-char-broadcom-vc_mem-Fix-preprocessor-conditional.patch new file mode 100644 index 0000000000..43283784dd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0825-char-broadcom-vc_mem-Fix-preprocessor-conditional.patch @@ -0,0 +1,21 @@ +From 282819aead0166af415b780241dc2def4caee7f4 Mon Sep 17 00:00:00 2001 +From: Alexander Winkowski +Date: Mon, 3 Jul 2023 18:12:01 +0000 +Subject: [PATCH] char: broadcom: vc_mem: Fix preprocessor conditional + +Signed-off-by: Alexander Winkowski +--- + 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); diff --git a/target/linux/bcm27xx/patches-6.1/950-0826-drivers-dwc_otg-Fix-fallthrough-warnings.patch b/target/linux/bcm27xx/patches-6.1/950-0826-drivers-dwc_otg-Fix-fallthrough-warnings.patch new file mode 100644 index 0000000000..fe74c75e07 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0826-drivers-dwc_otg-Fix-fallthrough-warnings.patch @@ -0,0 +1,32 @@ +From ec61075a786c455444a1d5df338a41bacfce0bb1 Mon Sep 17 00:00:00 2001 +From: Alexander Winkowski +Date: Mon, 3 Jul 2023 18:23:02 +0000 +Subject: [PATCH] drivers: dwc_otg: Fix fallthrough warnings + +Signed-off-by: Alexander Winkowski +--- + 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: diff --git a/target/linux/bcm27xx/patches-6.1/950-0827-vc04_services-vc-sm-cma-Switch-one-bit-bitfields-to-.patch b/target/linux/bcm27xx/patches-6.1/950-0827-vc04_services-vc-sm-cma-Switch-one-bit-bitfields-to-.patch new file mode 100644 index 0000000000..edd117c9b5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0827-vc04_services-vc-sm-cma-Switch-one-bit-bitfields-to-.patch @@ -0,0 +1,61 @@ +From 2dd2f36d10961e3819ff0525ae2567e601973826 Mon Sep 17 00:00:00 2001 +From: Alexander Winkowski +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 +--- + 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 */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0828-media-i2c-ov2311-Fix-uninitialized-variable-usage.patch b/target/linux/bcm27xx/patches-6.1/950-0828-media-i2c-ov2311-Fix-uninitialized-variable-usage.patch new file mode 100644 index 0000000000..d6fd3a9f92 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0828-media-i2c-ov2311-Fix-uninitialized-variable-usage.patch @@ -0,0 +1,21 @@ +From 3333d45347d313ea589b8b8da1193d342060a946 Mon Sep 17 00:00:00 2001 +From: Alexander Winkowski +Date: Mon, 3 Jul 2023 18:36:45 +0000 +Subject: [PATCH] media: i2c: ov2311: Fix uninitialized variable usage + +Signed-off-by: Alexander Winkowski +--- + 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, diff --git a/target/linux/bcm27xx/patches-6.1/950-0830-drm-panel-Fix-default-values-for-Waveshare-7.9-inch-.patch b/target/linux/bcm27xx/patches-6.1/950-0830-drm-panel-Fix-default-values-for-Waveshare-7.9-inch-.patch new file mode 100644 index 0000000000..035b5b0049 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0830-drm-panel-Fix-default-values-for-Waveshare-7.9-inch-.patch @@ -0,0 +1,29 @@ +From e89e7655a197d28df49da2be7e2003436cf52197 Mon Sep 17 00:00:00 2001 +From: Ignacio Larrain +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", diff --git a/target/linux/bcm27xx/patches-6.1/950-0831-dtoverlays-Add-i2c-bus-overrides-to-edt-ft5406-overl.patch b/target/linux/bcm27xx/patches-6.1/950-0831-dtoverlays-Add-i2c-bus-overrides-to-edt-ft5406-overl.patch new file mode 100644 index 0000000000..cf703b0029 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0831-dtoverlays-Add-i2c-bus-overrides-to-edt-ft5406-overl.patch @@ -0,0 +1,102 @@ +From 3fa2fbb7f6e60b85086e454403c5eab1af63b1aa Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +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 +--- + 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,= +@@ -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"; diff --git a/target/linux/bcm27xx/patches-6.1/950-0832-dtoverlays-Fix-README-text-for-i2c-fan.patch b/target/linux/bcm27xx/patches-6.1/950-0832-dtoverlays-Fix-README-text-for-i2c-fan.patch new file mode 100644 index 0000000000..23953c9636 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0832-dtoverlays-Fix-README-text-for-i2c-fan.patch @@ -0,0 +1,25 @@ +From 9d9586dc0c0deecb90675bd70862fe262f7376ab Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 14 Jun 2023 14:25:21 +0100 +Subject: [PATCH] dtoverlays: Fix README text for i2c-fan + +Signed-off-by: Dave Stevenson +--- + 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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0833-drivers-irqchip-irq-bcm2835-Concurrency-fix.patch b/target/linux/bcm27xx/patches-6.1/950-0833-drivers-irqchip-irq-bcm2835-Concurrency-fix.patch new file mode 100644 index 0000000000..48e2fcdc74 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0833-drivers-irqchip-irq-bcm2835-Concurrency-fix.patch @@ -0,0 +1,50 @@ +From e804bd1843236a63815e9acfb1a38ebf9a28ef5b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-0835-dtoverlays-Add-drm-option-to-piscreen-overlay.patch b/target/linux/bcm27xx/patches-6.1/950-0835-dtoverlays-Add-drm-option-to-piscreen-overlay.patch new file mode 100644 index 0000000000..10b1f15d2c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0835-dtoverlays-Add-drm-option-to-piscreen-overlay.patch @@ -0,0 +1,58 @@ +From 5e54398e1b61335883dff1be46a6c8b3ca973926 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +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 +--- + 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 ++ + / { + 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=",; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0836-drm-ili9486-Resolve-clash-in-spi_device_id-names.patch b/target/linux/bcm27xx/patches-6.1/950-0836-drm-ili9486-Resolve-clash-in-spi_device_id-names.patch new file mode 100644 index 0000000000..0bce9f9e78 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0836-drm-ili9486-Resolve-clash-in-spi_device_id-names.patch @@ -0,0 +1,36 @@ +From f59fe2d1bd056af117eb512bb0e9210a943c6d47 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +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 +--- + 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); diff --git a/target/linux/bcm27xx/patches-6.1/950-0837-input-ads7846-Add-missing-spi_device_id-strings.patch b/target/linux/bcm27xx/patches-6.1/950-0837-input-ads7846-Add-missing-spi_device_id-strings.patch new file mode 100644 index 0000000000..71f1063986 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0837-input-ads7846-Add-missing-spi_device_id-strings.patch @@ -0,0 +1,50 @@ +From 50c5a8558f4aaa54a3c4f5a8c2b6053f641d94eb Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +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 +--- + 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, + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0838-staging-bcm2835-codec-Downgrade-the-level-for-a-debu.patch b/target/linux/bcm27xx/patches-6.1/950-0838-staging-bcm2835-codec-Downgrade-the-level-for-a-debu.patch new file mode 100644 index 0000000000..5af23821a8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0838-staging-bcm2835-codec-Downgrade-the-level-for-a-debu.patch @@ -0,0 +1,27 @@ +From 65742d7116e89b08858fcd7d67bd521ee19ee837 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +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 +--- + .../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; diff --git a/target/linux/bcm27xx/patches-6.1/950-0840-gpio-fsm-Sort-functions-into-a-more-logical-order.patch b/target/linux/bcm27xx/patches-6.1/950-0840-gpio-fsm-Sort-functions-into-a-more-logical-order.patch new file mode 100644 index 0000000000..873077f51c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0840-gpio-fsm-Sort-functions-into-a-more-logical-order.patch @@ -0,0 +1,286 @@ +From cee471c3ada3215d6dfc53fb0f1b97548444dea7 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 : ""); +- +- 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 : ""); ++ ++ 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// diff --git a/target/linux/bcm27xx/patches-6.1/950-0841-gpio_fsm-Rework-the-atomic-vs-non-atomic-split.patch b/target/linux/bcm27xx/patches-6.1/950-0841-gpio_fsm-Rework-the-atomic-vs-non-atomic-split.patch new file mode 100644 index 0000000000..ae3c019e25 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0841-gpio_fsm-Rework-the-atomic-vs-non-atomic-split.patch @@ -0,0 +1,192 @@ +From f0061ffc98c6e027c5774e2a24ceadcfee4167ea Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 : ""); + ++ 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 : ""); ++ + 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); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0842-f2fs-fix-to-avoid-NULL-pointer-dereference-in-f2fs_i.patch b/target/linux/bcm27xx/patches-6.1/950-0842-f2fs-fix-to-avoid-NULL-pointer-dereference-in-f2fs_i.patch new file mode 100644 index 0000000000..33150551b3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0842-f2fs-fix-to-avoid-NULL-pointer-dereference-in-f2fs_i.patch @@ -0,0 +1,63 @@ +From bf9fb25f3265605572f04e5c7836bb83ee345236 Mon Sep 17 00:00:00 2001 +From: Chao Yu +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 +Signed-off-by: Jaegeuk Kim +--- + 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) diff --git a/target/linux/bcm27xx/patches-6.1/950-0177-hwrng-iproc-rng200-Add-BCM2838-support.patch b/target/linux/bcm27xx/patches-6.1/950-0846-hwrng-iproc-rng200-Add-BCM2838-support.patch similarity index 88% rename from target/linux/bcm27xx/patches-6.1/950-0177-hwrng-iproc-rng200-Add-BCM2838-support.patch rename to target/linux/bcm27xx/patches-6.1/950-0846-hwrng-iproc-rng200-Add-BCM2838-support.patch index 9a36dd1bcd..a179d930df 100644 --- a/target/linux/bcm27xx/patches-6.1/950-0177-hwrng-iproc-rng200-Add-BCM2838-support.patch +++ b/target/linux/bcm27xx/patches-6.1/950-0846-hwrng-iproc-rng200-Add-BCM2838-support.patch @@ -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 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 --- 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 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 + #include + #include ++#include + #include + #include + +@@ -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 #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 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 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); diff --git a/target/linux/bcm27xx/patches-6.1/950-0847-PCI-brcmstb-Wait-for-100ms-following-PERST-deassert.patch b/target/linux/bcm27xx/patches-6.1/950-0847-PCI-brcmstb-Wait-for-100ms-following-PERST-deassert.patch new file mode 100644 index 0000000000..b08676253e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0847-PCI-brcmstb-Wait-for-100ms-following-PERST-deassert.patch @@ -0,0 +1,39 @@ +From 6f634d7efb8876e5953c30c0a613aaa5f575fe05 Mon Sep 17 00:00:00 2001 +From: Jim Quinlan +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 +Signed-off-by: Lorenzo Pieralisi +Acked-by: Florian Fainelli +--- + 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); diff --git a/target/linux/bcm27xx/patches-6.1/950-0850-overlays-Add-a-sample-hat_map.patch b/target/linux/bcm27xx/patches-6.1/950-0850-overlays-Add-a-sample-hat_map.patch new file mode 100644 index 0000000000..19550b6fd5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0850-overlays-Add-a-sample-hat_map.patch @@ -0,0 +1,47 @@ +From cc08810f89e52337a99cc6ae5f53f08588357c5f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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"; ++ }; ++}; diff --git a/target/linux/bcm27xx/patches-6.1/950-0851-Revert-usb-phy-generic-Get-the-vbus-supply.patch b/target/linux/bcm27xx/patches-6.1/950-0851-Revert-usb-phy-generic-Get-the-vbus-supply.patch new file mode 100644 index 0000000000..aaf49e6a7c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0851-Revert-usb-phy-generic-Get-the-vbus-supply.patch @@ -0,0 +1,26 @@ +From 406e7dc82be6ce1b81c88b418640daeef6c2be42 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +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"; diff --git a/target/linux/bcm27xx/patches-6.1/950-0853-dts-2712-Update-for-device-tree.patch b/target/linux/bcm27xx/patches-6.1/950-0853-dts-2712-Update-for-device-tree.patch new file mode 100644 index 0000000000..6a5c40ef4e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0853-dts-2712-Update-for-device-tree.patch @@ -0,0 +1,7672 @@ +From 1196bf1a7736ff0ab79f5012fa84082e298031a7 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Tue, 19 Sep 2023 15:55:00 +0100 +Subject: [PATCH] dts: 2712: Update for device tree + +dtoverlays: Fix up edt5406 entries to match with vc4-kms-dsi-7inch + +vc4-kms-dsi-7inch expects the touch fragment to be named ts_i2c_frag, +but edt5406 didn't do this. + +Fixes: 736d601fb38c ("dts: 2712: Update for device tree") + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/Makefile | 3 +- + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 3 + + arch/arm/boot/dts/bcm2708-rpi-b-rev1.dts | 3 + + arch/arm/boot/dts/bcm2708-rpi-b.dts | 3 + + arch/arm/boot/dts/bcm2708-rpi-cm.dts | 3 + + arch/arm/boot/dts/bcm2708-rpi-zero-w.dts | 1 + + arch/arm/boot/dts/bcm2708-rpi-zero.dts | 1 + + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 3 + + arch/arm/boot/dts/bcm2709-rpi-cm2.dts | 3 + + arch/arm/boot/dts/bcm270x-rpi.dtsi | 3 + + arch/arm/boot/dts/bcm2710-rpi-2-b.dts | 3 + + arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts | 3 + + arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 3 + + arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 3 + + arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts | 3 + + arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 3 + + arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 3 + + arch/arm/boot/dts/bcm2711-rpi-cm4s.dts | 3 + + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 824 +++++++++++ + arch/arm/boot/dts/bcm2712-rpi.dtsi | 281 ++++ + arch/arm/boot/dts/bcm2712.dtsi | 1287 +++++++++++++++++ + arch/arm/boot/dts/overlays/Makefile | 23 + + arch/arm/boot/dts/overlays/README | 360 ++++- + .../dts/overlays/adau1977-adc-overlay.dts | 4 +- + .../dts/overlays/adau7002-simple-overlay.dts | 4 +- + .../overlays/akkordion-iqdacplus-overlay.dts | 4 +- + .../allo-boss-dac-pcm512x-audio-overlay.dts | 10 +- + .../overlays/allo-boss2-dac-audio-overlay.dts | 2 +- + .../dts/overlays/allo-digione-overlay.dts | 4 +- + .../allo-katana-dac-audio-overlay.dts | 2 +- + .../allo-piano-dac-pcm512x-audio-overlay.dts | 4 +- + ...o-piano-dac-plus-pcm512x-audio-overlay.dts | 4 +- + .../boot/dts/overlays/applepi-dac-overlay.dts | 4 +- + .../dts/overlays/arducam-64mp-overlay.dts | 2 +- + .../overlays/arducam-pivariety-overlay.dts | 2 +- + .../overlays/audioinjector-addons-overlay.dts | 4 +- + .../audioinjector-bare-i2s-overlay.dts | 6 +- + ...dioinjector-isolated-soundcard-overlay.dts | 4 +- + .../overlays/audioinjector-ultra-overlay.dts | 6 +- + .../audioinjector-wm8731-audio-overlay.dts | 4 +- + .../dts/overlays/audiosense-pi-overlay.dts | 4 +- + .../boot/dts/overlays/chipdip-dac-overlay.dts | 4 +- + .../dts/overlays/cirrus-wm5102-overlay.dts | 4 +- + .../boot/dts/overlays/dacberry400-overlay.dts | 4 +- + .../dts/overlays/dionaudio-kiwi-overlay.dts | 4 +- + .../dts/overlays/dionaudio-loco-overlay.dts | 4 +- + .../overlays/dionaudio-loco-v2-overlay.dts | 4 +- + .../dts/overlays/disable-bt-pi5-overlay.dts | 17 + + .../dts/overlays/disable-wifi-pi5-overlay.dts | 13 + + arch/arm/boot/dts/overlays/draws-overlay.dts | 6 +- + .../boot/dts/overlays/edt-ft5406-overlay.dts | 22 +- + arch/arm/boot/dts/overlays/edt-ft5406.dtsi | 2 +- + .../boot/dts/overlays/fe-pi-audio-overlay.dts | 4 +- + .../boot/dts/overlays/ghost-amp-overlay.dts | 4 +- + .../googlevoicehat-soundcard-overlay.dts | 4 +- + .../dts/overlays/hifiberry-amp-overlay.dts | 4 +- + .../dts/overlays/hifiberry-amp100-overlay.dts | 11 +- + .../dts/overlays/hifiberry-amp3-overlay.dts | 4 +- + .../dts/overlays/hifiberry-dac-overlay.dts | 4 +- + .../overlays/hifiberry-dacplus-overlay.dts | 11 +- + .../overlays/hifiberry-dacplusadc-overlay.dts | 10 +- + .../hifiberry-dacplusadcpro-overlay.dts | 10 +- + .../overlays/hifiberry-dacplusdsp-overlay.dts | 4 +- + .../overlays/hifiberry-dacplushd-overlay.dts | 4 +- + .../dts/overlays/hifiberry-digi-overlay.dts | 4 +- + .../overlays/hifiberry-digi-pro-overlay.dts | 4 +- + .../boot/dts/overlays/i-sabre-q2m-overlay.dts | 4 +- + .../boot/dts/overlays/i2c0-pi5-overlay.dts | 34 + + .../boot/dts/overlays/i2c1-pi5-overlay.dts | 34 + + .../boot/dts/overlays/i2c2-pi5-overlay.dts | 21 + + .../boot/dts/overlays/i2c3-pi5-overlay.dts | 22 + + .../arm/boot/dts/overlays/i2s-dac-overlay.dts | 4 +- + arch/arm/boot/dts/overlays/imx219-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/imx258-overlay.dts | 2 +- + .../boot/dts/overlays/imx290_327-overlay.dtsi | 2 +- + arch/arm/boot/dts/overlays/imx296-overlay.dts | 2 +- + .../boot/dts/overlays/imx477_378-overlay.dtsi | 2 +- + arch/arm/boot/dts/overlays/imx519-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/imx708-overlay.dts | 4 +- + .../dts/overlays/iqaudio-codec-overlay.dts | 4 +- + .../boot/dts/overlays/iqaudio-dac-overlay.dts | 4 +- + .../dts/overlays/iqaudio-dacplus-overlay.dts | 4 +- + .../iqaudio-digi-wm8804-audio-overlay.dts | 4 +- + .../arm/boot/dts/overlays/irs1125-overlay.dts | 2 +- + .../dts/overlays/justboom-both-overlay.dts | 4 +- + .../dts/overlays/justboom-dac-overlay.dts | 4 +- + .../dts/overlays/justboom-digi-overlay.dts | 4 +- + .../boot/dts/overlays/max98357a-overlay.dts | 6 +- + .../boot/dts/overlays/mbed-dac-overlay.dts | 6 +- + .../boot/dts/overlays/merus-amp-overlay.dts | 4 +- + .../dts/overlays/midi-uart0-pi5-overlay.dts | 35 + + .../dts/overlays/midi-uart1-pi5-overlay.dts | 35 + + .../dts/overlays/midi-uart2-pi5-overlay.dts | 35 + + .../dts/overlays/midi-uart3-pi5-overlay.dts | 35 + + .../dts/overlays/midi-uart4-pi5-overlay.dts | 35 + + arch/arm/boot/dts/overlays/ov2311-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/ov5647-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/ov7251-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/ov9281-overlay.dts | 2 +- + arch/arm/boot/dts/overlays/overlay_map.dts | 226 +++ + arch/arm/boot/dts/overlays/pibell-overlay.dts | 6 +- + .../arm/boot/dts/overlays/pifi-40-overlay.dts | 4 +- + .../boot/dts/overlays/pifi-dac-hd-overlay.dts | 4 +- + .../dts/overlays/pifi-dac-zero-overlay.dts | 4 +- + .../dts/overlays/pifi-mini-210-overlay.dts | 4 +- + .../arm/boot/dts/overlays/pisound-overlay.dts | 4 +- + .../boot/dts/overlays/proto-codec-overlay.dts | 4 +- + .../rra-digidac1-wm8741-audio-overlay.dts | 4 +- + .../dts/overlays/spi2-1cs-pi5-overlay.dts | 33 + + .../dts/overlays/spi2-2cs-pi5-overlay.dts | 44 + + .../dts/overlays/spi3-1cs-pi5-overlay.dts | 33 + + .../dts/overlays/spi3-2cs-pi5-overlay.dts | 44 + + .../dts/overlays/spi5-1cs-pi5-overlay.dts | 33 + + .../dts/overlays/spi5-2cs-pi5-overlay.dts | 44 + + .../dts/overlays/superaudioboard-overlay.dts | 6 +- + .../dts/overlays/tc358743-audio-overlay.dts | 10 +- + .../boot/dts/overlays/tc358743-overlay.dts | 2 +- + .../boot/dts/overlays/uart0-pi5-overlay.dts | 17 + + .../boot/dts/overlays/uart1-pi5-overlay.dts | 17 + + .../boot/dts/overlays/uart2-pi5-overlay.dts | 17 + + .../boot/dts/overlays/uart3-pi5-overlay.dts | 17 + + .../boot/dts/overlays/uart4-pi5-overlay.dts | 17 + + arch/arm/boot/dts/overlays/udrc-overlay.dts | 6 +- + .../dts/overlays/ugreen-dabboard-overlay.dts | 10 +- + .../dts/overlays/vc4-fkms-v3d-overlay.dts | 6 + + .../dts/overlays/vc4-fkms-v3d-pi4-overlay.dts | 6 + + .../overlays/vc4-kms-dsi-7inch-overlay.dts | 18 +- + .../vc4-kms-dsi-waveshare-panel-overlay.dts | 8 +- + .../dts/overlays/vc4-kms-v3d-pi5-overlay.dts | 147 ++ + .../dts/overlays/vc4-kms-vga666-overlay.dts | 9 +- + .../dts/overlays/wm8960-soundcard-overlay.dts | 4 +- + arch/arm/boot/dts/rp1.dtsi | 1168 +++++++++++++++ + arch/arm64/boot/dts/broadcom/Makefile | 1 + + .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 1 + + 134 files changed, 5143 insertions(+), 264 deletions(-) + create mode 100644 arch/arm/boot/dts/bcm2712-rpi-5-b.dts + create mode 100644 arch/arm/boot/dts/bcm2712-rpi.dtsi + create mode 100644 arch/arm/boot/dts/bcm2712.dtsi + create mode 100644 arch/arm/boot/dts/overlays/disable-bt-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/disable-wifi-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c0-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c1-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c2-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/i2c3-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart0-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart1-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart2-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart3-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/midi-uart4-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi2-1cs-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi2-2cs-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi3-1cs-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi3-2cs-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi5-1cs-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi5-2cs-pi5-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/uart0-pi5-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/uart1-pi5-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/uart2-pi5-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/uart3-pi5-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/uart4-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-v3d-pi5-overlay.dts + create mode 100644 arch/arm/boot/dts/rp1.dtsi + create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -18,7 +18,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ + bcm2709-rpi-cm2.dtb \ + bcm2710-rpi-cm3.dtb \ + bcm2711-rpi-cm4.dtb \ +- bcm2711-rpi-cm4s.dtb ++ bcm2711-rpi-cm4s.dtb \ ++ bcm2712-rpi-5-b.dtb + + dtb-$(CONFIG_ARCH_ALPINE) += \ + alpine-db.dtb +--- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +@@ -192,6 +192,9 @@ i2c_arm: &i2c1 { + i2c_vc: &i2c0 { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2708-rpi-b-rev1.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b-rev1.dts +@@ -203,6 +203,9 @@ i2c_arm: &i2c0 { + i2c_vc: &i2c1 { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2708-rpi-b.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts +@@ -185,6 +185,9 @@ i2c_arm: &i2c1 { + i2c_vc: &i2c0 { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts +@@ -19,6 +19,9 @@ cam0_reg: &cam0_regulator { + gpio = <&gpio 31 GPIO_ACTIVE_HIGH>; + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + &uart0 { + status = "okay"; + }; +--- a/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-zero-w.dts +@@ -243,6 +243,7 @@ cam0_reg: &cam_dummy_reg { + + i2c_arm: &i2c1 {}; + i2c_vc: &i2c0 {}; ++i2c_csi_dsi0: &i2c0 {}; + + / { + __overrides__ { +--- a/arch/arm/boot/dts/bcm2708-rpi-zero.dts ++++ b/arch/arm/boot/dts/bcm2708-rpi-zero.dts +@@ -178,6 +178,7 @@ cam0_reg: &cam_dummy_reg { + + i2c_arm: &i2c1 {}; + i2c_vc: &i2c0 {}; ++i2c_csi_dsi0: &i2c0 {}; + + / { + __overrides__ { +--- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts ++++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts +@@ -186,6 +186,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2709-rpi-cm2.dts ++++ b/arch/arm/boot/dts/bcm2709-rpi-cm2.dts +@@ -20,6 +20,9 @@ cam0_reg: &cam0_regulator { + gpio = <&gpio 30 GPIO_ACTIVE_HIGH>; + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + &uart0 { + status = "okay"; + }; +--- a/arch/arm/boot/dts/bcm270x-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm270x-rpi.dtsi +@@ -127,6 +127,9 @@ + status = "disabled"; + }; + ++i2s_clk_producer: &i2s {}; ++i2s_clk_consumer: &i2s {}; ++ + &clocks { + firmware = <&firmware>; + }; +--- a/arch/arm/boot/dts/bcm2710-rpi-2-b.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-2-b.dts +@@ -186,6 +186,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts +@@ -274,6 +274,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts +@@ -283,6 +283,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts +@@ -19,6 +19,9 @@ cam0_reg: &cam0_regulator { + gpio = <&gpio 31 GPIO_ACTIVE_HIGH>; + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + &uart0 { + status = "okay"; + }; +--- a/arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts +@@ -262,6 +262,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts ++++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts +@@ -400,6 +400,9 @@ + cam0_reg: &cam_dummy_reg { + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts ++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts +@@ -409,6 +409,9 @@ cam0_reg: &cam1_reg { + gpio = <&expgpio 5 GPIO_ACTIVE_HIGH>; + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_hdmi=0'}"; +--- a/arch/arm/boot/dts/bcm2711-rpi-cm4s.dts ++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4s.dts +@@ -282,6 +282,9 @@ cam0_reg: &cam0_regulator { + status = "disabled"; + }; + ++i2c_csi_dsi0: &i2c0 { ++}; ++ + / { + __overrides__ { + audio = <&chosen>,"bootargs{on='snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_hdmi=0'}"; +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -0,0 +1,824 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/dts-v1/; ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define i2c0 _i2c0 ++#define i2c3 _i2c3 ++#define i2c4 _i2c4 ++#define i2c5 _i2c5 ++#define i2c6 _i2c6 ++#define i2c8 _i2c8 ++#define i2s _i2s ++#define pwm0 _pwm0 ++#define pwm1 _pwm1 ++#define spi0 _spi0 ++#define spi3 _spi3 ++#define spi4 _spi4 ++#define spi5 _spi5 ++#define spi6 _spi6 ++#define uart0 _uart0 ++#define uart2 _uart2 ++#define uart3 _uart3 ++#define uart4 _uart4 ++#define uart5 _uart5 ++ ++#include "bcm2712.dtsi" ++ ++#undef i2c0 ++#undef i2c3 ++#undef i2c4 ++#undef i2c5 ++#undef i2c6 ++#undef i2c8 ++#undef i2s ++#undef pwm0 ++#undef pwm1 ++#undef spi0 ++#undef spi3 ++#undef spi4 ++#undef spi5 ++#undef spi6 ++#undef uart0 ++#undef uart2 ++#undef uart3 ++#undef uart4 ++#undef uart5 ++ ++/ { ++ compatible = "raspberrypi,5-model-b", "brcm,bcm2712"; ++ model = "Raspberry Pi 5 Model B"; ++ ++ /* Will be filled by the bootloader */ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0 0 0x28000000>; ++ }; ++ ++ leds: leds { ++ compatible = "gpio-leds"; ++ ++ pwr_led: led-pwr { ++ label = "PWR"; ++ gpios = <&rp1_gpio 44 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "none"; ++ }; ++ ++ act_led: led-act { ++ label = "ACT"; ++ gpios = <&gio_aon 9 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ sd_io_1v8_reg: sd_io_1v8_reg { ++ compatible = "regulator-gpio"; ++ regulator-name = "vdd-sd-io"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-settling-time-us = <5000>; ++ gpios = <&gio_aon 3 GPIO_ACTIVE_HIGH>; ++ states = <1800000 0x1 ++ 3300000 0x0>; ++ status = "okay"; ++ }; ++ ++ sd_vcc_reg: sd_vcc_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ enable-active-high; ++ gpios = <&gio_aon 4 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ wl_on_reg: wl_on_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "wl-on-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ pinctrl-0 = <&wl_on_pins>; ++ pinctrl-names = "default"; ++ ++ gpio = <&gio 28 GPIO_ACTIVE_HIGH>; ++ ++ startup-delay-us = <150000>; ++ enable-active-high; ++ }; ++ ++ clocks: clocks { ++ }; ++ ++ cam1_clk: cam1_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ cam0_clk: cam0_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ cam0_reg: cam0_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "cam0_reg"; ++ enable-active-high; ++ status = "okay"; ++ gpio = <&rp1_gpio 34 0>; // CD0_IO0_MICCLK, to MIPI 0 connector ++ }; ++ ++ cam1_reg: cam1_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "cam1_reg"; ++ enable-active-high; ++ status = "okay"; ++ gpio = <&rp1_gpio 46 0>; // CD1_IO0_MICCLK, to MIPI 1 connector ++ }; ++ ++ cam_dummy_reg: cam_dummy_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "cam-dummy-reg"; ++ status = "okay"; ++ }; ++ ++ dummy: dummy { ++ // A target for unwanted overlay fragments ++ }; ++}; ++ ++rp1_target: &pcie2 { ++ brcm,vdm-qos-map = <0xbbaa9888>; ++ aspm-no-l0s; ++ status = "okay"; ++}; ++ ++// Add some labels to 2712 device ++ ++// The system UART ++uart10: &_uart0 { status = "okay"; }; ++ ++// The system SPI for the bootloader EEPROM ++spi10: &_spi0 { status = "okay"; }; ++ ++i2c_rp1boot: &_i2c3 { }; ++ ++#include "rp1.dtsi" ++ ++&rp1 { ++ // PCIe address space layout: ++ // 00_00000000-00_00xxxxxx = RP1 peripherals ++ // 10_00000000-1x_xxxxxxxx = up to 64GB system RAM ++ ++ // outbound access aimed at PCIe 0_00xxxxxx -> RP1 c0_40xxxxxx ++ // This is the RP1 peripheral space ++ ranges = <0xc0 0x40000000 ++ 0x02000000 0x00 0x00000000 ++ 0x00 0x00400000>; ++ ++ dma-ranges = ++ // inbound RP1 1x_xxxxxxxx -> PCIe 1x_xxxxxxxx ++ <0x10 0x00000000 ++ 0x43000000 0x10 0x00000000 ++ 0x10 0x00000000>, ++ ++ // inbound RP1 c0_40xxxxxx -> PCIe 00_00xxxxxx ++ // This allows the RP1 DMA controller to address RP1 hardware ++ <0xc0 0x40000000 ++ 0x02000000 0x0 0x00000000 ++ 0x0 0x00400000>, ++ ++ // inbound RP1 0x_xxxxxxxx -> PCIe 1x_xxxxxxxx ++ <0x00 0x00000000 ++ 0x02000000 0x10 0x00000000 ++ 0x10 0x00000000>; ++}; ++ ++// Expose RP1 nodes as system nodes with labels ++ ++&rp1_dma { ++ status = "okay"; ++}; ++ ++&rp1_eth { ++ status = "okay"; ++ phy-handle = <&phy1>; ++ phy-reset-gpios = <&rp1_gpio 32 GPIO_ACTIVE_LOW>; ++ phy-reset-duration = <5>; ++ ++ phy1: ethernet-phy@1 { ++ reg = <0x1>; ++ brcm,powerdown-enable; ++ }; ++}; ++ ++gpio: &rp1_gpio { ++ status = "okay"; ++}; ++ ++aux: &dummy {}; ++ ++&rp1_usb0 { ++ pinctrl-0 = <&usb_vbus_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&rp1_usb1 { ++ status = "okay"; ++}; ++ ++#include "bcm2712-rpi.dtsi" ++ ++// A few extra labels to keep overlays happy ++ ++i2c0if: &rp1_gpio {}; ++i2c0mux: &rp1_gpio {}; ++ ++i2c_csi_dsi0: &i2c6 { // Note: This is for MIPI0 connector only ++ pinctrl-0 = <&rp1_i2c6_38_39>; ++ pinctrl-names = "default"; ++}; ++ ++i2c_csi_dsi1: &i2c4 { // Note: This is for MIPI1 connector only ++ pinctrl-0 = <&rp1_i2c4_40_41>; ++ pinctrl-names = "default"; ++}; ++ ++i2c_csi_dsi: &i2c_csi_dsi1 { }; // An alias for compatibility ++ ++csi0: &rp1_csi0 { }; ++csi1: &rp1_csi1 { }; ++dsi0: &rp1_dsi0 { }; ++dsi1: &rp1_dsi1 { }; ++dpi: &rp1_dpi { }; ++vec: &rp1_vec { }; ++dpi_gpio0: &rp1_dpi_24bit_gpio0 { }; ++dpi_gpio1: &rp1_dpi_24bit_gpio2 { }; ++dpi_18bit_cpadhi_gpio0: &rp1_dpi_18bit_cpadhi_gpio0 { }; ++dpi_18bit_cpadhi_gpio2: &rp1_dpi_18bit_cpadhi_gpio2 { }; ++dpi_18bit_gpio0: &rp1_dpi_18bit_gpio0 { }; ++dpi_18bit_gpio2: &rp1_dpi_18bit_gpio2 { }; ++dpi_16bit_cpadhi_gpio0: &rp1_dpi_16bit_cpadhi_gpio0 { }; ++dpi_16bit_cpadhi_gpio2: &rp1_dpi_16bit_cpadhi_gpio2 { }; ++dpi_16bit_gpio0: &rp1_dpi_16bit_gpio0 { }; ++dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { }; ++ ++/* Add the IOMMUs for some RP1 bus masters */ ++ ++&csi0 { ++ iommus = <&iommu5>; ++}; ++ ++&csi1 { ++ iommus = <&iommu5>; ++}; ++ ++&dsi0 { ++ iommus = <&iommu5>; ++}; ++ ++&dsi1 { ++ iommus = <&iommu5>; ++}; ++ ++&dpi { ++ iommus = <&iommu5>; ++}; ++ ++&vec { ++ iommus = <&iommu5>; ++}; ++ ++&ddc0 { ++ status = "disabled"; ++}; ++ ++&ddc1 { ++ status = "disabled"; ++}; ++ ++&hdmi0 { ++ clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 0>, <&clk_27MHz>; ++ clock-names = "hdmi", "bvb", "audio", "cec"; ++ status = "disabled"; ++}; ++ ++&hdmi1 { ++ clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 1>, <&clk_27MHz>; ++ clock-names = "hdmi", "bvb", "audio", "cec"; ++ status = "disabled"; ++}; ++ ++&hvs { ++ clocks = <&firmware_clocks 4>, <&firmware_clocks 16>; ++ clock-names = "core", "disp"; ++}; ++ ++&mop { ++ status = "disabled"; ++}; ++ ++&moplet { ++ status = "disabled"; ++}; ++ ++&pixelvalve0 { ++ status = "disabled"; ++}; ++ ++&pixelvalve1 { ++ status = "disabled"; ++}; ++ ++&disp_intr { ++ status = "disabled"; ++}; ++ ++/* SDIO1 is used to drive the SD card */ ++&sdio1 { ++ pinctrl-0 = <&emmc_sd_pulls>, <&emmc_aon_cd_pins>; ++ pinctrl-names = "default"; ++ vqmmc-supply = <&sd_io_1v8_reg>; ++ vmmc-supply = <&sd_vcc_reg>; ++ bus-width = <4>; ++ sd-uhs-sdr50; ++ sd-uhs-ddr50; ++ sd-uhs-sdr104; ++ //broken-cd; ++ //no-1-8-v; ++ status = "okay"; ++}; ++ ++&pinctrl_aon { ++ emmc_aon_cd_pins: emmc_aon_cd_pins { ++ function = "sd_card_g"; ++ pins = "aon_gpio5"; ++ bias-pull-up; ++ }; ++ ++ /* Slight hack - only one PWM pin (status LED) is usable */ ++ aon_pwm_1pin: aon_pwm_1pin { ++ function = "aon_pwm"; ++ pins = "aon_gpio9"; ++ }; ++}; ++ ++&pinctrl { ++ pwr_button_pins: pwr_button_pins { ++ function = "gpio"; ++ pins = "gpio20"; ++ bias-pull-up; ++ }; ++ ++ wl_on_pins: wl_on_pins { ++ function = "gpio"; ++ pins = "gpio28"; ++ }; ++ ++ bt_shutdown_pins: bt_shutdown_pins { ++ function = "gpio"; ++ pins = "gpio29"; ++ }; ++ ++ emmc_sd_pulls: emmc_sd_pulls { ++ function = "emmc_dat0", "emmc_dat1", "emmc_dat2", "emmc_dat3"; ++ bias-pull-up; ++ }; ++}; ++ ++/* uarta communicates with the BT module */ ++&uarta { ++ uart-has-rtscts; ++ auto-flow-control; ++ status = "okay"; ++ clock-frequency = <96000000>; ++ pinctrl-0 = <&uarta_24_pins &bt_shutdown_pins>; ++ pinctrl-names = "default"; ++ ++ bluetooth: bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ max-speed = <3000000>; ++ shutdown-gpios = <&gio 29 GPIO_ACTIVE_HIGH>; ++ local-bd-address = [ 00 00 00 00 00 00 ]; ++ }; ++}; ++ ++&i2c_rp1boot { ++ clock-frequency = <400000>; ++ pinctrl-0 = <&i2c3_m4_agpio0_pins>; ++ pinctrl-names = "default"; ++}; ++ ++/ { ++ chosen: chosen { ++ bootargs = "coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; ++ stdout-path = "serial10:115200n8"; ++ }; ++ ++ fan: cooling_fan { ++ status = "disabled"; ++ compatible = "pwm-fan"; ++ #cooling-cells = <2>; ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ cooling-levels = <0 75 125 175 250>; ++ pwms = <&rp1_pwm1 3 41566 PWM_POLARITY_INVERTED>; ++ rpm-regmap = <&rp1_pwm1>; ++ rpm-offset = <0x3c>; ++ }; ++ ++ pwr_button { ++ compatible = "gpio-keys"; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwr_button_pins>; ++ status = "okay"; ++ ++ pwr_key: pwr { ++ label = "pwr_button"; ++ // linux,code = <205>; // KEY_SUSPEND ++ linux,code = <116>; // KEY_POWER ++ gpios = <&gio 20 GPIO_ACTIVE_LOW>; ++ debounce-interval = <50>; // ms ++ }; ++ }; ++}; ++ ++&usb { ++ power-domains = <&power RPI_POWER_DOMAIN_USB>; ++}; ++ ++/* SDIO2 drives the WLAN interface */ ++&sdio2 { ++ pinctrl-0 = <&sdio2_30_pins>; ++ pinctrl-names = "default"; ++ bus-width = <4>; ++ vmmc-supply = <&wl_on_reg>; ++ sd-uhs-ddr50; ++ non-removable; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ wifi: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++}; ++ ++&rpivid { ++ status = "okay"; ++}; ++ ++&pinctrl { ++ spi10_gpio2: spi10_gpio2 { ++ function = "vc_spi0"; ++ pins = "gpio2", "gpio3", "gpio4"; ++ bias-disable; ++ }; ++ ++ spi10_cs_gpio1: spi10_cs_gpio1 { ++ function = "gpio"; ++ pins = "gpio1"; ++ bias-pull-up; ++ }; ++}; ++ ++spi10_pins: &spi10_gpio2 {}; ++spi10_cs_pins: &spi10_cs_gpio1 {}; ++ ++&spi10 { ++ pinctrl-names = "default"; ++ cs-gpios = <&gio 1 1>; ++ pinctrl-0 = <&spi10_pins &spi10_cs_pins>; ++ ++ spidev10: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <20000000>; ++ status = "okay"; ++ }; ++}; ++ ++// ============================================= ++// Board specific stuff here ++ ++&gio_aon { ++ // Don't use GIO_AON as an interrupt controller because it will ++ // clash with the firmware monitoring the PMIC interrupt via the VPU. ++ ++ /delete-property/ interrupt-controller; ++}; ++ ++&main_aon_irq { ++ // Don't use the MAIN_AON_IRQ interrupt controller because it will ++ // clash with the firmware monitoring the PMIC interrupt via the VPU. ++ ++ status = "disabled"; ++}; ++ ++&rp1_pwm1 { ++ status = "disabled"; ++ pinctrl-0 = <&rp1_pwm1_gpio45>; ++ pinctrl-names = "default"; ++}; ++ ++&thermal_trips { ++ cpu_tepid: cpu-tepid { ++ temperature = <50000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ cpu_warm: cpu-warm { ++ temperature = <60000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ cpu_hot: cpu-hot { ++ temperature = <67500>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ cpu_vhot: cpu-vhot { ++ temperature = <75000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++}; ++ ++&cooling_maps { ++ tepid { ++ trip = <&cpu_tepid>; ++ cooling-device = <&fan 1 1>; ++ }; ++ ++ warm { ++ trip = <&cpu_warm>; ++ cooling-device = <&fan 2 2>; ++ }; ++ ++ hot { ++ trip = <&cpu_hot>; ++ cooling-device = <&fan 3 3>; ++ }; ++ ++ vhot { ++ trip = <&cpu_vhot>; ++ cooling-device = <&fan 4 4>; ++ }; ++ ++ melt { ++ trip = <&cpu_crit>; ++ cooling-device = <&fan 4 4>; ++ }; ++}; ++ ++&gio { ++ // The GPIOs above 35 are not used on Pi 5, so shrink the upper bank ++ // to reduce the clutter in gpioinfo/pinctrl ++ brcm,gpio-bank-widths = <32 4>; ++ ++ gpio-line-names = ++ "-", // GPIO_000 ++ "2712_BOOT_CS_N", // GPIO_001 ++ "2712_BOOT_MISO", // GPIO_002 ++ "2712_BOOT_MOSI", // GPIO_003 ++ "2712_BOOT_SCLK", // GPIO_004 ++ "-", // GPIO_005 ++ "-", // GPIO_006 ++ "-", // GPIO_007 ++ "-", // GPIO_008 ++ "-", // GPIO_009 ++ "-", // GPIO_010 ++ "-", // GPIO_011 ++ "-", // GPIO_012 ++ "-", // GPIO_013 ++ "PCIE_SDA", // GPIO_014 ++ "PCIE_SCL", // GPIO_015 ++ "-", // GPIO_016 ++ "-", // GPIO_017 ++ "-", // GPIO_018 ++ "-", // GPIO_019 ++ "PWR_GPIO", // GPIO_020 ++ "2712_G21_FS", // GPIO_021 ++ "-", // GPIO_022 ++ "-", // GPIO_023 ++ "BT_RTS", // GPIO_024 ++ "BT_CTS", // GPIO_025 ++ "BT_TXD", // GPIO_026 ++ "BT_RXD", // GPIO_027 ++ "WL_ON", // GPIO_028 ++ "BT_ON", // GPIO_029 ++ "WIFI_SDIO_CLK", // GPIO_030 ++ "WIFI_SDIO_CMD", // GPIO_031 ++ "WIFI_SDIO_D0", // GPIO_032 ++ "WIFI_SDIO_D1", // GPIO_033 ++ "WIFI_SDIO_D2", // GPIO_034 ++ "WIFI_SDIO_D3"; // GPIO_035 ++}; ++ ++&gio_aon { ++ gpio-line-names = ++ "RP1_SDA", // AON_GPIO_00 ++ "RP1_SCL", // AON_GPIO_01 ++ "RP1_RUN", // AON_GPIO_02 ++ "SD_IOVDD_SEL", // AON_GPIO_03 ++ "SD_PWR_ON", // AON_GPIO_04 ++ "SD_CDET_N", // AON_GPIO_05 ++ "SD_FLG_N", // AON_GPIO_06 ++ "-", // AON_GPIO_07 ++ "2712_WAKE", // AON_GPIO_08 ++ "2712_STAT_LED", // AON_GPIO_09 ++ "-", // AON_GPIO_10 ++ "-", // AON_GPIO_11 ++ "PMIC_INT", // AON_GPIO_12 ++ "UART_TX_FS", // AON_GPIO_13 ++ "UART_RX_FS", // AON_GPIO_14 ++ "-", // AON_GPIO_15 ++ "-", // AON_GPIO_16 ++ ++ // Pad bank0 out to 32 entries ++ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ++ ++ "HDMI0_SCL", // AON_SGPIO_00 ++ "HDMI0_SDA", // AON_SGPIO_01 ++ "HDMI1_SCL", // AON_SGPIO_02 ++ "HDMI1_SDA", // AON_SGPIO_03 ++ "PMIC_SCL", // AON_SGPIO_04 ++ "PMIC_SDA"; // AON_SGPIO_05 ++ ++ rp1_run_hog { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RP1 RUN pin"; ++ }; ++}; ++ ++&rp1_gpio { ++ gpio-line-names = ++ "ID_SD", // GPIO0 ++ "ID_SC", // GPIO1 ++ "PIN3", // GPIO2 ++ "PIN5", // GPIO3 ++ "PIN7", // GPIO4 ++ "PIN29", // GPIO5 ++ "PIN31", // GPIO6 ++ "PIN26", // GPIO7 ++ "PIN24", // GPIO8 ++ "PIN21", // GPIO9 ++ "PIN19", // GPIO10 ++ "PIN23", // GPIO11 ++ "PIN32", // GPIO12 ++ "PIN33", // GPIO13 ++ "PIN8", // GPIO14 ++ "PIN10", // GPIO15 ++ "PIN36", // GPIO16 ++ "PIN11", // GPIO17 ++ "PIN12", // GPIO18 ++ "PIN35", // GPIO19 ++ "PIN38", // GPIO20 ++ "PIN40", // GPIO21 ++ "PIN15", // GPIO22 ++ "PIN16", // GPIO23 ++ "PIN18", // GPIO24 ++ "PIN22", // GPIO25 ++ "PIN37", // GPIO26 ++ "PIN13", // GPIO27 ++ ++ "PCIE_RP1_WAKE", // GPIO28 ++ "FAN_TACH", // GPIO29 ++ "HOST_SDA", // GPIO30 ++ "HOST_SCL", // GPIO31 ++ "ETH_RST_N", // GPIO32 ++ "-", // GPIO33 ++ ++ "CD0_IO0_MICCLK", // GPIO34 ++ "CD0_IO0_MICDAT0", // GPIO35 ++ "RP1_PCIE_CLKREQ_N", // GPIO36 ++ "-", // GPIO37 ++ "CD0_SDA", // GPIO38 ++ "CD0_SCL", // GPIO39 ++ "CD1_SDA", // GPIO40 ++ "CD1_SCL", // GPIO41 ++ "USB_VBUS_EN", // GPIO42 ++ "USB_OC_N", // GPIO43 ++ "RP1_STAT_LED", // GPIO44 ++ "FAN_PWM", // GPIO45 ++ "CD1_IO0_MICCLK", // GPIO46 ++ "2712_WAKE", // GPIO47 ++ "CD1_IO1_MICDAT1", // GPIO48 ++ "EN_MAX_USB_CUR", // GPIO49 ++ "-", // GPIO50 ++ "-", // GPIO51 ++ "-", // GPIO52 ++ "-"; // GPIO53 ++ ++ usb_vbus_pins: usb_vbus_pins { ++ function = "vbus1"; ++ pins = "gpio42", "gpio43"; ++ }; ++}; ++ ++/ { ++ aliases: aliases { ++ blconfig = &blconfig; ++ bluetooth = &bluetooth; ++ console = &uart10; ++ ethernet0 = &rp1_eth; ++ wifi0 = &wifi; ++ fb = &fb; ++ mailbox = &mailbox; ++ mmc0 = &sdio1; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ uart2 = &uart2; ++ uart3 = &uart3; ++ uart4 = &uart4; ++ uart10 = &uart10; ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial2 = &uart2; ++ serial3 = &uart3; ++ serial4 = &uart4; ++ serial10 = &uart10; ++ i2c = &i2c_arm; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ i2c5 = &i2c5; ++ i2c6 = &i2c6; ++ i2c10 = &i2c_rp1boot; ++ // Bit-bashed i2c_gpios start at 10 ++ spi0 = &spi0; ++ spi1 = &spi1; ++ spi2 = &spi2; ++ spi3 = &spi3; ++ spi4 = &spi4; ++ spi5 = &spi5; ++ spi10 = &spi10; ++ gpio0 = &gpio; ++ gpio1 = &gio; ++ gpio2 = &gio_aon; ++ gpio3 = &pinctrl; ++ gpio4 = &pinctrl_aon; ++ usb0 = &rp1_usb0; ++ usb1 = &rp1_usb1; ++ }; ++ ++ __overrides__ { ++ bdaddr = <&bluetooth>, "local-bd-address["; ++ button_debounce = <&pwr_key>, "debounce-interval:0"; ++ cooling_fan = <&fan>, "status", <&rp1_pwm1>, "status"; ++ uart0_console = <&uart0>,"status", <&aliases>, "console=",&uart0; ++ i2c0 = <&i2c0>, "status"; ++ i2c1 = <&i2c1>, "status"; ++ i2c = <&i2c1>, "status"; ++ i2c_arm = <&i2c_arm>, "status"; ++ i2c_vc = <&i2c_vc>, "status"; ++ i2c_csi_dsi = <&i2c_csi_dsi>, "status"; ++ i2c_csi_dsi0 = <&i2c_csi_dsi0>, "status"; ++ i2c_csi_dsi1 = <&i2c_csi_dsi1>, "status"; ++ i2c0_baudrate = <&i2c0>, "clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>, "clock-frequency:0"; ++ i2c_baudrate = <&i2c_arm>, "clock-frequency:0"; ++ i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0"; ++ i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0"; ++ nvme = <&pciex1>, "status"; ++ pciex1 = <&pciex1>, "status"; ++ pciex1_gen = <&pciex1> , "max-link-speed:0"; ++ pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?"; ++ random = <&random>, "status"; ++ rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0"; ++ spi = <&spi0>, "status"; ++ suspend = <&pwr_key>, "linux,code:0=205"; ++ uart0 = <&uart0>, "status"; ++ wifiaddr = <&wifi>, "local-mac-address["; ++ ++ act_led_activelow = <&act_led>, "active-low?"; ++ act_led_trigger = <&act_led>, "linux,default-trigger"; ++ pwr_led_activelow = <&pwr_led>, "gpios:8"; ++ pwr_led_trigger = <&pwr_led>, "linux,default-trigger"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2712-rpi.dtsi +@@ -0,0 +1,281 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++ ++&soc { ++ firmware: firmware { ++ compatible = "raspberrypi,bcm2835-firmware", "simple-mfd"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ mboxes = <&mailbox>; ++ dma-ranges; ++ ++ firmware_clocks: clocks { ++ compatible = "raspberrypi,firmware-clocks"; ++ #clock-cells = <1>; ++ }; ++ ++ reset: reset { ++ compatible = "raspberrypi,firmware-reset"; ++ #reset-cells = <1>; ++ }; ++ ++ vcio: vcio { ++ compatible = "raspberrypi,vcio"; ++ }; ++ }; ++ ++ power: power { ++ compatible = "raspberrypi,bcm2835-power"; ++ firmware = <&firmware>; ++ #power-domain-cells = <1>; ++ }; ++ ++ fb: fb { ++ compatible = "brcm,bcm2708-fb"; ++ firmware = <&firmware>; ++ status = "okay"; ++ }; ++ ++ rpi_rtc: rpi_rtc { ++ compatible = "raspberrypi,rpi-rtc"; ++ firmware = <&firmware>; ++ status = "okay"; ++ trickle-charge-microvolt = <0>; ++ }; ++ ++ /* Define these notional regulators for use by overlays, etc. */ ++ vdd_3v3_reg: fixedregulator_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-always-on; ++ regulator-max-microvolt = <3300000>; ++ regulator-min-microvolt = <3300000>; ++ regulator-name = "3v3"; ++ }; ++ ++ vdd_5v0_reg: fixedregulator_5v0 { ++ compatible = "regulator-fixed"; ++ regulator-always-on; ++ regulator-max-microvolt = <5000000>; ++ regulator-min-microvolt = <5000000>; ++ regulator-name = "5v0"; ++ }; ++}; ++ ++/ { ++ __overrides__ { ++ arm_freq; ++ }; ++}; ++ ++pciex1: &pcie1 { }; ++pciex4: &pcie2 { }; ++ ++&dma32 { ++ /* The VPU firmware uses DMA channel 11 for VCHIQ */ ++ brcm,dma-channel-mask = <0x03f>; ++}; ++ ++&dma40 { ++ /* The VPU firmware DMA channel 11 for VCHIQ */ ++ brcm,dma-channel-mask = <0x07c0>; ++}; ++ ++&hdmi0 { ++ dmas = <&dma40 (10|(1<<30)|(1<<24)|(10<<16)|(15<<20))>; ++}; ++ ++&hdmi1 { ++ dmas = <&dma40 (17|(1<<30)|(1<<24)|(10<<16)|(15<<20))>; ++}; ++ ++&spi10 { ++ dmas = <&dma40 6>, <&dma40 7>; ++ dma-names = "tx", "rx"; ++}; ++ ++&usb { ++ power-domains = <&power RPI_POWER_DOMAIN_USB>; ++}; ++ ++&rmem { ++ /* ++ * RPi4's co-processor will copy the board's bootloader configuration ++ * into memory for the OS to consume. It'll also update this node with ++ * its placement information. ++ */ ++ blconfig: nvram@0 { ++ compatible = "raspberrypi,bootloader-config", "nvmem-rmem"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x0 0x0 0x0>; ++ no-map; ++ status = "disabled"; ++ }; ++}; ++ ++&rp1_adc { ++ status = "okay"; ++}; ++ ++/* Add some gpiomem nodes to make the devices accessible to userspace. ++ * /dev/gpiomem should expose the registers for the interface with DT alias ++ * gpio. ++ */ ++ ++&rp1 { ++ gpiomem@d0000 { ++ /* Export IO_BANKs, RIO_BANKs and PADS_BANKs to userspace */ ++ compatible = "raspberrypi,gpiomem"; ++ reg = <0xc0 0x400d0000 0x0 0x30000>; ++ chardev-name = "gpiomem0"; ++ }; ++}; ++ ++&soc { ++ gpiomem@7d508500 { ++ compatible = "raspberrypi,gpiomem"; ++ reg = <0x7d508500 0x40>; ++ chardev-name = "gpiomem1"; ++ }; ++ ++ gpiomem@7d517c00 { ++ compatible = "raspberrypi,gpiomem"; ++ reg = <0x7d517c00 0x40>; ++ chardev-name = "gpiomem2"; ++ }; ++ ++ gpiomem@7d504100 { ++ compatible = "raspberrypi,gpiomem"; ++ reg = <0x7d504100 0x20>; ++ chardev-name = "gpiomem3"; ++ }; ++ ++ gpiomem@7d510700 { ++ compatible = "raspberrypi,gpiomem"; ++ reg = <0x7d510700 0x20>; ++ chardev-name = "gpiomem4"; ++ }; ++}; ++ ++i2c0: &rp1_i2c0 { }; ++i2c1: &rp1_i2c1 { }; ++i2c2: &rp1_i2c2 { }; ++i2c3: &rp1_i2c3 { }; ++i2c4: &rp1_i2c4 { }; ++i2c5: &rp1_i2c5 { }; ++i2c6: &rp1_i2c6 { }; ++i2s: &rp1_i2s0 { }; ++i2s_clk_producer: &rp1_i2s0 { }; ++i2s_clk_consumer: &rp1_i2s1 { }; ++pwm0: &rp1_pwm0 { }; ++pwm1: &rp1_pwm1 { }; ++pwm: &pwm0 { }; ++spi0: &rp1_spi0 { }; ++spi1: &rp1_spi1 { }; ++spi2: &rp1_spi2 { }; ++spi3: &rp1_spi3 { }; ++spi4: &rp1_spi4 { }; ++spi5: &rp1_spi5 { }; ++ ++uart0_pins: &rp1_uart0_14_15 {}; ++uart0_ctsrts_pins: &rp1_uart0_ctsrts_16_17 {}; ++uart0: &rp1_uart0 { ++ pinctrl-0 = <&uart0_pins>; ++}; ++ ++uart1_pins: &rp1_uart1_0_1 {}; ++uart1_ctsrts_pins: &rp1_uart1_ctsrts_2_3 {}; ++uart1: &rp1_uart1 { }; ++ ++uart2_pins: &rp1_uart2_4_5 {}; ++uart2_ctsrts_pins: &rp1_uart2_ctsrts_6_7 {}; ++uart2: &rp1_uart2 { }; ++ ++uart3_pins: &rp1_uart3_8_9 {}; ++uart3_ctsrts_pins: &rp1_uart3_ctsrts_10_11 {}; ++uart3: &rp1_uart3 { }; ++ ++uart4_pins: &rp1_uart4_12_13 {}; ++uart4_ctsrts_pins: &rp1_uart4_ctsrts_14_15 {}; ++uart4: &rp1_uart4 { }; ++ ++i2c_vc: &i2c0 { // This is pins 27,28 on the header (not MIPI) ++ pinctrl-0 = <&rp1_i2c0_0_1>; ++ pinctrl-names = "default"; ++}; ++ ++i2c_arm: &i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rp1_i2c1_2_3>; ++}; ++ ++&i2c2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rp1_i2c2_4_5>; ++}; ++ ++&i2c3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rp1_i2c3_6_7>; ++}; ++ ++&i2s_clk_producer { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rp1_i2s0_18_21>; ++}; ++ ++&i2s_clk_consumer { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rp1_i2s1_18_21>; ++}; ++ ++spi0_pins: &rp1_spi0_gpio9 {}; ++spi0_cs_pins: &rp1_spi0_cs_gpio7 {}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins &spi0_cs_pins>; ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; ++ ++ spidev0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ }; ++ ++ spidev1: spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ }; ++}; ++ ++spi2_pins: &rp1_spi2_gpio1 {}; ++&spi2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi2_pins>; ++}; ++ ++spi3_pins: &rp1_spi3_gpio5 {}; ++&spi3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi3_pins>; ++}; ++ ++spi4_pins: &rp1_spi4_gpio9 {}; ++&spi4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi4_pins>; ++}; ++ ++spi5_pins: &rp1_spi5_gpio13 {}; ++&spi5 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi5_pins>; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2712.dtsi +@@ -0,0 +1,1287 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include ++#include ++#include ++ ++/ { ++ compatible = "brcm,bcm2712", "brcm,bcm2711"; ++ model = "BCM2712"; ++ ++ #address-cells = <2>; ++ #size-cells = <1>; ++ ++ interrupt-parent = <&gicv2>; ++ ++ rmem: reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ ranges; ++ ++ atf@0 { ++ reg = <0x0 0x0 0x80000>; ++ no-map; ++ }; ++ ++ cma: linux,cma { ++ compatible = "shared-dma-pool"; ++ size = <0x4000000>; /* 64MB */ ++ reusable; ++ linux,cma-default; ++ ++ /* ++ * arm64 reserves the CMA by default somewhere in ++ * ZONE_DMA32, that's not good enough for the BCM2711 ++ * as some devices can only address the lower 1G of ++ * memory (ZONE_DMA). ++ */ ++ alloc-ranges = <0x0 0x00000000 0x40000000>; ++ }; ++ }; ++ ++ thermal-zones { ++ cpu_thermal: cpu-thermal { ++ polling-delay-passive = <2000>; ++ polling-delay = <1000>; ++ coefficients = <(-550) 450000>; ++ thermal-sensors = <&thermal>; ++ ++ thermal_trips: trips { ++ cpu_crit: cpu-crit { ++ temperature = <110000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling_maps: cooling-maps { ++ }; ++ }; ++ }; ++ ++ clk_27MHz: clk-27M { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <27000000>; ++ clock-output-names = "27MHz-clock"; ++ }; ++ ++ clk_108MHz: clk-108M { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <108000000>; ++ clock-output-names = "108MHz-clock"; ++ }; ++ ++ hvs: hvs@107c580000 { ++ compatible = "brcm,bcm2712-hvs"; ++ reg = <0x10 0x7c580000 0x1a000>; ++ interrupt-parent = <&disp_intr>; ++ interrupts = <2>, <9>, <16>; ++ interrupt-names = "ch0-eof", "ch1-eof", "ch2-eof"; ++ //iommus = <&iommu4>; ++ status = "disabled"; ++ }; ++ ++ soc: soc { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ ranges = <0x7c000000 0x10 0x7c000000 0x04000000>; ++ /* Emulate a contiguous 30-bit address range for DMA */ ++ dma-ranges = <0xc0000000 0x00 0x00000000 0x40000000>, ++ <0x7c000000 0x10 0x7c000000 0x04000000>; ++ ++ system_timer: timer@7c003000 { ++ compatible = "brcm,bcm2835-system-timer"; ++ reg = <0x7c003000 0x1000>; ++ interrupts = , ++ , ++ , ++ ; ++ clock-frequency = <1000000>; ++ }; ++ ++ firmwarekms: firmwarekms@7d503000 { ++ compatible = "raspberrypi,rpi-firmware-kms"; ++ /* SUN_L2 interrupt reg */ ++ reg = <0x7d503000 0x18>; ++ interrupt-parent = <&cpu_l2_irq>; ++ interrupts = <19>; ++ brcm,firmware = <&firmware>; ++ status = "disabled"; ++ }; ++ ++ mailbox: mailbox@7c013880 { ++ compatible = "brcm,bcm2835-mbox"; ++ reg = <0x7c013880 0x40>; ++ interrupts = ; ++ #mbox-cells = <0>; ++ }; ++ ++ pixelvalve0: pixelvalve@7c410000 { ++ compatible = "brcm,bcm2712-pixelvalve0"; ++ reg = <0x7c410000 0x100>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ pixelvalve1: pixelvalve@7c411000 { ++ compatible = "brcm,bcm2712-pixelvalve1"; ++ reg = <0x7c411000 0x100>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ usb: usb@7c480000 { ++ compatible = "brcm,bcm2835-usb"; ++ reg = <0x7c480000 0x10000>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clocks = <&clk_usb>; ++ clock-names = "otg"; ++ phys = <&usbphy>; ++ phy-names = "usb2-phy"; ++ status = "disabled"; ++ }; ++ ++ mop: mop@7c500000 { ++ compatible = "brcm,bcm2712-mop"; ++ reg = <0x7c500000 0x20>; ++ interrupt-parent = <&disp_intr>; ++ interrupts = <1>; ++ status = "disabled"; ++ }; ++ ++ moplet: moplet@7c501000 { ++ compatible = "brcm,bcm2712-moplet"; ++ reg = <0x7c501000 0x20>; ++ interrupt-parent = <&disp_intr>; ++ interrupts = <0>; ++ status = "disabled"; ++ }; ++ ++ disp_intr: interrupt-controller@7c502000 { ++ compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; ++ reg = <0x7c502000 0x30>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ dvp: clock@7c700000 { ++ compatible = "brcm,brcm2711-dvp"; ++ reg = <0x7c700000 0x10>; ++ clocks = <&clk_108MHz>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ ++ /* ++ * This node is the provider for the enable-method for ++ * bringing up secondary cores. ++ */ ++ local_intc: local_intc@7cd00000 { ++ compatible = "brcm,bcm2836-l1-intc"; ++ reg = <0x7cd00000 0x100>; ++ }; ++ ++ uart0: serial@7d001000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7d001000 0x200>; ++ interrupts = ; ++ clocks = <&clk_uart>, ++ <&clk_vpu>; ++ clock-names = "uartclk", "apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@7d001400 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7d001400 0x200>; ++ interrupts = ; ++ clocks = <&clk_uart>, ++ <&clk_vpu>; ++ clock-names = "uartclk", "apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; ++ status = "disabled"; ++ }; ++ ++ uart3: serial@7d001600 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7d001600 0x200>; ++ interrupts = ; ++ clocks = <&clk_uart>, ++ <&clk_vpu>; ++ clock-names = "uartclk", "apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; ++ status = "disabled"; ++ }; ++ ++ uart4: serial@7d001800 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7d001800 0x200>; ++ interrupts = ; ++ clocks = <&clk_uart>, ++ <&clk_vpu>; ++ clock-names = "uartclk", "apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; ++ status = "disabled"; ++ }; ++ ++ uart5: serial@7d001a00 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7d001a00 0x200>; ++ interrupts = ; ++ clocks = <&clk_uart>, ++ <&clk_vpu>; ++ clock-names = "uartclk", "apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; ++ status = "disabled"; ++ }; ++ ++ sdhost: mmc@7d002000 { ++ compatible = "brcm,bcm2835-sdhost"; ++ reg = <0x7d002000 0x100>; ++ //interrupts = ; ++ clocks = <&clk_vpu>; ++ status = "disabled"; ++ }; ++ ++ i2s: i2s@7d003000 { ++ compatible = "brcm,bcm2835-i2s"; ++ reg = <0x7d003000 0x24>; ++ //clocks = <&cprman BCM2835_CLOCK_PCM>; ++ status = "disabled"; ++ }; ++ ++ spi0: spi@7d004000 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7d004000 0x200>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi3: spi@7d004600 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7d004600 0x0200>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi4: spi@7d004800 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7d004800 0x0200>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi5: spi@7d004a00 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7d004a00 0x0200>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi6: spi@7d004c00 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7d004c00 0x0200>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@7d005000 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005000 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c@7d005600 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005600 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c4: i2c@7d005800 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005800 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c5: i2c@7d005a00 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005a00 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c6: i2c@7d005c00 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005c00 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c8: i2c@7d005e00 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005e00 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ pwm0: pwm@7d00c000 { ++ compatible = "brcm,bcm2835-pwm"; ++ reg = <0x7d00c000 0x28>; ++ assigned-clock-rates = <10000000>; ++ #pwm-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ pwm1: pwm@7d00c800 { ++ compatible = "brcm,bcm2835-pwm"; ++ reg = <0x7d00c800 0x28>; ++ assigned-clock-rates = <10000000>; ++ #pwm-cells = <2>; ++ status = "disabled"; ++ }; ++ ++ pm: watchdog@7d200000 { ++ compatible = "brcm,bcm2712-pm"; ++ reg = <0x7d200000 0x308>; ++ reg-names = "pm"; ++ #power-domain-cells = <1>; ++ #reset-cells = <1>; ++ //clocks = <&cprman BCM2835_CLOCK_V3D>, ++ // <&cprman BCM2835_CLOCK_PERI_IMAGE>, ++ // <&cprman BCM2835_CLOCK_H264>, ++ // <&cprman BCM2835_CLOCK_ISP>; ++ clock-names = "v3d", "peri_image", "h264", "isp"; ++ system-power-controller; ++ }; ++ ++ cprman: cprman@7d202000 { ++ compatible = "brcm,bcm2711-cprman"; ++ reg = <0x7d202000 0x2000>; ++ #clock-cells = <1>; ++ ++ /* CPRMAN derives almost everything from the ++ * platform's oscillator. However, the DSI ++ * pixel clocks come from the DSI analog PHY. ++ */ ++ clocks = <&clk_osc>; ++ status = "disabled"; ++ }; ++ ++ random: rng@7d208000 { ++ compatible = "brcm,bcm2711-rng200"; ++ reg = <0x7d208000 0x28>; ++ status = "okay"; ++ }; ++ ++ cpu_l2_irq: intc@7d503000 { ++ compatible = "brcm,l2-intc"; ++ reg = <0x7d503000 0x18>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ pinctrl: pinctrl@7d504100 { ++ compatible = "brcm,bcm2712-pinctrl"; ++ reg = <0x7d504100 0x30>; ++ ++ uarta_24_pins: uarta_24_pins { ++ pin_rts { ++ function = "uart0"; ++ pins = "gpio24"; ++ bias-disable; ++ }; ++ pin_cts { ++ function = "uart0"; ++ pins = "gpio25"; ++ bias-pull-up; ++ }; ++ pin_txd { ++ function = "uart0"; ++ pins = "gpio26"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart0"; ++ pins = "gpio27"; ++ bias-pull-up; ++ }; ++ }; ++ ++ sdio2_30_pins: sdio2_30_pins { ++ pin_clk { ++ function = "sd2"; ++ pins = "gpio30"; ++ bias-disable; ++ }; ++ pin_cmd { ++ function = "sd2"; ++ pins = "gpio31"; ++ bias-pull-up; ++ }; ++ pins_dat { ++ function = "sd2"; ++ pins = "gpio32", "gpio33", "gpio34", "gpio35"; ++ bias-pull-up; ++ }; ++ }; ++ }; ++ ++ ddc0: i2c@7d508200 { ++ compatible = "brcm,brcmstb-i2c"; ++ reg = <0x7d508200 0x58>; ++ interrupt-parent = <&bsc_irq>; ++ interrupts = <1>; ++ clock-frequency = <200000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ ddc1: i2c@7d508280 { ++ compatible = "brcm,brcmstb-i2c"; ++ reg = <0x7d508280 0x58>; ++ interrupt-parent = <&bsc_irq>; ++ interrupts = <2>; ++ clock-frequency = <200000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ bscd: i2c@7d508300 { ++ compatible = "brcm,brcmstb-i2c"; ++ reg = <0x7d508300 0x58>; ++ interrupt-parent = <&bsc_irq>; ++ interrupts = <0>; ++ clock-frequency = <200000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ bsc_irq: intc@7d508380 { ++ compatible = "brcm,bcm7271-l2-intc"; ++ reg = <0x7d508380 0x10>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ main_irq: intc@7d508400 { ++ compatible = "brcm,bcm7271-l2-intc"; ++ reg = <0x7d508400 0x10>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ gio: gpio@7d508500 { ++ compatible = "brcm,brcmstb-gpio"; ++ reg = <0x7d508500 0x40>; ++ interrupt-parent = <&main_irq>; ++ interrupts = <0>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ brcm,gpio-bank-widths = <32 22>; ++ brcm,gpio-direct; ++ }; ++ ++ uarta: serial@7d50c000 { ++ compatible = "brcm,bcm7271-uart"; ++ reg = <0x7d50c000 0x20>; ++ reg-names = "uart"; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ interrupts = ; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ uartb: serial@7d50d000 { ++ compatible = "brcm,bcm7271-uart"; ++ reg = <0x7d50d000 0x20>; ++ reg-names = "uart"; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ interrupts = ; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ uartc: serial@7d50e000 { ++ compatible = "brcm,bcm7271-uart"; ++ reg = <0x7d50e000 0x20>; ++ reg-names = "uart"; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ interrupts = ; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ aon_intr: interrupt-controller@7d510600 { ++ compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; ++ reg = <0x7d510600 0x30>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ pinctrl_aon: pinctrl@7d510700 { ++ compatible = "brcm,bcm2712-aon-pinctrl"; ++ reg = <0x7d510700 0x20>; ++ ++ i2c3_m4_agpio0_pins: i2c3_m4_agpio0_pins { ++ function = "vc_i2c3"; ++ pins = "aon_gpio0", "aon_gpio1"; ++ bias-pull-up; ++ }; ++ ++ bsc_m1_agpio13_pins: bsc_m1_agpio13_pins { ++ function = "bsc_m1"; ++ pins = "aon_gpio13", "aon_gpio14"; ++ bias-pull-up; ++ }; ++ ++ bsc_pmu_sgpio4_pins: bsc_pmu_sgpio4_pins { ++ function = "avs_pmu_bsc"; ++ pins = "aon_sgpio4", "aon_sgpio5"; ++ }; ++ ++ bsc_m2_sgpio4_pins: bsc_m2_sgpio4_pins { ++ function = "bsc_m2"; ++ pins = "aon_sgpio4", "aon_sgpio5"; ++ }; ++ ++ pwm_aon_agpio1_pins: pwm_aon_agpio1_pins { ++ function = "aon_pwm"; ++ pins = "aon_gpio1", "aon_gpio2"; ++ }; ++ ++ pwm_aon_agpio4_pins: pwm_aon_agpio4_pins { ++ function = "vc_pwm0"; ++ pins = "aon_gpio4", "aon_gpio5"; ++ }; ++ ++ pwm_aon_agpio7_pins: pwm_aon_agpio7_pins { ++ function = "aon_pwm"; ++ pins = "aon_gpio7", "aon_gpio9"; ++ }; ++ }; ++ ++ intc@7d517000 { ++ compatible = "brcm,bcm7271-l2-intc"; ++ reg = <0x7d517000 0x10>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ bscc: i2c@7d517a00 { ++ compatible = "brcm,brcmstb-i2c"; ++ reg = <0x7d517a00 0x58>; ++ interrupt-parent = <&bsc_aon_irq>; ++ interrupts = <0>; ++ clock-frequency = <200000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ pwm_aon: pwm@7d517a80 { ++ compatible = "brcm,bcm7038-pwm"; ++ reg = <0x7d517a80 0x28>; ++ #pwm-cells = <2>; ++ clocks = <&clk_27MHz>; ++ }; ++ ++ main_aon_irq: intc@7d517ac0 { ++ compatible = "brcm,bcm7271-l2-intc"; ++ reg = <0x7d517ac0 0x10>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ bsc_aon_irq: intc@7d517b00 { ++ compatible = "brcm,bcm7271-l2-intc"; ++ reg = <0x7d517b00 0x10>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ gio_aon: gpio@7d517c00 { ++ compatible = "brcm,brcmstb-gpio"; ++ reg = <0x7d517c00 0x40>; ++ interrupt-parent = <&main_aon_irq>; ++ interrupts = <0>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ brcm,gpio-bank-widths = <17 6>; ++ brcm,gpio-direct; ++ }; ++ ++ avs_monitor: avs-monitor@7d542000 { ++ compatible = "brcm,bcm2711-avs-monitor", ++ "syscon", "simple-mfd"; ++ reg = <0x7d542000 0xf00>; ++ status = "okay"; ++ ++ thermal: thermal { ++ compatible = "brcm,bcm2711-thermal"; ++ #thermal-sensor-cells = <0>; ++ }; ++ }; ++ ++ bsc_pmu: i2c@7d544000 { ++ compatible = "brcm,brcmstb-i2c"; ++ reg = <0x7d544000 0x58>; ++ interrupt-parent = <&bsc_aon_irq>; ++ interrupts = <1>; ++ clock-frequency = <200000>; ++ status = "disabled"; ++ }; ++ ++ hdmi0: hdmi@7ef00700 { ++ compatible = "brcm,bcm2712-hdmi0"; ++ reg = <0x7c701400 0x300>, ++ <0x7c701000 0x200>, ++ <0x7c701d00 0x300>, ++ <0x7c702000 0x80>, ++ <0x7c703800 0x200>, ++ <0x7c704000 0x800>, ++ <0x7c700100 0x80>, ++ <0x7d510800 0x100>, ++ <0x7c720000 0x100>; ++ reg-names = "hdmi", ++ "dvp", ++ "phy", ++ "rm", ++ "packet", ++ "metadata", ++ "csc", ++ "cec", ++ "hd"; ++ resets = <&dvp 1>; ++ interrupt-parent = <&aon_intr>; ++ interrupts = <1>, <2>, <3>, ++ <7>, <8>; ++ interrupt-names = "cec-tx", "cec-rx", "cec-low", ++ "hpd-connected", "hpd-removed"; ++ ddc = <&ddc0>; ++ dmas = <&dma32 10>; ++ dma-names = "audio-rx"; ++ status = "disabled"; ++ }; ++ ++ hdmi1: hdmi@7ef05700 { ++ compatible = "brcm,bcm2712-hdmi1"; ++ reg = <0x7c706400 0x300>, ++ <0x7c706000 0x200>, ++ <0x7c706d00 0x300>, ++ <0x7c707000 0x80>, ++ <0x7c708800 0x200>, ++ <0x7c709000 0x800>, ++ <0x7c700180 0x80>, ++ <0x7d511000 0x100>, ++ <0x7c720000 0x100>; ++ reg-names = "hdmi", ++ "dvp", ++ "phy", ++ "rm", ++ "packet", ++ "metadata", ++ "csc", ++ "cec", ++ "hd"; ++ ddc = <&ddc1>; ++ resets = <&dvp 2>; ++ interrupt-parent = <&aon_intr>; ++ interrupts = <11>, <12>, <13>, ++ <14>, <15>; ++ interrupt-names = "cec-tx", "cec-rx", "cec-low", ++ "hpd-connected", "hpd-removed"; ++ dmas = <&dma32 17>; ++ dma-names = "audio-rx"; ++ status = "disabled"; ++ }; ++ ++ sound: sound { ++ }; ++ }; ++ ++ arm-pmu { ++ compatible = "arm,cortex-a76-pmu"; ++ interrupts = , ++ , ++ , ++ ; ++ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = , ++ , ++ , ++ ; ++ /* This only applies to the ARMv7 stub */ ++ arm,cpu-registers-not-fw-configured; ++ }; ++ ++ cpus: cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit ++ ++ cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x000>; ++ enable-method = "psci"; ++ next-level-cache = <&l2_cache>; ++ }; ++ ++ cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x100>; ++ enable-method = "psci"; ++ next-level-cache = <&l2_cache>; ++ }; ++ ++ cpu2: cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x200>; ++ enable-method = "psci"; ++ next-level-cache = <&l2_cache>; ++ }; ++ ++ cpu3: cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x300>; ++ enable-method = "psci"; ++ next-level-cache = <&l2_cache>; ++ }; ++ ++ l2_cache: l2-cache { ++ compatible = "cache"; ++ next-level-cache = <&l3_cache>; ++ }; ++ ++ l3_cache: l3-cache { ++ compatible = "cache"; ++ }; ++ }; ++ ++ psci { ++ method = "smc"; ++ compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; ++ cpu_on = <0xc4000003>; ++ cpu_suspend = <0xc4000001>; ++ cpu_off = <0x84000002>; ++ }; ++ ++ axi: axi { ++ compatible = "simple-bus"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ ranges = <0x00 0x00000000 0x00 0x00000000 0x10 0x00000000>, ++ <0x10 0x00000000 0x10 0x00000000 0x01 0x00000000>, ++ <0x14 0x00000000 0x14 0x00000000 0x04 0x00000000>, ++ <0x18 0x00000000 0x18 0x00000000 0x04 0x00000000>, ++ <0x1c 0x00000000 0x1c 0x00000000 0x04 0x00000000>; ++ ++ dma-ranges = <0x00 0x00000000 0x00 0x00000000 0x10 0x00000000>, ++ <0x10 0x00000000 0x10 0x00000000 0x01 0x00000000>, ++ <0x14 0x00000000 0x14 0x00000000 0x04 0x00000000>, ++ <0x18 0x00000000 0x18 0x00000000 0x04 0x00000000>, ++ <0x1c 0x00000000 0x1c 0x00000000 0x04 0x00000000>; ++ ++ vc4: gpu { ++ compatible = "brcm,bcm2712-vc6"; ++ }; ++ ++ iommu2: iommu@5100 { ++ /* IOMMU2 for PISP-BE, HEVC; and (unused) H264 accelerators */ ++ compatible = "brcm,bcm2712-iommu"; ++ reg = <0x10 0x5100 0x0 0x80>; ++ cache = <&iommuc>; ++ #iommu-cells = <0>; ++ }; ++ ++ iommu4: iommu@5200 { ++ /* IOMMU4 for HVS, MPL/TXP; and (unused) Unicam, PISP-FE, MiniBVN */ ++ compatible = "brcm,bcm2712-iommu"; ++ reg = <0x10 0x5200 0x0 0x80>; ++ cache = <&iommuc>; ++ #iommu-cells = <0>; ++ #interconnect-cells = <0>; ++ }; ++ ++ iommu5: iommu@5280 { ++ /* IOMMU5 for PCIe2 (RP1); and (unused) BSTM */ ++ compatible = "brcm,bcm2712-iommu"; ++ reg = <0x10 0x5280 0x0 0x80>; ++ cache = <&iommuc>; ++ #iommu-cells = <0>; ++ dma-iova-offset = <0x10 0x00000000>; // HACK for RP1 masters over PCIe ++ }; ++ ++ iommuc: iommuc@5b00 { ++ compatible = "brcm,bcm2712-iommuc"; ++ reg = <0x10 0x5b00 0x0 0x80>; ++ }; ++ ++ dma32: dma@10000 { ++ compatible = "brcm,bcm2712-dma"; ++ reg = <0x10 0x00010000 0 0x600>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ ; ++ interrupt-names = "dma0", ++ "dma1", ++ "dma2", ++ "dma3", ++ "dma4", ++ "dma5"; ++ #dma-cells = <1>; ++ brcm,dma-channel-mask = <0x0035>; ++ }; ++ ++ dma40: dma@10600 { ++ compatible = "brcm,bcm2712-dma"; ++ reg = <0x10 0x00010600 0 0x600>; ++ interrupts = ++ , /* dma4 6 */ ++ , /* dma4 7 */ ++ , /* dma4 8 */ ++ , /* dma4 9 */ ++ , /* dma4 10 */ ++ ; /* dma4 11 */ ++ interrupt-names = "dma6", ++ "dma7", ++ "dma8", ++ "dma9", ++ "dma10", ++ "dma11"; ++ #dma-cells = <1>; ++ brcm,dma-channel-mask = <0x0fc0>; ++ }; ++ ++ // Single-lane Gen3 PCIe ++ // Outbound window at 0x14_000000-0x17_ffffff ++ pcie0: pcie@100000 { ++ compatible = "brcm,bcm2712-pcie"; ++ reg = <0x10 0x00100000 0x0 0x9310>; ++ device_type = "pci"; ++ max-link-speed = <2>; ++ #address-cells = <3>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ /* ++ * Unused interrupts: ++ * 208: AER ++ * 215: NMI ++ * 216: PME ++ */ ++ interrupt-parent = <&gicv2>; ++ interrupts = , ++ ; ++ interrupt-names = "pcie", "msi"; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 209 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 2 &gicv2 GIC_SPI 210 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 3 &gicv2 GIC_SPI 211 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 4 &gicv2 GIC_SPI 212 ++ IRQ_TYPE_LEVEL_HIGH>; ++ resets = <&bcm_reset 5>, <&bcm_reset 42>, <&pcie_rescal>; ++ reset-names = "swinit", "bridge", "rescal"; ++ msi-controller; ++ msi-parent = <&pcie0>; ++ ++ ranges = <0x02000000 0x00 0x00000000 ++ 0x17 0x00000000 ++ 0x0 0xfffffffc>, ++ <0x43000000 0x04 0x00000000 ++ 0x14 0x00000000 ++ 0x3 0x00000000>; ++ ++ dma-ranges = <0x43000000 0x10 0x00000000 ++ 0x00 0x00000000 ++ 0x10 0x00000000>; ++ ++ status = "disabled"; ++ }; ++ ++ // Single-lane Gen3 PCIe ++ // Outbound window at 0x18_000000-0x1b_ffffff ++ pcie1: pcie@110000 { ++ compatible = "brcm,bcm2712-pcie"; ++ reg = <0x10 0x00110000 0x0 0x9310>; ++ device_type = "pci"; ++ max-link-speed = <2>; ++ #address-cells = <3>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ /* ++ * Unused interrupts: ++ * 218: AER ++ * 225: NMI ++ * 226: PME ++ */ ++ interrupt-parent = <&gicv2>; ++ interrupts = , ++ ; ++ interrupt-names = "pcie", "msi"; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 219 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 2 &gicv2 GIC_SPI 220 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 3 &gicv2 GIC_SPI 221 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 4 &gicv2 GIC_SPI 222 ++ IRQ_TYPE_LEVEL_HIGH>; ++ resets = <&bcm_reset 7>, <&bcm_reset 43>, <&pcie_rescal>; ++ reset-names = "swinit", "bridge", "rescal"; ++ msi-controller; ++ msi-parent = <&mip1>; ++ ++ ranges = <0x02000000 0x00 0x00000000 ++ 0x1b 0x00000000 ++ 0x00 0xfffffffc>, ++ <0x43000000 0x04 0x00000000 ++ 0x18 0x00000000 ++ 0x03 0x00000000>; ++ ++ dma-ranges = <0x03000000 0x10 0x00000000 ++ 0x00 0x00000000 ++ 0x10 0x00000000>; ++ ++ brcm,enable-l1ss; ++ status = "disabled"; ++ }; ++ ++ pcie_rescal: reset-controller@119500 { ++ compatible = "brcm,bcm7216-pcie-sata-rescal"; ++ reg = <0x10 0x00119500 0x0 0x10>; ++ #reset-cells = <0>; ++ }; ++ ++ // Quad-lane Gen3 PCIe ++ // Outbound window at 0x1c_000000-0x1f_ffffff ++ pcie2: pcie@120000 { ++ compatible = "brcm,bcm2712-pcie"; ++ reg = <0x10 0x00120000 0x0 0x9310>; ++ device_type = "pci"; ++ max-link-speed = <2>; ++ #address-cells = <3>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ /* ++ * Unused interrupts: ++ * 228: AER ++ * 235: NMI ++ * 236: PME ++ */ ++ interrupt-parent = <&gicv2>; ++ interrupts = , ++ ; ++ interrupt-names = "pcie", "msi"; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 229 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 2 &gicv2 GIC_SPI 230 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 3 &gicv2 GIC_SPI 231 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 4 &gicv2 GIC_SPI 232 ++ IRQ_TYPE_LEVEL_HIGH>; ++ resets = <&bcm_reset 32>, <&bcm_reset 44>, <&pcie_rescal>; ++ reset-names = "swinit", "bridge", "rescal"; ++ msi-controller; ++ msi-parent = <&mip0>; ++ ++ // ~4GB, 32-bit, not-prefetchable at PCIe 00_00000000 ++ ranges = <0x02000000 0x00 0x00000000 ++ 0x1f 0x00000000 ++ 0x0 0xfffffffc>, ++ // 12GB, 64-bit, prefetchable at PCIe 04_00000000 ++ <0x43000000 0x04 0x00000000 ++ 0x1c 0x00000000 ++ 0x03 0x00000000>; ++ ++ // 64GB system RAM space at PCIe 10_00000000 ++ dma-ranges = <0x02000000 0x00 0x00000000 ++ 0x1f 0x00000000 ++ 0x00 0x00400000>, ++ <0x43000000 0x10 0x00000000 ++ 0x00 0x00000000 ++ 0x10 0x00000000>; ++ ++ brcm,enable-mps-rcb; ++ brcm,enable-l1ss; ++ status = "disabled"; ++ }; ++ ++ mip0: msi-controller@130000 { ++ compatible = "brcm,bcm2712-mip-intc"; ++ reg = <0x10 0x00130000 0x0 0xc0>; ++ msi-controller; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ brcm,msi-base-spi = <128>; ++ brcm,msi-num-spis = <64>; ++ brcm,msi-offset = <0>; ++ brcm,msi-pci-addr = <0xff 0xfffff000>; ++ }; ++ ++ mip1: msi-controller@131000 { ++ compatible = "brcm,bcm2712-mip-intc"; ++ reg = <0x10 0x00131000 0x0 0xc0>; ++ msi-controller; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ brcm,msi-base-spi = <247>; ++ /* Actually 20 total, but the others are ++ * both sparse and non-consecutive */ ++ brcm,msi-num-spis = <8>; ++ brcm,msi-offset = <8>; ++ brcm,msi-pci-addr = <0xff 0xffffe000>; ++ }; ++ ++ genet: ethernet@1300000 { ++ compatible = "brcm,bcm2711-genet-v5"; ++ reg = <0x10 0x01300000 0x0 0x20010>; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ interrupts = , ++ ; ++ status = "disabled"; ++ phy-mode = "rgmii"; ++ fixed-link = <0x0 0x1 0x3e8 0x0 0x0>; ++ phy-speed = <0x3e8>; ++ phy-id = <0x101>; ++ phy-type = <0x6>; ++ local-mac-address = [ 00 10 18 d8 45 de ]; ++ device_type = "network"; ++ ++ genet_mdio: mdio@e14 { ++ compatible = "brcm,genet-mdio-v5"; ++ reg = <0xe14 0x8>; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ }; ++ }; ++ ++ syscon_piarbctl: syscon@400018 { ++ compatible = "brcm,syscon-piarbctl", "syscon", "simple-mfd"; ++ reg = <0x10 0x00400018 0x0 0x18>; ++ }; ++ ++ rpivid: codec@800000 { ++ compatible = "raspberrypi,rpivid-vid-decoder"; ++ reg = <0x10 0x00800000 0x0 0x10000>, /* HEVC */ ++ <0x10 0x00840000 0x0 0x1000>; /* INTC */ ++ reg-names = "hevc", ++ "intc"; ++ ++ interrupts = ; ++ ++ clocks = <&firmware_clocks 11>; ++ clock-names = "hevc"; ++ status = "disabled"; ++ }; ++ ++ sdio1: mmc@fff000 { ++ compatible = "brcm,bcm2712-sdhci"; ++ reg = <0x10 0x00fff000 0x0 0x260>, ++ <0x10 0x00fff400 0x0 0x200>, ++ <0x10 0x015040b0 0x0 0x4>, // Bus isolation control ++ <0x10 0x015200f0 0x0 0x24>; // LCPLL control misc0-8 ++ reg-names = "host", "cfg", "busisol", "lcpll"; ++ interrupts = ; ++ clocks = <&clk_emmc2>; ++ sdhci-caps-mask = <0x0000C000 0x0>; ++ sdhci-caps = <0x0 0x0>; ++ supports-cqe; ++ mmc-ddr-3_3v; ++ }; ++ ++ sdio2: mmc@1100000 { ++ compatible = "brcm,bcm2712-sdhci"; ++ reg = <0x10 0x01100000 0x0 0x260>, ++ <0x10 0x01100400 0x0 0x200>; ++ reg-names = "host", "cfg"; ++ interrupts = ; ++ clocks = <&clk_emmc2>; ++ sdhci-caps-mask = <0x0000C000 0x0>; ++ sdhci-caps = <0x0 0x0>; ++ supports-cqe; ++ mmc-ddr-3_3v; ++ status = "disabled"; ++ }; ++ ++ sdio0: mmc@1108000 { ++ compatible = "brcm,bcm2711-emmc2"; ++ reg = <0x10 0x01108000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&clk_emmc2>; ++ mmc-ddr-3_3v; ++ status = "disabled"; ++ }; ++ ++ bcm_reset: reset-controller@1504318 { ++ compatible = "brcm,brcmstb-reset"; ++ reg = <0x10 0x01504318 0x0 0x30>; ++ #reset-cells = <1>; ++ }; ++ ++ v3d: v3d@2000000 { ++ compatible = "brcm,2712-v3d"; ++ reg = <0x10 0x02000000 0x0 0x4000>, ++ <0x10 0x02008000 0x0 0x6000>; ++ reg-names = "hub", "core0"; ++ ++ power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>; ++ resets = <&pm BCM2835_RESET_V3D>; ++ clocks = <&firmware_clocks 5>; ++ clocks-names = "v3d"; ++ interrupts = , ++ ; ++ status = "disabled"; ++ }; ++ ++ gicv2: interrupt-controller@7fff9000 { ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ compatible = "arm,gic-400"; ++ reg = <0x10 0x7fff9000 0x0 0x1000>, ++ <0x10 0x7fffa000 0x0 0x2000>, ++ <0x10 0x7fffc000 0x0 0x2000>, ++ <0x10 0x7fffe000 0x0 0x2000>; ++ interrupts = ; ++ }; ++ ++ pisp_be: pisp_be@880000 { ++ compatible = "raspberrypi,pispbe"; ++ reg = <0x10 0x00880000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&firmware_clocks 7>; ++ clocks-names = "isp_be"; ++ status = "okay"; ++ iommus = <&iommu2>; ++ }; ++ }; ++ ++ clocks { ++ /* The oscillator is the root of the clock tree. */ ++ clk_osc: clk-osc { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "osc"; ++ clock-frequency = <54000000>; ++ }; ++ ++ clk_usb: clk-usb { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "otg"; ++ clock-frequency = <480000000>; ++ }; ++ ++ clk_vpu: clk_vpu { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <750000000>; ++ clock-output-names = "vpu-clock"; ++ }; ++ ++ clk_uart: clk_uart { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <9216000>; ++ clock-output-names = "uart-clock"; ++ }; ++ ++ clk_emmc2: clk_emmc2 { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <54000000>; ++ clock-output-names = "emmc2-clock"; ++ }; ++ }; ++ ++ usbphy: phy { ++ compatible = "usb-nop-xceiv"; ++ #phy-cells = <0>; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -49,8 +49,10 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + dionaudio-loco.dtbo \ + dionaudio-loco-v2.dtbo \ + disable-bt.dtbo \ ++ disable-bt-pi5.dtbo \ + disable-emmc2.dtbo \ + disable-wifi.dtbo \ ++ disable-wifi-pi5.dtbo \ + dpi18.dtbo \ + dpi18cpadhi.dtbo \ + dpi24.dtbo \ +@@ -106,8 +108,12 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + i2c-rtc-gpio.dtbo \ + i2c-sensor.dtbo \ + i2c0.dtbo \ ++ i2c0-pi5.dtbo \ + i2c1.dtbo \ ++ i2c1-pi5.dtbo \ ++ i2c2-pi5.dtbo \ + i2c3.dtbo \ ++ i2c3-pi5.dtbo \ + i2c4.dtbo \ + i2c5.dtbo \ + i2c6.dtbo \ +@@ -150,10 +156,15 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + media-center.dtbo \ + merus-amp.dtbo \ + midi-uart0.dtbo \ ++ midi-uart0-pi5.dtbo \ + midi-uart1.dtbo \ ++ midi-uart1-pi5.dtbo \ + midi-uart2.dtbo \ ++ midi-uart2-pi5.dtbo \ + midi-uart3.dtbo \ ++ midi-uart3-pi5.dtbo \ + midi-uart4.dtbo \ ++ midi-uart4-pi5.dtbo \ + midi-uart5.dtbo \ + minipitft13.dtbo \ + miniuart-bt.dtbo \ +@@ -231,14 +242,20 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + spi1-2cs.dtbo \ + spi1-3cs.dtbo \ + spi2-1cs.dtbo \ ++ spi2-1cs-pi5.dtbo \ + spi2-2cs.dtbo \ ++ spi2-2cs-pi5.dtbo \ + spi2-3cs.dtbo \ + spi3-1cs.dtbo \ ++ spi3-1cs-pi5.dtbo \ + spi3-2cs.dtbo \ ++ spi3-2cs-pi5.dtbo \ + spi4-1cs.dtbo \ + spi4-2cs.dtbo \ + spi5-1cs.dtbo \ ++ spi5-1cs-pi5.dtbo \ + spi5-2cs.dtbo \ ++ spi5-2cs-pi5.dtbo \ + spi6-1cs.dtbo \ + spi6-2cs.dtbo \ + ssd1306.dtbo \ +@@ -253,10 +270,15 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + tpm-slb9670.dtbo \ + tpm-slb9673.dtbo \ + uart0.dtbo \ ++ uart0-pi5.dtbo \ + uart1.dtbo \ ++ uart1-pi5.dtbo \ + uart2.dtbo \ ++ uart2-pi5.dtbo \ + uart3.dtbo \ ++ uart3-pi5.dtbo \ + uart4.dtbo \ ++ uart4-pi5.dtbo \ + uart5.dtbo \ + udrc.dtbo \ + ugreen-dabboard.dtbo \ +@@ -276,6 +298,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + vc4-kms-kippah-7inch.dtbo \ + vc4-kms-v3d.dtbo \ + vc4-kms-v3d-pi4.dtbo \ ++ vc4-kms-v3d-pi5.dtbo \ + vc4-kms-vga666.dtbo \ + vga666.dtbo \ + vl805.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -151,6 +151,9 @@ Params: + bdaddr=06:05:04:03:02:01 + will set the BDADDR to 01:02:03:04:05:06. + ++ button_debounce Set the debounce delay (in ms) on the power/ ++ shutdown button (default 50ms) ++ + cam0_reg Enables CAM 0 regulator. + Only required on CM1 & 3. + +@@ -167,6 +170,9 @@ Params: + Default of GPIO expander 5 on CM4, but override + switches to normal GPIO. + ++ cooling_fan Enables the Pi 5 cooling fan (enabled ++ automatically by the firmware) ++ + eee Enable Energy Efficient Ethernet support for + compatible devices (default "on"). See also + "tx_lpi_timer". Pi3B+ only. +@@ -206,23 +212,29 @@ Params: + hdmi Set to "off" to disable the HDMI interface + (default "on") + ++ i2c An alias for i2c_arm ++ + i2c_arm Set to "on" to enable the ARM's i2c interface + (default "off") + ++ i2c_arm_baudrate Set the baudrate of the ARM's i2c interface ++ (default "100000") ++ ++ i2c_baudrate An alias for i2c_arm_baudrate ++ ++ i2c_csi_dsi Set to "on" to enable the i2c_csi_dsi interface ++ ++ i2c_csi_dsi0 Set to "on" to enable the i2c_csi_dsi0 interface ++ ++ i2c_csi_dsi1 Set to "on" to enable the i2c_csi_dsi1 interface ++ + i2c_vc Set to "on" to enable the i2c interface + usually reserved for the VideoCore processor + (default "off") + +- i2c An alias for i2c_arm +- +- i2c_arm_baudrate Set the baudrate of the ARM's i2c interface +- (default "100000") +- + i2c_vc_baudrate Set the baudrate of the VideoCore i2c interface + (default "100000") + +- i2c_baudrate An alias for i2c_arm_baudrate +- + i2s Set to "on" to enable the i2s interface + (default "off") + +@@ -237,11 +249,23 @@ Params: + krnbt_baudrate Set the baudrate of the PL011 UART when used + with krnbt=on + ++ nvme Alias for "pciex1" (2712 only) ++ + pcie Set to "off" to disable the PCIe interface + (default "on") + (2711 only, but not applicable on CM4S) + N.B. USB-A ports on 4B are subsequently disabled + ++ pciex1 Set to "on" to enable the external PCIe link ++ (2712 only, default "off") ++ ++ pciex1_gen Sets the PCIe "GEN"/speed for the external PCIe ++ link (2712 only, default "2") ++ ++ pciex1_no_l0s Set to "on" to disable ASPM L0s on the external ++ PCIe link for devices that have broken ++ implementations (2712 only, default "off") ++ + spi Set to "on" to enable the spi interfaces + (default "off") + +@@ -252,6 +276,11 @@ Params: + random Set to "on" to enable the hardware random + number generator (default "on") + ++ rtc_bbat_vchg Set the RTC backup battery charging voltage in ++ microvolts. If set to 0 or not specified, the ++ trickle charger is disabled. ++ (2712 only, default "0") ++ + sd Set to "off" to disable the SD card (or eMMC on + non-lite SKU of CM4). + (default "on") +@@ -276,18 +305,30 @@ Params: + sdio_overclock Clock (in MHz) to use when the MMC framework + requests 50MHz for the SDIO/WLAN interface. + ++ suspend Make the power button trigger a suspend rather ++ than a power-off (2712 only, default "off") ++ + tx_lpi_timer Set the delay in microseconds between going idle + and entering the low power state (default 600). + Requires EEE to be enabled - see "eee". + + uart0 Set to "off" to disable uart0 (default "on") + ++ uart0_console Move the kernel boot console to UART0 on pins ++ 6, 8 and 10 of the 40-way header (2712 only, ++ default "off") ++ + uart1 Set to "on" or "off" to enable or disable uart1 + (default varies) + + watchdog Set to "on" to enable the hardware watchdog + (default "off") + ++ wifiaddr Set an alternative WiFi MAC address. ++ The value should be a 6-byte hexadecimal value, ++ with or without colon separators, written in the ++ natural (big-endian) order. ++ + act_led_trigger Choose which activity the LED tracks. + Use "heartbeat" for a nice load indicator. + (default "mmc") +@@ -919,14 +960,16 @@ Params: 24db_digital_gain Allow ga + + + Name: disable-bt +-Info: Disable onboard Bluetooth on Pi 3B, 3B+, 3A+, 4B and Zero W, restoring +- UART0/ttyAMA0 over GPIOs 14 & 15. +- N.B. To disable the systemd service that initialises the modem so it +- doesn't use the UART, use 'sudo systemctl disable hciuart'. ++Info: Disable onboard Bluetooth on Bluetooth-capable Raspberry Pis. On Pis ++ prior to Pi 5 this restores UART0/ttyAMA0 over GPIOs 14 & 15. + Load: dtoverlay=disable-bt + Params: + + ++Name: disable-bt-pi5 ++Info: See disable-bt ++ ++ + Name: disable-emmc2 + Info: Disable EMMC2 controller on BCM2711. + The allows the onboard EMMC storage on Compute Module 4 to be disabled +@@ -936,11 +979,15 @@ Params: + + + Name: disable-wifi +-Info: Disable onboard WLAN on Pi 3B, 3B+, 3A+, 4B and Zero W. ++Info: Disable onboard WLAN on WiFi-capable Raspberry Pis. + Load: dtoverlay=disable-wifi + Params: + + ++Name: disable-wifi-pi5 ++Info: See disable-wifi ++ ++ + Name: dpi18 + Info: Overlay for a generic 18-bit DPI display + This uses GPIOs 0-21 (so no I2C, uart etc.), and activates the output +@@ -2233,6 +2280,15 @@ Info: Deprecated, legacy version of i2 + Load: + + ++Name: i2c0-pi5 ++Info: Enable i2c0 (Pi 5 only) ++Load: dtoverlay=i2c0-pi5,= ++Params: pins_0_1 Use GPIOs 0 and 1 (default) ++ pins_8_9 Use GPIOs 8 and 9 ++ baudrate Set the baudrate for the interface (default ++ "100000") ++ ++ + Name: i2c1 + Info: Change i2c1 pin usage. Not all pin combinations are usable on all + platforms - platforms other then Compute Modules can only use this +@@ -2249,6 +2305,24 @@ Info: Deprecated, legacy version of i2 + Load: + + ++Name: i2c1-pi5 ++Info: Enable i2c1 (Pi 5 only) ++Load: dtoverlay=i2c1-pi5,= ++Params: pins_2_3 Use GPIOs 2 and 3 (default) ++ pins_10_11 Use GPIOs 10 and 11 ++ baudrate Set the baudrate for the interface (default ++ "100000") ++ ++ ++Name: i2c2-pi5 ++Info: Enable i2c2 (Pi 5 only) ++Load: dtoverlay=i2c2-pi5,= ++Params: pins_4_5 Use GPIOs 4 and 5 (default) ++ pins_12_13 Use GPIOs 12 and 13 ++ baudrate Set the baudrate for the interface (default ++ "100000") ++ ++ + Name: i2c3 + Info: Enable the i2c3 bus. BCM2711 only. + Load: dtoverlay=i2c3, +@@ -2258,6 +2332,16 @@ Params: pins_2_3 Use GPIO + "100000") + + ++Name: i2c3-pi5 ++Info: Enable i2c3 (Pi 5 only) ++Load: dtoverlay=i2c3-pi5,= ++Params: pins_6_7 Use GPIOs 6 and 7 (default) ++ pins_14_15 Use GPIOs 14 and 15 ++ pins_22_23 Use GPIOs 22 and 23 ++ baudrate Set the baudrate for the interface (default ++ "100000") ++ ++ + Name: i2c4 + Info: Enable the i2c4 bus. BCM2711 only. + Load: dtoverlay=i2c4, +@@ -2869,6 +2953,10 @@ Load: dtoverlay=midi-uart0 + Params: + + ++Name: midi-uart0-pi5 ++Info: See midi-uart0 (this is the Pi 5 version) ++ ++ + Name: midi-uart1 + Info: Configures UART1 (ttyS0) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI +@@ -2876,29 +2964,45 @@ Load: dtoverlay=midi-uart1 + Params: + + ++Name: midi-uart1-pi5 ++Info: See midi-uart1 (this is the Pi 5 version) ++ ++ + Name: midi-uart2 +-Info: Configures UART2 (ttyAMA1) so that a requested 38.4kbaud actually gets ++Info: Configures UART2 (ttyAMA2) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI + Load: dtoverlay=midi-uart2 + Params: + + ++Name: midi-uart2-pi5 ++Info: See midi-uart2 (this is the Pi 5 version) ++ ++ + Name: midi-uart3 +-Info: Configures UART3 (ttyAMA2) so that a requested 38.4kbaud actually gets ++Info: Configures UART3 (ttyAMA3) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI + Load: dtoverlay=midi-uart3 + Params: + + ++Name: midi-uart3-pi5 ++Info: See midi-uart3 (this is the Pi 5 version) ++ ++ + Name: midi-uart4 +-Info: Configures UART4 (ttyAMA3) so that a requested 38.4kbaud actually gets ++Info: Configures UART4 (ttyAMA4) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI + Load: dtoverlay=midi-uart4 + Params: + + ++Name: midi-uart4-pi5 ++Info: See midi-uart4 (this is the Pi 5 version) ++ ++ + Name: midi-uart5 +-Info: Configures UART5 (ttyAMA4) so that a requested 38.4kbaud actually gets ++Info: Configures UART5 (ttyAMA5) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI + Load: dtoverlay=midi-uart5 + Params: +@@ -3921,105 +4025,131 @@ Name: spi1-1cs + Info: Enables spi1 with a single chip select (CS) line and associated spidev + dev node. The gpio pin number for the CS line and spidev device node + creation are configurable. +- N.B.: spi1 is only accessible on devices with a 40pin header, eg: +- A+, B+, Zero and PI2 B; as well as the Compute Module. ++ N.B.: spi1 is not accessible on old Pis without a 40-pin header. + Load: dtoverlay=spi1-1cs,= + Params: cs0_pin GPIO pin for CS0 (default 18 - BCM SPI1_CE0). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.0 (default +- is 'okay' or enabled). ++ is 'on' or enabled). + + + Name: spi1-2cs + Info: Enables spi1 with two chip select (CS) lines and associated spidev + dev nodes. The gpio pin numbers for the CS lines and spidev device node + creation are configurable. +- N.B.: spi1 is only accessible on devices with a 40pin header, eg: +- A+, B+, Zero and PI2 B; as well as the Compute Module. ++ N.B.: spi1 is not accessible on old Pis without a 40-pin header. + Load: dtoverlay=spi1-2cs,= + Params: cs0_pin GPIO pin for CS0 (default 18 - BCM SPI1_CE0). + cs1_pin GPIO pin for CS1 (default 17 - BCM SPI1_CE1). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.0 (default +- is 'okay' or enabled). +- cs1_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.1 (default +- is 'okay' or enabled). ++ is 'on' or enabled). + + + Name: spi1-3cs + Info: Enables spi1 with three chip select (CS) lines and associated spidev + dev nodes. The gpio pin numbers for the CS lines and spidev device node + creation are configurable. +- N.B.: spi1 is only accessible on devices with a 40pin header, eg: +- A+, B+, Zero and PI2 B; as well as the Compute Module. ++ N.B.: spi1 is not accessible on old Pis without a 40-pin header. + Load: dtoverlay=spi1-3cs,= + Params: cs0_pin GPIO pin for CS0 (default 18 - BCM SPI1_CE0). + cs1_pin GPIO pin for CS1 (default 17 - BCM SPI1_CE1). + cs2_pin GPIO pin for CS2 (default 16 - BCM SPI1_CE2). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.0 (default +- is 'okay' or enabled). +- cs1_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.1 (default +- is 'okay' or enabled). +- cs2_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs2_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev1.2 (default +- is 'okay' or enabled). ++ is 'on' or enabled). + + + Name: spi2-1cs +-Info: Enables spi2 with a single chip select (CS) line and associated spidev +- dev node. The gpio pin number for the CS line and spidev device node +- creation are configurable. +- N.B.: spi2 is only accessible with the Compute Module. ++Info: Enables spi2 on GPIOs 40-42 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin number for the CS line and ++ spidev device node creation are configurable. spi2-2cs-pi5 is ++ substituted on a Pi 5. ++ N.B.: spi2 is only accessible with the Compute Module or Pi 5. + Load: dtoverlay=spi2-1cs,= + Params: cs0_pin GPIO pin for CS0 (default 43 - BCM SPI2_CE0). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.0 (default +- is 'okay' or enabled). ++ is 'on' or enabled). ++ ++ ++Name: spi2-1cs-pi5 ++Info: Enables spi2 on GPIOs 1-3 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin number for the CS line and ++ spidev device node creation are configurable. Pi 5 only. ++Load: dtoverlay=spi2-1cs-pi5,= ++Params: cs0_pin GPIO pin for CS0 (default 0). ++ cs0_spidev Set to 'off' to stop the creation of a ++ userspace device node /dev/spidev2.0 (default ++ is 'on' or enabled). + + + Name: spi2-2cs +-Info: Enables spi2 with two chip select (CS) lines and associated spidev +- dev nodes. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. +- N.B.: spi2 is only accessible with the Compute Module. ++Info: Enables spi2 on GPIOs 40-42 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. spi2-2cs-pi5 is ++ substituted on a Pi 5. ++ N.B.: spi2 is only accessible with the Compute Module or Pi 5. + Load: dtoverlay=spi2-2cs,= + Params: cs0_pin GPIO pin for CS0 (default 43 - BCM SPI2_CE0). + cs1_pin GPIO pin for CS1 (default 44 - BCM SPI2_CE1). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a ++ userspace device node /dev/spidev2.0 (default ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to stop the creation of a ++ userspace device node /dev/spidev2.1 (default ++ is 'on' or enabled). ++ ++ ++Name: spi2-2cs-pi5 ++Info: Enables spi2 on GPIOs 1-3 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. Pi 5 only. ++Load: dtoverlay=spi2-2cs-pi5,= ++Params: cs0_pin GPIO pin for CS0 (default 0). ++ cs1_pin GPIO pin for CS1 (default 24). ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.0 (default +- is 'okay' or enabled). +- cs1_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.1 (default +- is 'okay' or enabled). ++ is 'on' or enabled). + + + Name: spi2-3cs +-Info: Enables spi2 with three chip select (CS) lines and associated spidev +- dev nodes. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. +- N.B.: spi2 is only accessible with the Compute Module. ++Info: Enables spi2 on GPIOs 40-42 with three chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. ++ N.B.: spi2 is only accessible with the Compute Module or Pi 5. + Load: dtoverlay=spi2-3cs,= + Params: cs0_pin GPIO pin for CS0 (default 43 - BCM SPI2_CE0). + cs1_pin GPIO pin for CS1 (default 44 - BCM SPI2_CE1). + cs2_pin GPIO pin for CS2 (default 45 - BCM SPI2_CE2). +- cs0_spidev Set to 'disabled' to stop the creation of a ++ cs0_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.0 (default +- is 'okay' or enabled). +- cs1_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.1 (default +- is 'okay' or enabled). +- cs2_spidev Set to 'disabled' to stop the creation of a ++ is 'on' or enabled). ++ cs2_spidev Set to 'off' to stop the creation of a + userspace device node /dev/spidev2.2 (default +- is 'okay' or enabled). ++ is 'on' or enabled). + + + Name: spi3-1cs +-Info: Enables spi3 with a single chip select (CS) line and associated spidev +- dev node. The gpio pin number for the CS line and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi3 on GPIOs 1-3 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin number for the CS line and ++ spidev device node creation are configurable. BCM2711 only, ++ spi3-1cs-pi5 is substituted on Pi 5. + Load: dtoverlay=spi3-1cs,= + Params: cs0_pin GPIO pin for CS0 (default 0 - BCM SPI3_CE0). + cs0_spidev Set to 'off' to prevent the creation of a +@@ -4027,10 +4157,22 @@ Params: cs0_pin GPIO pin + is 'on' or enabled). + + ++Name: spi3-1cs-pi5 ++Info: Enables spi3 on GPIOs 5-7 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin number for the CS line and ++ spidev device node creation are configurable. Pi 5 only. ++Load: dtoverlay=spi3-1cs-pi5,= ++Params: cs0_pin GPIO pin for CS0 (default 4). ++ cs0_spidev Set to 'off' to prevent the creation of a ++ userspace device node /dev/spidev3.0 (default ++ is 'on' or enabled). ++ ++ + Name: spi3-2cs +-Info: Enables spi3 with two chip select (CS) lines and associated spidev +- dev nodes. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi3 on GPIO2 1-3 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. BCM2711 only, ++ spi3-2cs-pi5 is substituted on Pi 5. + Load: dtoverlay=spi3-2cs,= + Params: cs0_pin GPIO pin for CS0 (default 0 - BCM SPI3_CE0). + cs1_pin GPIO pin for CS1 (default 24 - BCM SPI3_CE1). +@@ -4042,10 +4184,25 @@ Params: cs0_pin GPIO pin + is 'on' or enabled). + + ++Name: spi3-2cs-pi5 ++Info: Enables spi3 on GPIOs 5-7 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. Pi 5 only. ++Load: dtoverlay=spi3-2cs-pi5,= ++Params: cs0_pin GPIO pin for CS0 (default 4). ++ cs1_pin GPIO pin for CS1 (default 25). ++ cs0_spidev Set to 'off' to prevent the creation of a ++ userspace device node /dev/spidev3.0 (default ++ is 'on' or enabled). ++ cs1_spidev Set to 'off' to prevent the creation of a ++ userspace device node /dev/spidev3.1 (default ++ is 'on' or enabled). ++ ++ + Name: spi4-1cs +-Info: Enables spi4 with a single chip select (CS) line and associated spidev +- dev node. The gpio pin number for the CS line and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi4 on GPIOs 5-7 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin number for the CS line and ++ spidev device node creation are configurable. BCM2711 only. + Load: dtoverlay=spi4-1cs,= + Params: cs0_pin GPIO pin for CS0 (default 4 - BCM SPI4_CE0). + cs0_spidev Set to 'off' to prevent the creation of a +@@ -4054,9 +4211,9 @@ Params: cs0_pin GPIO pin + + + Name: spi4-2cs +-Info: Enables spi4 with two chip select (CS) lines and associated spidev +- dev nodes. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi4 on GPIOs 5-6 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. BCM2711 only. + Load: dtoverlay=spi4-2cs,= + Params: cs0_pin GPIO pin for CS0 (default 4 - BCM SPI4_CE0). + cs1_pin GPIO pin for CS1 (default 25 - BCM SPI4_CE1). +@@ -4069,23 +4226,27 @@ Params: cs0_pin GPIO pin + + + Name: spi5-1cs +-Info: Enables spi5 with a single chip select (CS) line and associated spidev +- dev node. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi5 on GPIOs 13-15 with a single chip select (CS) line and ++ associated spidev dev node. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. BCM2711 and Pi 5. + Load: dtoverlay=spi5-1cs,= +-Params: cs0_pin GPIO pin for CS0 (default 12 - BCM SPI5_CE0). ++Params: cs0_pin GPIO pin for CS0 (default 12). + cs0_spidev Set to 'off' to prevent the creation of a + userspace device node /dev/spidev5.0 (default + is 'on' or enabled). + + ++Name: spi5-1cs-pi5 ++Info: See spi5-1cs ++ ++ + Name: spi5-2cs +-Info: Enables spi5 with two chip select (CS) lines and associated spidev +- dev nodes. The gpio pin numbers for the CS lines and spidev device node +- creation are configurable. BCM2711 only. ++Info: Enables spi5 on GPIOs 13-15 with two chip select (CS) lines and ++ associated spidev dev nodes. The gpio pin numbers for the CS lines and ++ spidev device node creation are configurable. BCM2711 and Pi 5. + Load: dtoverlay=spi5-2cs,= +-Params: cs0_pin GPIO pin for CS0 (default 12 - BCM SPI5_CE0). +- cs1_pin GPIO pin for CS1 (default 26 - BCM SPI5_CE1). ++Params: cs0_pin GPIO pin for CS0 (default 12). ++ cs1_pin GPIO pin for CS1 (default 26). + cs0_spidev Set to 'off' to prevent the creation of a + userspace device node /dev/spidev5.0 (default + is 'on' or enabled). +@@ -4094,6 +4255,10 @@ Params: cs0_pin GPIO pin + is 'on' or enabled). + + ++Name: spi5-2cs-pi5 ++Info: See spi5-2cs ++ ++ + Name: spi6-1cs + Info: Enables spi6 with a single chip select (CS) line and associated spidev + dev node. The gpio pin number for the CS line and spidev device node +@@ -4296,6 +4461,12 @@ Params: txd0_pin GPIO pin + 7(Alt3) for 32&33, 6(Alt2) for 36&37 + + ++Name: uart0-pi5 ++Info: Enable uart 0 on GPIOs 14-15. Pi 5 only. ++Load: dtoverlay=uart0-pi5, ++Params: ctsrts Enable CTS/RTS on GPIOs 16-17 (default off) ++ ++ + Name: uart1 + Info: Change the pin usage of uart1 + Load: dtoverlay=uart1,= +@@ -4304,24 +4475,48 @@ Params: txd1_pin GPIO pin + rxd1_pin GPIO pin for RXD1 (15, 33 or 41 - default 15) + + ++Name: uart1-pi5 ++Info: Enable uart 1 on GPIOs 0-1. Pi 5 only. ++Load: dtoverlay=uart1-pi5, ++Params: ctsrts Enable CTS/RTS on GPIOs 2-3 (default off) ++ ++ + Name: uart2 + Info: Enable uart 2 on GPIOs 0-3. BCM2711 only. + Load: dtoverlay=uart2, + Params: ctsrts Enable CTS/RTS on GPIOs 2-3 (default off) + + ++Name: uart2-pi5 ++Info: Enable uart 2 on GPIOs 4-5. Pi 5 only. ++Load: dtoverlay=uart2-pi5, ++Params: ctsrts Enable CTS/RTS on GPIOs 6-7 (default off) ++ ++ + Name: uart3 + Info: Enable uart 3 on GPIOs 4-7. BCM2711 only. + Load: dtoverlay=uart3, + Params: ctsrts Enable CTS/RTS on GPIOs 6-7 (default off) + + ++Name: uart3-pi5 ++Info: Enable uart 3 on GPIOs 8-9. Pi 5 only. ++Load: dtoverlay=uart3-pi5, ++Params: ctsrts Enable CTS/RTS on GPIOs 10-11 (default off) ++ ++ + Name: uart4 + Info: Enable uart 4 on GPIOs 8-11. BCM2711 only. + Load: dtoverlay=uart4, + Params: ctsrts Enable CTS/RTS on GPIOs 10-11 (default off) + + ++Name: uart4-pi5 ++Info: Enable uart 4 on GPIOs 12-13. Pi 5 only. ++Load: dtoverlay=uart4-pi5, ++Params: ctsrts Enable CTS/RTS on GPIOs 14-15 (default off) ++ ++ + Name: uart5 + Info: Enable uart 5 on GPIOs 12-15. BCM2711 only. + Load: dtoverlay=uart5, +@@ -4530,6 +4725,8 @@ Params: sizex Touchscr + invy Touchscreen inverted y axis + swapxy Touchscreen swapped x y axis + disable_touch Disables the touch screen overlay driver ++ dsi0 Use DSI0 and i2c_csi_dsi0 (rather than ++ the default DSI1 and i2c_csi_dsi). + + + Name: vc4-kms-dsi-lt070me05000 +@@ -4579,6 +4776,8 @@ Params: 2_8_inch 2.8" 480 + invx Touchscreen inverted x axis + invy Touchscreen inverted y axis + swapxy Touchscreen swapped x y axis ++ dsi0 Use DSI0 and i2c_csi_dsi0 (rather than ++ the default DSI1 and i2c_csi_dsi). + + + Name: vc4-kms-kippah-7inch +@@ -4633,6 +4832,9 @@ Params: cma-512 CMA is 5 + nohdmi1 Disable HDMI 1 output + + ++Name: vc4-kms-v3d-pi5 ++Info: See vc4-kms-v3d-pi4 (this is the Pi 5 version) ++ + + Name: vc4-kms-vga666 + Info: Enable the VGA666 (resistor ladder ADC) for the vc4-kms-v3d driver. +--- a/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts ++++ b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts +@@ -23,7 +23,7 @@ + }; + + fragment@1 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -33,7 +33,7 @@ + target = <&sound>; + __overlay__ { + compatible = "adi,adau1977-adc"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts ++++ b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts +@@ -5,7 +5,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -37,7 +37,7 @@ + "PDM_DAT", "Microphone Jack"; + status = "okay"; + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + dailink0_slave: simple-audio-card,codec { + sound-dai = <&adau7002_codec>; +--- a/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts ++++ b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -38,7 +38,7 @@ + card_name = "Akkordion"; + dai_name = "IQaudIO DAC"; + dai_stream_name = "IQaudIO DAC HiFi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-boss-dac-pcm512x-audio-overlay.dts +@@ -18,8 +18,8 @@ + }; + }; + +- fragment@1 { +- target = <&i2s>; ++ frag1: fragment@1 { ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -46,7 +46,7 @@ + target = <&sound>; + boss_dac: __overlay__ { + compatible = "allo,boss-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + mute-gpios = <&gpio 6 1>; + status = "okay"; + }; +@@ -54,6 +54,8 @@ + + __overrides__ { + 24db_digital_gain = <&boss_dac>,"allo,24db_digital_gain?"; +- slave = <&boss_dac>,"allo,slave?"; ++ slave = <&boss_dac>,"allo,slave?", ++ <&frag1>,"target:0=",<&i2s_clk_producer>, ++ <&boss_dac>,"i2s-controller:0=",<&i2s_clk_producer>; + }; + }; +--- a/arch/arm/boot/dts/overlays/allo-boss2-dac-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-boss2-dac-audio-overlay.dts +@@ -8,7 +8,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + #sound-dai-cells = <0>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/allo-digione-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-digione-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -35,7 +35,7 @@ + target = <&sound>; + __overlay__ { + compatible = "allo,allo-digione"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + clock44-gpio = <&gpio 5 0>; + clock48-gpio = <&gpio 6 0>; +--- a/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-katana-dac-audio-overlay.dts +@@ -9,7 +9,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + #sound-dai-cells = <0>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-piano-dac-pcm512x-audio-overlay.dts +@@ -16,7 +16,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -42,7 +42,7 @@ + target = <&sound>; + piano_dac: __overlay__ { + compatible = "allo,piano-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/allo-piano-dac-plus-pcm512x-audio-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -41,7 +41,7 @@ + piano_dac: __overlay__ { + compatible = "allo,piano-dac-plus"; + audio-codec = <&allo_pcm5122_4c &allo_pcm5122_4d>; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + mute1-gpios = <&gpio 6 1>; + mute2-gpios = <&gpio 25 1>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/applepi-dac-overlay.dts +@@ -16,7 +16,7 @@ + format = "i2s"; + + p_cpu_dai: cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +@@ -40,7 +40,7 @@ + }; + + fragment@2 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + #sound-dai-cells = <0>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/arducam-64mp-overlay.dts ++++ b/arch/arm/boot/dts/overlays/arducam-64mp-overlay.dts +@@ -67,7 +67,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/arducam-pivariety-overlay.dts ++++ b/arch/arm/boot/dts/overlays/arducam-pivariety-overlay.dts +@@ -85,7 +85,7 @@ + rotation = <&arducam_pivariety>,"rotation:0"; + orientation = <&arducam_pivariety>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&arducam_pivariety>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -48,7 +48,7 @@ + mult-gpios = <&gpio 27 0>, <&gpio 22 0>, <&gpio 23 0>, + <&gpio 24 0>; + reset-gpios = <&gpio 5 0>; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + codec = <&cs42448>; + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/audioinjector-bare-i2s-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audioinjector-bare-i2s-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -27,7 +27,7 @@ + target = <&sound>; + __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + + simple-audio-card,name = "audioinjector-bare"; +@@ -37,7 +37,7 @@ + simple-audio-card,frame-master = <&dailink0_master>; + + dailink0_master: simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +--- a/arch/arm/boot/dts/overlays/audioinjector-isolated-soundcard-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audioinjector-isolated-soundcard-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -47,7 +47,7 @@ + snd: __overlay__ { + compatible = "ai,audioinjector-isolated-soundcard"; + mute-gpios = <&gpio 17 0>; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + codec = <&cs4272>; + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audioinjector-ultra-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -33,7 +33,7 @@ + target = <&sound>; + __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + + simple-audio-card,name = "audioinjector-ultra"; +@@ -57,7 +57,7 @@ + simple-audio-card,frame-master = <&sound_master>; + + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_consumer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +--- a/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "ai,audioinjector-pi-soundcard"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts ++++ b/arch/arm/boot/dts/overlays/audiosense-pi-overlay.dts +@@ -8,7 +8,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -75,7 +75,7 @@ + target = <&sound>; + __overlay__ { + compatible = "as,audiosense-pi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/chipdip-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/chipdip-dac-overlay.dts +@@ -9,7 +9,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "chipdip,chipdip-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + sr0-gpios = <&gpio 5 0>; + sr1-gpios = <&gpio 6 0>; + sr2-gpios = <&gpio 12 0>; +--- a/arch/arm/boot/dts/overlays/cirrus-wm5102-overlay.dts ++++ b/arch/arm/boot/dts/overlays/cirrus-wm5102-overlay.dts +@@ -9,7 +9,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -165,7 +165,7 @@ + target = <&sound>; + __overlay__ { + compatible = "wlf,rpi-cirrus"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/dacberry400-overlay.dts ++++ b/arch/arm/boot/dts/overlays/dacberry400-overlay.dts +@@ -5,7 +5,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -62,7 +62,7 @@ + target = <&sound>; + __overlay__ { + compatible = "osaelectronics,dacberry400"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/dionaudio-kiwi-overlay.dts ++++ b/arch/arm/boot/dts/overlays/dionaudio-kiwi-overlay.dts +@@ -11,7 +11,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "dionaudio,dionaudio-kiwi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts ++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts +@@ -11,7 +11,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "dionaudio,loco-pcm5242-tpa3118"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts ++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts +@@ -15,13 +15,13 @@ + target = <&sound>; + frag0: __overlay__ { + compatible = "dionaudio,dionaudio-loco-v2"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; + + fragment@1 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/disable-bt-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/* Disable Bluetooth */ ++ ++#include ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&bluetooth>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/disable-wifi-pi5-overlay.dts +@@ -0,0 +1,13 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&sdio2>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/draws-overlay.dts ++++ b/arch/arm/boot/dts/overlays/draws-overlay.dts +@@ -9,7 +9,7 @@ + / { + compatible = "brcm,bcm2835"; + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -131,7 +131,7 @@ + target = <&sound>; + snd: __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + + simple-audio-card,name = "draws"; +@@ -153,7 +153,7 @@ + "Line Out", "LOL"; + + dailink0_master: simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + + simple-audio-card,codec { +--- a/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts ++++ b/arch/arm/boot/dts/overlays/edt-ft5406-overlay.dts +@@ -25,21 +25,21 @@ + }; + + __overrides__ { +- i2c0 = <&frag13>,"target:0=",<&i2c0>; +- i2c1 = <&frag13>, "target?=0", +- <&frag13>, "target-path=i2c1", ++ i2c0 = <&ts_i2c_frag>,"target:0=",<&i2c0>; ++ i2c1 = <&ts_i2c_frag>, "target?=0", ++ <&ts_i2c_frag>, "target-path=i2c1", + <0>,"-0-1"; +- i2c3 = <&frag13>, "target?=0", +- <&frag13>, "target-path=i2c3", ++ i2c3 = <&ts_i2c_frag>, "target?=0", ++ <&ts_i2c_frag>, "target-path=i2c3", + <0>,"-0-1"; +- i2c4 = <&frag13>, "target?=0", +- <&frag13>, "target-path=i2c4", ++ i2c4 = <&ts_i2c_frag>, "target?=0", ++ <&ts_i2c_frag>, "target-path=i2c4", + <0>,"-0-1"; +- i2c5 = <&frag13>, "target?=0", +- <&frag13>, "target-path=i2c5", ++ i2c5 = <&ts_i2c_frag>, "target?=0", ++ <&ts_i2c_frag>, "target-path=i2c5", + <0>,"-0-1"; +- i2c6 = <&frag13>, "target?=0", +- <&frag13>, "target-path=i2c6", ++ i2c6 = <&ts_i2c_frag>, "target?=0", ++ <&ts_i2c_frag>, "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 +@@ -37,7 +37,7 @@ + }; + }; + +- frag13: fragment@13 { ++ ts_i2c_frag: fragment@13 { + target = <&i2c_csi_dsi>; + i2cbus: __overlay__ { + status = "okay"; +--- a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts +@@ -53,7 +53,7 @@ + }; + + fragment@3 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -63,7 +63,7 @@ + target = <&sound>; + __overlay__ { + compatible = "fe-pi,fe-pi-audio"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/ghost-amp-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ghost-amp-overlay.dts +@@ -14,7 +14,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -43,7 +43,7 @@ + target = <&sound>; + iqaudio_dac: __overlay__ { + compatible = "iqaudio,iqaudio-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + mute-gpios = <& 0 0>; + iqaudio-dac,auto-mute-amp; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts ++++ b/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -42,7 +42,7 @@ + target = <&sound>; + __overlay__ { + compatible = "googlevoicehat,googlevoicehat-soundcard"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-amp"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-amp100-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-amp100-overlay.dts +@@ -15,8 +15,8 @@ + }; + }; + +- fragment@1 { +- target = <&i2s>; ++ frag1: fragment@1 { ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -46,7 +46,7 @@ + target = <&sound>; + hifiberry_dacplus: __overlay__ { + compatible = "hifiberry,hifiberry-dacplus"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + mute-gpio = <&gpio 4 0>; + reset-gpio = <&gpio 17 0x11>; +@@ -56,7 +56,10 @@ + __overrides__ { + 24db_digital_gain = + <&hifiberry_dacplus>,"hifiberry,24db_digital_gain?"; +- slave = <&hifiberry_dacplus>,"hifiberry-dacplus,slave?"; ++ slave = <&hifiberry_dacplus>,"hifiberry-dacplus,slave?", ++ <&frag1>,"target:0=",<&i2s_clk_producer>, ++ <&hifiberry_dacplus>,"i2s-controller:0=",<&i2s_clk_producer>; ++ + leds_off = <&hifiberry_dacplus>,"hifiberry-dacplus,leds_off?"; + mute_ext_ctl = <&hifiberry_dacplus>,"hifiberry-dacplus,mute_ext_ctl:0"; + auto_mute = <&hifiberry_dacplus>,"hifiberry-dacplus,auto_mute?"; +--- a/arch/arm/boot/dts/overlays/hifiberry-amp3-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-amp3-overlay.dts +@@ -10,7 +10,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -50,7 +50,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-amp3"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dac-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -27,7 +27,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts +@@ -15,8 +15,8 @@ + }; + }; + +- fragment@1 { +- target = <&i2s>; ++ frag1: fragment@1 { ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -51,7 +51,7 @@ + target = <&sound>; + hifiberry_dacplus: __overlay__ { + compatible = "hifiberry,hifiberry-dacplus"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +@@ -59,7 +59,10 @@ + __overrides__ { + 24db_digital_gain = + <&hifiberry_dacplus>,"hifiberry,24db_digital_gain?"; +- slave = <&hifiberry_dacplus>,"hifiberry-dacplus,slave?"; ++ slave = <&hifiberry_dacplus>,"hifiberry-dacplus,slave?", ++ <&frag1>,"target:0=",<&i2s_clk_producer>, ++ <&hifiberry_dacplus>,"i2s-controller:0=",<&i2s_clk_producer>; ++ + leds_off = <&hifiberry_dacplus>,"hifiberry-dacplus,leds_off?"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadc-overlay.dts +@@ -15,8 +15,8 @@ + }; + }; + +- fragment@1 { +- target = <&i2s>; ++ frag1: fragment@1 { ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -58,7 +58,7 @@ + target = <&sound>; + hifiberry_dacplusadc: __overlay__ { + compatible = "hifiberry,hifiberry-dacplusadc"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +@@ -66,7 +66,9 @@ + __overrides__ { + 24db_digital_gain = + <&hifiberry_dacplusadc>,"hifiberry,24db_digital_gain?"; +- slave = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,slave?"; ++ slave = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,slave?", ++ <&frag1>,"target:0=",<&i2s_clk_producer>, ++ <&hifiberry_dacplusadc>,"i2s-controller:0=",<&i2s_clk_producer>; + leds_off = <&hifiberry_dacplusadc>,"hifiberry-dacplusadc,leds_off?"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusadcpro-overlay.dts +@@ -15,8 +15,8 @@ + }; + }; + +- fragment@1 { +- target = <&i2s>; ++ frag1: fragment@1 { ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -56,7 +56,7 @@ + hifiberry_dacplusadcpro: __overlay__ { + compatible = "hifiberry,hifiberry-dacplusadcpro"; + audio-codec = <&hb_dac &hb_adc>; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +@@ -64,7 +64,9 @@ + __overrides__ { + 24db_digital_gain = + <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,24db_digital_gain?"; +- slave = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,slave?"; ++ slave = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,slave?", ++ <&frag1>,"target:0=",<&i2s_clk_producer>, ++ <&hifiberry_dacplusadcpro>,"i2s-controller:0=",<&i2s_clk_producer>; + leds_off = <&hifiberry_dacplusadcpro>,"hifiberry-dacplusadcpro,leds_off?"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dacplusdsp-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplusdsp-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -27,7 +27,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberrydacplusdsp,hifiberrydacplusdsp-soundcard"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-dacplushd-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-dacplushd-overlay.dts +@@ -8,7 +8,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -84,7 +84,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-dacplushd"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + clocks = <&pll 0>; + reset-gpio = <&gpio 16 GPIO_ACTIVE_LOW>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -34,7 +34,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-digi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts ++++ b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -34,7 +34,7 @@ + target = <&sound>; + __overlay__ { + compatible = "hifiberry,hifiberry-digi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + clock44-gpio = <&gpio 5 0>; + clock48-gpio = <&gpio 6 0>; +--- a/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i-sabre-q2m-overlay.dts +@@ -9,13 +9,13 @@ + target = <&sound>; + frag0: __overlay__ { + compatible = "audiophonics,i-sabre-q2m"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; + + fragment@1 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c0-pi5-overlay.dts +@@ -0,0 +1,34 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&i2c0>; ++ frag0: __overlay__ { ++ status = "okay"; ++ clock-frequency = <100000>; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&frag0>; ++ __overlay__ { ++ pinctrl-0 = <&rp1_i2c0_0_1>; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&frag0>; ++ __dormant__ { ++ pinctrl-0 = <&rp1_i2c0_8_9>; ++ }; ++ }; ++ ++ __overrides__ { ++ pins_0_1 = <0>,"+1-2"; ++ pins_8_9 = <0>,"-1+2"; ++ baudrate = <&frag0>, "clock-frequency:0"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c1-pi5-overlay.dts +@@ -0,0 +1,34 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&i2c1>; ++ frag0: __overlay__ { ++ status = "okay"; ++ clock-frequency = <100000>; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&frag0>; ++ __overlay__ { ++ pinctrl-0 = <&rp1_i2c1_2_3>; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&frag0>; ++ __dormant__ { ++ pinctrl-0 = <&rp1_i2c1_10_11>; ++ }; ++ }; ++ ++ __overrides__ { ++ pins_2_3 = <0>,"+1-2"; ++ pins_10_11 = <0>,"-1+2"; ++ baudrate = <&frag0>, "clock-frequency:0"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c2-pi5-overlay.dts +@@ -0,0 +1,21 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&i2c2>; ++ frag0: __overlay__ { ++ status = "okay"; ++ clock-frequency = <100000>; ++ pinctrl-0 = <&rp1_i2c2_4_5>; ++ }; ++ }; ++ ++ __overrides__ { ++ pins_4_5 = <&frag0>,"pinctrl-0:0=", <&rp1_i2c2_4_5>; ++ pins_12_13 = <&frag0>,"pinctrl-0:0=", <&rp1_i2c2_12_13>; ++ baudrate = <&frag0>, "clock-frequency:0"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/i2c3-pi5-overlay.dts +@@ -0,0 +1,22 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&i2c3>; ++ frag0: __overlay__ { ++ status = "okay"; ++ clock-frequency = <100000>; ++ pinctrl-0 = <&rp1_i2c3_6_7>; ++ }; ++ }; ++ ++ __overrides__ { ++ pins_6_7 = <&frag0>,"pinctrl-0:0=", <&rp1_i2c3_6_7>; ++ pins_14_15 = <&frag0>,"pinctrl-0:0=", <&rp1_i2c3_14_15>; ++ pins_22_23 = <&frag0>,"pinctrl-0:0=", <&rp1_i2c3_22_23>; ++ baudrate = <&frag0>, "clock-frequency:0"; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/i2s-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2s-dac-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -27,7 +27,7 @@ + target = <&sound>; + __overlay__ { + compatible = "rpi,rpi-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/imx219-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx219-overlay.dts +@@ -69,7 +69,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/imx258-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx258-overlay.dts +@@ -110,7 +110,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <®_frag>, "target:0=",<&cam0_reg>, +--- a/arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi ++++ b/arch/arm/boot/dts/overlays/imx290_327-overlay.dtsi +@@ -95,7 +95,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/imx296-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx296-overlay.dts +@@ -94,7 +94,7 @@ + rotation = <&imx296>,"rotation:0"; + orientation = <&imx296>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&imx296>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi ++++ b/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi +@@ -65,7 +65,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <®_frag>, "target:0=",<&cam0_reg>, +--- a/arch/arm/boot/dts/overlays/imx519-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx519-overlay.dts +@@ -69,7 +69,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/imx708-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx708-overlay.dts +@@ -79,12 +79,12 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <®_frag>, "target:0=",<&cam0_reg>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +- <&cam_node>, "VANA1-supply:0=",<&cam0_reg>, ++ <&cam_node>, "vana1-supply:0=",<&cam0_reg>, + <&vcm_node>, "VDD-supply:0=",<&cam0_reg>; + vcm = <&vcm_node>, "status", + <0>, "=4"; +--- a/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts ++++ b/arch/arm/boot/dts/overlays/iqaudio-codec-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + iqaudio_dac: __overlay__ { + compatible = "iqaudio,iqaudio-codec"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -35,7 +35,7 @@ + target = <&sound>; + frag2: __overlay__ { + compatible = "iqaudio,iqaudio-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts ++++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -35,7 +35,7 @@ + target = <&sound>; + iqaudio_dac: __overlay__ { + compatible = "iqaudio,iqaudio-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + mute-gpios = <&gpio 22 0>; + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -34,7 +34,7 @@ + target = <&sound>; + wm8804_digi: __overlay__ { + compatible = "iqaudio,wm8804-digi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/irs1125-overlay.dts ++++ b/arch/arm/boot/dts/overlays/irs1125-overlay.dts +@@ -82,7 +82,7 @@ + + __overrides__ { + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&irs1125>, "clocks:0=",<&cam0_clk>; +--- a/arch/arm/boot/dts/overlays/justboom-both-overlay.dts ++++ b/arch/arm/boot/dts/overlays/justboom-both-overlay.dts +@@ -7,7 +7,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -54,7 +54,7 @@ + target = <&sound>; + frag3: __overlay__ { + compatible = "justboom,justboom-both"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -35,7 +35,7 @@ + target = <&sound>; + frag2: __overlay__ { + compatible = "justboom,justboom-dac"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts ++++ b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -34,7 +34,7 @@ + target = <&sound>; + __overlay__ { + compatible = "justboom,justboom-digi"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/max98357a-overlay.dts ++++ b/arch/arm/boot/dts/overlays/max98357a-overlay.dts +@@ -12,7 +12,7 @@ + + /* Enable I2S */ + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -52,7 +52,7 @@ + simple-audio-card,name = "MAX98357A"; + status = "okay"; + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + simple-audio-card,codec { + sound-dai = <&max98357a_dac>; +@@ -69,7 +69,7 @@ + simple-audio-card,name = "MAX98357A"; + status = "okay"; + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + simple-audio-card,codec { + sound-dai = <&max98357a_nsd>; +--- a/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts ++++ b/arch/arm/boot/dts/overlays/mbed-dac-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + + simple-audio-card,name = "mbed-DAC"; +@@ -52,7 +52,7 @@ + simple-audio-card,format = "i2s"; + + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + + sound_master: simple-audio-card,codec { +--- a/arch/arm/boot/dts/overlays/merus-amp-overlay.dts ++++ b/arch/arm/boot/dts/overlays/merus-amp-overlay.dts +@@ -9,7 +9,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -52,7 +52,7 @@ + target = <&sound>; + __overlay__ { + compatible = "merus,merus-amp"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + }; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart0-pi5-overlay.dts +@@ -0,0 +1,35 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 100MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 100000000*38400/31250 = 122880000 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ midi_clk: midi_clk0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart0_pclk"; ++ clock-frequency = <122880000>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart0>; ++ __overlay__ { ++ clocks = <&midi_clk &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart1-pi5-overlay.dts +@@ -0,0 +1,35 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 100MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 100000000*38400/31250 = 122880000 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ midi_clk: midi_clk1 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart1_pclk"; ++ clock-frequency = <122880000>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart1>; ++ __overlay__ { ++ clocks = <&midi_clk &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart2-pi5-overlay.dts +@@ -0,0 +1,35 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 100MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 100000000*38400/31250 = 122880000 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ midi_clk: midi_clk2 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart2_pclk"; ++ clock-frequency = <122880000>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart2>; ++ __overlay__ { ++ clocks = <&midi_clk &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart3-pi5-overlay.dts +@@ -0,0 +1,35 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 100MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 100000000*38400/31250 = 122880000 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ midi_clk: midi_clk3 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart3_pclk"; ++ clock-frequency = <122880000>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart3>; ++ __overlay__ { ++ clocks = <&midi_clk &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/midi-uart4-pi5-overlay.dts +@@ -0,0 +1,35 @@ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Fake a higher clock rate to get a larger divisor, and thereby a lower ++ * baudrate. The real clock is 100MHz, which we scale so that requesting ++ * 38.4kHz results in an actual 31.25kHz. ++ * ++ * 100000000*38400/31250 = 122880000 ++ */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ midi_clk: midi_clk4 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "uart4_pclk"; ++ clock-frequency = <122880000>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&uart4>; ++ __overlay__ { ++ clocks = <&midi_clk &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/ov2311-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov2311-overlay.dts +@@ -60,7 +60,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts +@@ -72,7 +72,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <®_frag>, "target:0=",<&cam0_reg>, + <&clk_frag>, "target:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/ov7251-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov7251-overlay.dts +@@ -60,7 +60,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/ov9281-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov9281-overlay.dts +@@ -61,7 +61,7 @@ + rotation = <&cam_node>,"rotation:0"; + orientation = <&cam_node>,"orientation:0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +--- a/arch/arm/boot/dts/overlays/overlay_map.dts ++++ b/arch/arm/boot/dts/overlays/overlay_map.dts +@@ -1,32 +1,100 @@ + /dts-v1/; + + / { ++ audremap { ++ bcm2835; ++ bcm2711; ++ }; ++ ++ balena-fin { ++ bcm2835; ++ bcm2711; ++ }; ++ + bmp085_i2c-sensor { + deprecated = "use i2c-sensor,bmp085"; + }; + ++ cm-swap-i2c0 { ++ bcm2835; ++ bcm2711; ++ }; ++ + cutiepi-panel { + bcm2711; + }; + ++ disable-bt { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "disable-bt-pi5"; ++ }; ++ ++ disable-bt-pi5 { ++ bcm2712; ++ }; ++ + disable-emmc2 { + bcm2711; + }; + ++ disable-wifi { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "disable-wifi-pi5"; ++ }; ++ ++ disable-wifi-pi5 { ++ bcm2712; ++ }; ++ + highperi { + bcm2711; + }; + ++ i2c0 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "i2c0-pi5"; ++ }; ++ + i2c0-bcm2708 { + deprecated = "use i2c0"; + }; + ++ i2c0-pi5 { ++ bcm2712; ++ }; ++ ++ i2c1 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "i2c1-pi5"; ++ }; ++ + i2c1-bcm2708 { + deprecated = "use i2c1"; + }; + ++ i2c1-pi5 { ++ bcm2712; ++ }; ++ ++ i2c2 { ++ bcm2712 = "i2c2-pi5"; ++ }; ++ ++ i2c2-pi5 { ++ bcm2712; ++ }; ++ + i2c3 { + bcm2711; ++ bcm2712 = "i2c3-pi5"; ++ }; ++ ++ i2c3-pi5 { ++ bcm2712; + }; + + i2c4 { +@@ -41,26 +109,76 @@ + bcm2711; + }; + ++ i2s-gpio28-31 { ++ bcm2835; ++ bcm2711; ++ }; ++ + lirc-rpi { + deprecated = "use gpio-ir"; + }; + ++ midi-uart0 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "midi-uart0-pi5"; ++ }; ++ ++ midi-uart0-pi5 { ++ bcm2712; ++ }; ++ ++ midi-uart1 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "midi-uart1-pi5"; ++ }; ++ ++ midi-uart1-pi5 { ++ bcm2712; ++ }; ++ + midi-uart2 { + bcm2711; ++ bcm2712 = "midi-uart2-pi5"; ++ }; ++ ++ midi-uart2-pi5 { ++ bcm2712; + }; + + midi-uart3 { + bcm2711; ++ bcm2712 = "midi-uart3-pi5"; ++ }; ++ ++ midi-uart3-pi5 { ++ bcm2712; + }; + + midi-uart4 { + bcm2711; ++ bcm2712 = "midi-uart4-pi5"; ++ }; ++ ++ midi-uart4-pi5 { ++ bcm2712; + }; + + midi-uart5 { + bcm2711; + }; + ++ miniuart-bt { ++ bcm2835; ++ bcm2711; ++ }; ++ ++ mmc { ++ bcm2835; ++ bcm2711; ++ }; ++ + mpu6050 { + deprecated = "use i2c-sensor,mpu6050"; + }; +@@ -118,6 +236,16 @@ + deprecated = "no longer necessary"; + }; + ++ sdhost { ++ bcm2835; ++ bcm2711; ++ }; ++ ++ sdio { ++ bcm2835; ++ bcm2711; ++ }; ++ + sdio-1bit { + deprecated = "use sdio,bus_width=1,gpios_22_25"; + }; +@@ -126,6 +254,21 @@ + deprecated = "use 'dtparam=sd_poll_once' etc."; + }; + ++ smi { ++ bcm2835; ++ bcm2711; ++ }; ++ ++ smi-dev { ++ bcm2835; ++ bcm2711; ++ }; ++ ++ smi-nand { ++ bcm2835; ++ bcm2711; ++ }; ++ + spi0-cs { + renamed = "spi0-2cs"; + }; +@@ -134,12 +277,42 @@ + deprecated = "no longer necessary"; + }; + ++ spi2-1cs { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "spi2-1cs-pi5"; ++ }; ++ ++ spi2-1cs-pi5 { ++ bcm2712; ++ }; ++ ++ spi2-2cs { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "spi2-2cs-pi5"; ++ }; ++ ++ spi2-2cs-pi5 { ++ bcm2712; ++ }; ++ + spi3-1cs { + bcm2711; ++ bcm2712 = "spi3-1cs-pi5"; ++ }; ++ ++ spi3-1cs-pi5 { ++ bcm2712; + }; + + spi3-2cs { + bcm2711; ++ bcm2712 = "spi3-2cs-pi5"; ++ }; ++ ++ spi3-2cs-pi5 { ++ bcm2712; + }; + + spi4-1cs { +@@ -152,10 +325,20 @@ + + spi5-1cs { + bcm2711; ++ bcm2712 = "spi5-1cs-pi5"; ++ }; ++ ++ spi5-1cs-pi5 { ++ bcm2712; + }; + + spi5-2cs { + bcm2711; ++ bcm2712 = "spi5-2cs-pi5"; ++ }; ++ ++ spi5-2cs-pi5 { ++ bcm2712; + }; + + spi6-1cs { +@@ -166,16 +349,51 @@ + bcm2711; + }; + ++ uart0 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "uart0-pi5"; ++ }; ++ ++ uart0-pi5 { ++ bcm2712; ++ }; ++ ++ uart1 { ++ bcm2835; ++ bcm2711; ++ bcm2712 = "uart1-pi5"; ++ }; ++ ++ uart1-pi5 { ++ bcm2712; ++ }; ++ + uart2 { + bcm2711; ++ bcm2712 = "uart2-pi5"; ++ }; ++ ++ uart2-pi5 { ++ bcm2712; + }; + + uart3 { + bcm2711; ++ bcm2712 = "uart3-pi5"; ++ }; ++ ++ uart3-pi5 { ++ bcm2712; + }; + + uart4 { + bcm2711; ++ bcm2712 = "uart4-pi5"; ++ }; ++ ++ uart4-pi5 { ++ bcm2712; + }; + + uart5 { +@@ -198,10 +416,12 @@ + vc4-fkms-v3d { + bcm2835; + bcm2711 = "vc4-fkms-v3d-pi4"; ++ bcm2712 = "vc4-fkms-v3d-pi4"; + }; + + vc4-fkms-v3d-pi4 { + bcm2711; ++ bcm2712; + }; + + vc4-kms-dpi-at056tn53v1 { +@@ -211,10 +431,16 @@ + vc4-kms-v3d { + bcm2835; + bcm2711 = "vc4-kms-v3d-pi4"; ++ bcm2712 = "vc4-kms-v3d-pi5"; + }; + + vc4-kms-v3d-pi4 { + bcm2711; ++ bcm2712 = "vc4-kms-v3d-pi5"; ++ }; ++ ++ vc4-kms-v3d-pi5 { ++ bcm2712; + }; + + vl805 { +--- a/arch/arm/boot/dts/overlays/pibell-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pibell-overlay.dts +@@ -24,7 +24,7 @@ + }; + + fragment@1 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + #sound-dai-cells = <0>; + status = "okay"; +@@ -43,7 +43,7 @@ + format = "i2s"; + + r_cpu_dai: cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + + /* example TDM slot configuration + dai-tdm-slot-num = <2>; +@@ -60,7 +60,7 @@ + format = "i2s"; + + p_cpu_dai: cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + + /* example TDM slot configuration + dai-tdm-slot-num = <2>; +--- a/arch/arm/boot/dts/overlays/pifi-40-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pifi-40-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -42,7 +42,7 @@ + pifi_40: __overlay__ { + compatible = "pifi,pifi-40"; + audio-codec = <&tas5711l &tas5711r>; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + pdn-gpios = <&gpio 23 1>; + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/pifi-dac-hd-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pifi-dac-hd-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -38,7 +38,7 @@ + simple-audio-card,dai-link@1 { + format = "i2s"; + cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + codec { + sound-dai = <&pcm5142>; +--- a/arch/arm/boot/dts/overlays/pifi-dac-zero-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pifi-dac-zero-overlay.dts +@@ -16,7 +16,7 @@ + format = "i2s"; + + cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +@@ -40,7 +40,7 @@ + }; + + fragment@2 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + #sound-dai-cells = <0>; + status = "okay"; +--- a/arch/arm/boot/dts/overlays/pifi-mini-210-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pifi-mini-210-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -34,7 +34,7 @@ + target = <&sound>; + __overlay__ { + compatible = "pifi,pifi-mini-210"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/pisound-overlay.dts ++++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts +@@ -75,7 +75,7 @@ + target = <&sound>; + __overlay__ { + compatible = "blokaslabs,pisound"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + + pinctrl-names = "default"; +@@ -108,7 +108,7 @@ + }; + + fragment@7 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/proto-codec-overlay.dts ++++ b/arch/arm/boot/dts/overlays/proto-codec-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -32,7 +32,7 @@ + target = <&sound>; + __overlay__ { + compatible = "rpi,rpi-proto"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- a/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -42,7 +42,7 @@ + target = <&sound>; + __overlay__ { + compatible = "rra,digidac1-soundcard"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + }; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi2-1cs-pi5-overlay.dts +@@ -0,0 +1,33 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi2>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 0 1>; ++ status = "okay"; ++ ++ spidev2_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs0_spidev = <&spidev2_0>,"status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi2-2cs-pi5-overlay.dts +@@ -0,0 +1,44 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi2>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 0 1>, <&gpio 24 1>; ++ status = "okay"; ++ ++ spidev2_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ ++ spidev2_1: spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs1_pin = <&frag1>,"cs-gpios:16"; ++ cs0_spidev = <&spidev2_0>,"status"; ++ cs1_spidev = <&spidev2_1>,"status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi3-1cs-pi5-overlay.dts +@@ -0,0 +1,33 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi3>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 4 1>; ++ status = "okay"; ++ ++ spidev3_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs0_spidev = <&spidev3_0>,"status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi3-2cs-pi5-overlay.dts +@@ -0,0 +1,44 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi3>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 4 1>, <&gpio 25 1>; ++ status = "okay"; ++ ++ spidev3_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ ++ spidev3_1: spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs1_pin = <&frag1>,"cs-gpios:16"; ++ cs0_spidev = <&spidev3_0>,"status"; ++ cs1_spidev = <&spidev3_1>,"status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi5-1cs-pi5-overlay.dts +@@ -0,0 +1,33 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi5>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 12 1>; ++ status = "okay"; ++ ++ spidev5_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs0_spidev = <&spidev5_0>,"status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi5-2cs-pi5-overlay.dts +@@ -0,0 +1,44 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&spi5>; ++ frag1: __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cs-gpios = <&gpio 12 1>, <&gpio 26 1>; ++ status = "okay"; ++ ++ spidev5_0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ ++ spidev5_1: spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag1>,"cs-gpios:4"; ++ cs1_pin = <&frag1>,"cs-gpios:16"; ++ cs0_spidev = <&spidev5_0>,"status"; ++ cs1_spidev = <&spidev5_1>,"status"; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts ++++ b/arch/arm/boot/dts/overlays/superaudioboard-overlay.dts +@@ -9,7 +9,7 @@ + target = <&sound>; + __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_consumer>; + status = "okay"; + + simple-audio-card,name = "SuperAudioBoard"; +@@ -32,7 +32,7 @@ + simple-audio-card,frame-master = <&sound_master>; + + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_consumer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +@@ -45,7 +45,7 @@ + }; + + fragment@1 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +--- a/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts ++++ b/arch/arm/boot/dts/overlays/tc358743-audio-overlay.dts +@@ -8,7 +8,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -31,16 +31,16 @@ + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "tc358743"; +- simple-audio-card,bitclock-master = <&dailink0_slave>; +- simple-audio-card,frame-master = <&dailink0_slave>; ++ simple-audio-card,bitclock-master = <&dailink0_master>; ++ simple-audio-card,frame-master = <&dailink0_master>; + status = "okay"; + + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_consumer>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; +- dailink0_slave: simple-audio-card,codec { ++ dailink0_master: simple-audio-card,codec { + sound-dai = <&tc358743_codec>; + }; + }; +--- a/arch/arm/boot/dts/overlays/tc358743-overlay.dts ++++ b/arch/arm/boot/dts/overlays/tc358743-overlay.dts +@@ -101,7 +101,7 @@ + 4lane = <0>, "-2+3-7+8"; + link-frequency = <&tc358743_0>,"link-frequencies#0"; + media-controller = <&csi>,"brcm,media-controller?"; +- cam0 = <&i2c_frag>, "target:0=",<&i2c_vc>, ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&tc358743>, "clocks:0=",<&cam0_clk>; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/uart0-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&uart0>; ++ frag0: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ ctsrts = <&frag0>,"pinctrl-0:4=",<&uart0_ctsrts_pins>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/uart1-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&uart1>; ++ frag0: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ ctsrts = <&frag0>,"pinctrl-0:4=",<&uart1_ctsrts_pins>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/uart2-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&uart2>; ++ frag0: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ ctsrts = <&frag0>,"pinctrl-0:4=",<&uart2_ctsrts_pins>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/uart3-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&uart3>; ++ frag0: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ ctsrts = <&frag0>,"pinctrl-0:4=",<&uart3_ctsrts_pins>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/uart4-pi5-overlay.dts +@@ -0,0 +1,17 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&uart4>; ++ frag0: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ ctsrts = <&frag0>,"pinctrl-0:4=",<&uart4_ctsrts_pins>; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/udrc-overlay.dts ++++ b/arch/arm/boot/dts/overlays/udrc-overlay.dts +@@ -9,7 +9,7 @@ + / { + compatible = "brcm,bcm2835"; + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + clocks = <&clocks BCM2835_CLOCK_PCM>; + clock-names = "pcm"; +@@ -71,7 +71,7 @@ + target = <&sound>; + snd: __overlay__ { + compatible = "simple-audio-card"; +- i2s-controller = <&i2s>; ++ i2s-controller = <&i2s_clk_producer>; + status = "okay"; + + simple-audio-card,name = "udrc"; +@@ -93,7 +93,7 @@ + "Line Out", "LOL"; + + dailink0_master: simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + + simple-audio-card,codec { +--- a/arch/arm/boot/dts/overlays/ugreen-dabboard-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ugreen-dabboard-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_consumer>; + __overlay__ { + status = "okay"; + }; +@@ -29,14 +29,14 @@ + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,name = "dabboard"; +- simple-audio-card,bitclock-master = <&dailink0_slave>; +- simple-audio-card,frame-master = <&dailink0_slave>; ++ simple-audio-card,bitclock-master = <&dailink0_master>; ++ simple-audio-card,frame-master = <&dailink0_master>; + simple-audio-card,widgets = "Microphone", "Microphone Jack"; + status = "okay"; + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_consumer>; + }; +- dailink0_slave: simple-audio-card,codec { ++ dailink0_master: simple-audio-card,codec { + #sound-dai-cells = <0>; + sound-dai = <&dmic_codec>; + }; +--- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts +@@ -37,4 +37,10 @@ + status = "okay"; + }; + }; ++ fragment@5 { ++ target-path = "/chosen"; ++ __overlay__ { ++ bootargs = "clk_ignore_unused"; ++ }; ++ }; + }; +--- a/arch/arm/boot/dts/overlays/vc4-fkms-v3d-pi4-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-fkms-v3d-pi4-overlay.dts +@@ -41,4 +41,10 @@ + status = "okay"; + }; + }; ++ fragment@5 { ++ target-path = "/chosen"; ++ __overlay__ { ++ bootargs = "clk_ignore_unused"; ++ }; ++ }; + }; +--- a/arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts +@@ -11,7 +11,7 @@ + / { + /* No compatible as it will have come from edt-ft5406.dtsi */ + +- fragment@0 { ++ dsi_frag: fragment@0 { + target = <&dsi1>; + __overlay__ { + #address-cells = <1>; +@@ -51,8 +51,8 @@ + fragment@1 { + target-path = "/"; + __overlay__ { +- panel_disp1: panel_disp1@0 { +- reg = <0>; ++ panel_disp: panel_disp@1 { ++ reg = <1>; + compatible = "raspberrypi,7inch-dsi", "simple-panel"; + backlight = <®_display>; + power-supply = <®_display>; +@@ -64,8 +64,8 @@ + }; + }; + +- reg_bridge: reg_bridge@0 { +- reg = <0>; ++ reg_bridge: reg_bridge@1 { ++ reg = <1>; + compatible = "regulator-fixed"; + regulator-name = "bridge_reg"; + gpio = <®_display 0 0>; +@@ -75,7 +75,7 @@ + }; + }; + +- fragment@2 { ++ i2c_frag: fragment@2 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; +@@ -113,6 +113,12 @@ + }; + + __overrides__ { ++ dsi0 = <&dsi_frag>, "target:0=",<&dsi0>, ++ <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, ++ <&ts_i2c_frag>, "target:0=",<&i2c_csi_dsi0>, ++ <&panel_disp>, "reg:0=0", ++ <®_bridge>, "reg:0=0", ++ <®_bridge>, "regulator-name=bridge_reg_0"; + disable_touch = <0>, "-10-11-12"; + }; + }; +--- 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 +@@ -9,7 +9,7 @@ + / { + compatible = "brcm,bcm2835"; + +- fragment@0 { ++ dsi_frag: fragment@0 { + target = <&dsi1>; + __overlay__ { + #address-cells = <1>; +@@ -29,7 +29,7 @@ + }; + }; + +- frag2: fragment@2 { ++ i2c_frag: fragment@2 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; +@@ -112,12 +112,14 @@ + <&touch>, "touchscreen-size-y:0=1480", + <&touch>, "touchscreen-inverted-x?", + <&touch>, "touchscreen-swapped-x-y?"; +- i2c1 = <&frag2>, "target:0=",<&i2c1>, ++ i2c1 = <&i2c_frag>, "target:0=",<&i2c1>, + <0>, "-3-4+5"; + disable_touch = <&touch>, "status=disabled"; + rotation = <&panel>, "rotation:0"; + invx = <&touch>,"touchscreen-inverted-x?"; + invy = <&touch>,"touchscreen-inverted-y?"; + swapxy = <&touch>,"touchscreen-swapped-x-y?"; ++ dsi0 = <&dsi_frag>, "target:0=",<&dsi0>, ++ <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>; + }; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-pi5-overlay.dts +@@ -0,0 +1,147 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include "cma-overlay.dts" ++ ++&frag0 { ++ size = <((320-4)*1024*1024)>; ++}; ++ ++/ { ++ compatible = "brcm,bcm2712"; ++ ++ fragment@1 { ++ target = <&fb>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&aon_intr>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&ddc0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&ddc1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&hdmi0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@6 { ++ target = <&hdmi1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@7 { ++ target = <&hvs>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@8 { ++ target = <&mop>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@9 { ++ target = <&moplet>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@10 { ++ target = <&pixelvalve0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@11 { ++ target = <&pixelvalve1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@12 { ++ target = <&v3d>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@13 { ++ target = <&vec>; ++ frag13: __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@14 { ++ target = <&hdmi0>; ++ __dormant__ { ++ dmas; ++ }; ++ }; ++ ++ fragment@15 { ++ target = <&hdmi1>; ++ __dormant__ { ++ dmas; ++ }; ++ }; ++ ++ fragment@16 { ++ target = <&disp_intr>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@17 { ++ target = <&vc4>; ++ __overlay__ { ++ /* IOMMU attaches here, where we allocate DMA buffers */ ++ iommus = <&iommu4>; ++ }; ++ }; ++ ++ __overrides__ { ++ audio = <0>,"!14"; ++ audio1 = <0>,"!15"; ++ noaudio = <0>,"=14", <0>,"=15"; ++ composite = <0>, "!3", ++ <0>, "!4", ++ <0>, "!5", ++ <0>, "!6", ++ <0>, "!10", ++ <0>, "!11", ++ <&frag13>, "status"; ++ nohdmi0 = <0>, "-3-5-10"; ++ nohdmi1 = <0>, "-4-6-11"; ++ nohdmi = <0>, "-3-4-5-6-10-11"; ++ }; ++}; +--- a/arch/arm/boot/dts/overlays/vc4-kms-vga666-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-vga666-overlay.dts +@@ -94,7 +94,14 @@ + }; + }; + ++ fragment@5 { ++ target = <&i2c_vc>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { +- ddc = <0>,"=2", <0>,"=3", <0>,"=4"; ++ ddc = <0>,"=2", <0>,"=3", <0>,"=4", <0>,"=5"; + }; + }; +--- a/arch/arm/boot/dts/overlays/wm8960-soundcard-overlay.dts ++++ b/arch/arm/boot/dts/overlays/wm8960-soundcard-overlay.dts +@@ -6,7 +6,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2s>; ++ target = <&i2s_clk_producer>; + __overlay__ { + status = "okay"; + }; +@@ -65,7 +65,7 @@ + "RINPUT2", "Mic Jack"; + + simple-audio-card,cpu { +- sound-dai = <&i2s>; ++ sound-dai = <&i2s_clk_producer>; + }; + dailink0_slave: simple-audio-card,codec { + sound-dai = <&wm8960>; +--- /dev/null ++++ b/arch/arm/boot/dts/rp1.dtsi +@@ -0,0 +1,1168 @@ ++#include ++#include ++#include ++ ++&rp1_target { ++ rp1: rp1 { ++ compatible = "simple-bus"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&rp1>; ++ ++ // ranges and dma-ranges must be provided by the includer ++ ++ rp1_clocks: clocks@18000 { ++ compatible = "raspberrypi,rp1-clocks"; ++ #clock-cells = <1>; ++ reg = <0xc0 0x40018000 0x0 0x10038>; ++ clocks = <&clk_xosc>; ++ ++ assigned-clocks = <&rp1_clocks RP1_PLL_SYS_CORE>, ++ <&rp1_clocks RP1_PLL_AUDIO_CORE>, ++ // RP1_PLL_VIDEO_CORE and dividers are now managed by VEC,DPI drivers ++ <&rp1_clocks RP1_PLL_SYS>, ++ <&rp1_clocks RP1_PLL_SYS_SEC>, ++ <&rp1_clocks RP1_PLL_AUDIO>, ++ <&rp1_clocks RP1_PLL_AUDIO_SEC>, ++ <&rp1_clocks RP1_CLK_SYS>, ++ <&rp1_clocks RP1_PLL_SYS_PRI_PH>, ++ // RP1_CLK_SLOW_SYS is used for the frequency counter (FC0) ++ <&rp1_clocks RP1_CLK_SLOW_SYS>, ++ <&rp1_clocks RP1_CLK_SDIO_TIMER>, ++ <&rp1_clocks RP1_CLK_SDIO_ALT_SRC>, ++ <&rp1_clocks RP1_CLK_ETH_TSU>; ++ ++ assigned-clock-rates = <1000000000>, // RP1_PLL_SYS_CORE ++ <1536000000>, // RP1_PLL_AUDIO_CORE ++ <200000000>, // RP1_PLL_SYS ++ <125000000>, // RP1_PLL_SYS_SEC ++ <61440000>, // RP1_PLL_AUDIO ++ <192000000>, // RP1_PLL_AUDIO_SEC ++ <200000000>, // RP1_CLK_SYS ++ <100000000>, // RP1_PLL_SYS_PRI_PH ++ // Must match the XOSC frequency ++ <50000000>, // RP1_CLK_SLOW_SYS ++ <1000000>, // RP1_CLK_SDIO_TIMER ++ <200000000>, // RP1_CLK_SDIO_ALT_SRC ++ <50000000>; // RP1_CLK_ETH_TSU ++ }; ++ ++ rp1_uart0: serial@30000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x40030000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ dmas = <&rp1_dma RP1_DMA_UART0_TX>, ++ <&rp1_dma RP1_DMA_UART0_RX>; ++ dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_uart1: serial@34000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x40034000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ // dmas = <&rp1_dma RP1_DMA_UART1_TX>, ++ // <&rp1_dma RP1_DMA_UART1_RX>; ++ // dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_uart2: serial@38000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x40038000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ // dmas = <&rp1_dma RP1_DMA_UART2_TX>, ++ // <&rp1_dma RP1_DMA_UART2_RX>; ++ // dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_uart3: serial@3c000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x4003c000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ // dmas = <&rp1_dma RP1_DMA_UART3_TX>, ++ // <&rp1_dma RP1_DMA_UART3_RX>; ++ // dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_uart4: serial@40000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x40040000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ // dmas = <&rp1_dma RP1_DMA_UART4_TX>, ++ // <&rp1_dma RP1_DMA_UART4_RX>; ++ // dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_uart5: serial@44000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x40044000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ // dmas = <&rp1_dma RP1_DMA_UART5_TX>, ++ // <&rp1_dma RP1_DMA_UART5_RX>; ++ // dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_spi8: spi@4c000 { ++ reg = <0xc0 0x4004c000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI8_TX>, ++ <&rp1_dma RP1_DMA_SPI8_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_spi0: spi@50000 { ++ reg = <0xc0 0x40050000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI0_TX>, ++ <&rp1_dma RP1_DMA_SPI0_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_spi1: spi@54000 { ++ reg = <0xc0 0x40054000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <0>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI1_TX>, ++ <&rp1_dma RP1_DMA_SPI1_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_spi2: spi@58000 { ++ reg = <0xc0 0x40058000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI2_TX>, ++ <&rp1_dma RP1_DMA_SPI2_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_spi3: spi@5c000 { ++ reg = <0xc0 0x4005c000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI3_TX>, ++ <&rp1_dma RP1_DMA_SPI3_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ // SPI4 is a target/slave interface ++ rp1_spi4: spi@60000 { ++ reg = <0xc0 0x40060000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <0>; ++ #size-cells = <0>; ++ num-cs = <1>; ++ spi-slave; ++ dmas = <&rp1_dma RP1_DMA_SPI4_TX>, ++ <&rp1_dma RP1_DMA_SPI4_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ ++ slave { ++ compatible = "spidev"; ++ spi-max-frequency = <1000000>; ++ }; ++ }; ++ ++ rp1_spi5: spi@64000 { ++ reg = <0xc0 0x40064000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI5_TX>, ++ <&rp1_dma RP1_DMA_SPI5_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ // SPI7 is a target/slave interface ++ rp1_spi7: spi@6c000 { ++ reg = <0xc0 0x4006c000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <0>; ++ #size-cells = <0>; ++ num-cs = <1>; ++ spi-slave; ++ dmas = <&rp1_dma RP1_DMA_SPI7_TX>, ++ <&rp1_dma RP1_DMA_SPI7_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ ++ slave { ++ compatible = "spidev"; ++ spi-max-frequency = <1000000>; ++ }; ++ }; ++ ++ rp1_i2c0: i2c@70000 { ++ reg = <0xc0 0x40070000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c1: i2c@74000 { ++ reg = <0xc0 0x40074000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c2: i2c@78000 { ++ reg = <0xc0 0x40078000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c3: i2c@7c000 { ++ reg = <0xc0 0x4007c000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c4: i2c@80000 { ++ reg = <0xc0 0x40080000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c5: i2c@84000 { ++ reg = <0xc0 0x40084000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c6: i2c@88000 { ++ reg = <0xc0 0x40088000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ status = "disabled"; ++ }; ++ ++ rp1_pwm0: pwm@98000 { ++ compatible = "raspberrypi,rp1-pwm"; ++ reg = <0xc0 0x40098000 0x0 0x100>; ++ #pwm-cells = <3>; ++ clocks = <&rp1_clocks RP1_CLK_PWM0>; ++ assigned-clocks = <&rp1_clocks RP1_CLK_PWM0>; ++ assigned-clock-rates = <6144000>; ++ status = "disabled"; ++ }; ++ ++ rp1_pwm1: pwm@9c000 { ++ compatible = "raspberrypi,rp1-pwm"; ++ reg = <0xc0 0x4009c000 0x0 0x100>; ++ #pwm-cells = <3>; ++ clocks = <&rp1_clocks RP1_CLK_PWM1>; ++ assigned-clocks = <&rp1_clocks RP1_CLK_PWM1>; ++ assigned-clock-rates = <6144000>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2s0: i2s@a0000 { ++ reg = <0xc0 0x400a0000 0x0 0x1000>; ++ compatible = "snps,designware-i2s"; ++ // Providing an interrupt disables DMA ++ // interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_I2S>; ++ clock-names = "i2sclk"; ++ #sound-dai-cells = <0>; ++ dmas = <&rp1_dma RP1_DMA_I2S0_TX>,<&rp1_dma RP1_DMA_I2S0_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_i2s1: i2s@a4000 { ++ reg = <0xc0 0x400a4000 0x0 0x1000>; ++ compatible = "snps,designware-i2s"; ++ // Providing an interrupt disables DMA ++ // interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_I2S>; ++ clock-names = "i2sclk"; ++ #sound-dai-cells = <0>; ++ dmas = <&rp1_dma RP1_DMA_I2S1_TX>,<&rp1_dma RP1_DMA_I2S1_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_i2s2: i2s@a8000 { ++ reg = <0xc0 0x400a8000 0x0 0x1000>; ++ compatible = "snps,designware-i2s"; ++ // Providing an interrupt disables DMA ++ // interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_I2S>; ++ status = "disabled"; ++ }; ++ ++ rp1_sdio_clk0: sdio_clk0@b0004 { ++ compatible = "raspberrypi,rp1-sdio-clk"; ++ reg = <0xc0 0x400b0004 0x0 0x1c>; ++ clocks = <&sdio_src &sdhci_core>; ++ clock-names = "src", "base"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ rp1_sdio_clk1: sdio_clk1@b4004 { ++ compatible = "raspberrypi,rp1-sdio-clk"; ++ reg = <0xc0 0x400b4004 0x0 0x1c>; ++ clocks = <&sdio_src &sdhci_core>; ++ clock-names = "src", "base"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ rp1_adc: adc@c8000 { ++ compatible = "raspberrypi,rp1-adc"; ++ reg = <0xc0 0x400c8000 0x0 0x4000>; ++ clocks = <&rp1_clocks RP1_CLK_ADC>; ++ clock-names = "adcclk"; ++ #clock-cells = <0>; ++ vref-supply = <&rp1_vdd_3v3>; ++ status = "disabled"; ++ }; ++ ++ rp1_gpio: gpio@d0000 { ++ reg = <0xc0 0x400d0000 0x0 0xc000>, ++ <0xc0 0x400e0000 0x0 0xc000>, ++ <0xc0 0x400f0000 0x0 0xc000>; ++ compatible = "raspberrypi,rp1-gpio"; ++ interrupts = , ++ , ++ ; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ++ rp1_uart0_14_15: rp1_uart0_14_15 { ++ pin_txd { ++ function = "uart0"; ++ pins = "gpio14"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart0"; ++ pins = "gpio15"; ++ bias-pull-up; ++ }; ++ }; ++ rp1_uart0_ctsrts_16_17: rp1_uart0_ctsrts_16_17 { ++ pin_cts { ++ function = "uart0"; ++ pins = "gpio16"; ++ bias-pull-up; ++ }; ++ pin_rts { ++ function = "uart0"; ++ pins = "gpio17"; ++ bias-disable; ++ }; ++ }; ++ rp1_uart1_0_1: rp1_uart1_0_1 { ++ pin_txd { ++ function = "uart1"; ++ pins = "gpio0"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart1"; ++ pins = "gpio1"; ++ bias-pull-up; ++ }; ++ }; ++ rp1_uart1_ctsrts_2_3: rp1_uart1_ctsrts_2_3 { ++ pin_cts { ++ function = "uart1"; ++ pins = "gpio2"; ++ bias-pull-up; ++ }; ++ pin_rts { ++ function = "uart1"; ++ pins = "gpio3"; ++ bias-disable; ++ }; ++ }; ++ rp1_uart2_4_5: rp1_uart2_4_5 { ++ pin_txd { ++ function = "uart2"; ++ pins = "gpio4"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart2"; ++ pins = "gpio5"; ++ bias-pull-up; ++ }; ++ }; ++ rp1_uart2_ctsrts_6_7: rp1_uart2_ctsrts_6_7 { ++ pin_cts { ++ function = "uart2"; ++ pins = "gpio6"; ++ bias-pull-up; ++ }; ++ pin_rts { ++ function = "uart2"; ++ pins = "gpio7"; ++ bias-disable; ++ }; ++ }; ++ rp1_uart3_8_9: rp1_uart3_8_9 { ++ pin_txd { ++ function = "uart3"; ++ pins = "gpio8"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart3"; ++ pins = "gpio9"; ++ bias-pull-up; ++ }; ++ }; ++ rp1_uart3_ctsrts_10_11: rp1_uart3_ctsrts_10_11 { ++ pin_cts { ++ function = "uart3"; ++ pins = "gpio10"; ++ bias-pull-up; ++ }; ++ pin_rts { ++ function = "uart3"; ++ pins = "gpio11"; ++ bias-disable; ++ }; ++ }; ++ rp1_uart4_12_13: rp1_uart4_12_13 { ++ pin_txd { ++ function = "uart4"; ++ pins = "gpio12"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart4"; ++ pins = "gpio13"; ++ bias-pull-up; ++ }; ++ }; ++ rp1_uart4_ctsrts_14_15: rp1_uart4_ctsrts_14_15 { ++ pin_cts { ++ function = "uart4"; ++ pins = "gpio14"; ++ bias-pull-up; ++ }; ++ pin_rts { ++ function = "uart4"; ++ pins = "gpio15"; ++ bias-disable; ++ }; ++ }; ++ ++ rp1_sdio0_22_27: rp1_sdio0_22_27 { ++ pin_clk { ++ function = "sd0"; ++ pins = "gpio22"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ pin_cmd { ++ function = "sd0"; ++ pins = "gpio23"; ++ bias-pull-up; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ pins_dat { ++ function = "sd0"; ++ pins = "gpio24", "gpio25", "gpio26", "gpio27"; ++ bias-pull-up; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ }; ++ ++ rp1_sdio1_28_33: rp1_sdio1_28_33 { ++ pin_clk { ++ function = "sd1"; ++ pins = "gpio28"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ pin_cmd { ++ function = "sd1"; ++ pins = "gpio29"; ++ bias-pull-up; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ pins_dat { ++ function = "sd1"; ++ pins = "gpio30", "gpio31", "gpio32", "gpio33"; ++ bias-pull-up; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ }; ++ ++ rp1_i2s0_18_21: rp1_i2s0_18_21 { ++ function = "i2s0"; ++ pins = "gpio18", "gpio19", "gpio20", "gpio21"; ++ bias-disable; ++ }; ++ ++ rp1_i2s1_18_21: rp1_i2s1_18_21 { ++ function = "i2s1"; ++ pins = "gpio18", "gpio19", "gpio20", "gpio21"; ++ bias-disable; ++ }; ++ ++ rp1_i2c4_34_35: rp1_i2c4_34_35 { ++ function = "i2c4"; ++ pins = "gpio34", "gpio35"; ++ bias-pull-up; ++ }; ++ rp1_i2c6_38_39: rp1_i2c6_38_39 { ++ function = "i2c6"; ++ pins = "gpio38", "gpio39"; ++ bias-pull-up; ++ }; ++ rp1_i2c4_40_41: rp1_i2c4_40_41 { ++ function = "i2c4"; ++ pins = "gpio40", "gpio41"; ++ bias-pull-up; ++ }; ++ rp1_i2c5_44_45: rp1_i2c5_44_45 { ++ function = "i2c5"; ++ pins = "gpio44", "gpio45"; ++ bias-pull-up; ++ }; ++ rp1_i2c0_0_1: rp1_i2c0_0_1 { ++ function = "i2c0"; ++ pins = "gpio0", "gpio1"; ++ bias-pull-up; ++ }; ++ rp1_i2c0_8_9: rp1_i2c0_8_9 { ++ function = "i2c0"; ++ pins = "gpio8", "gpio9"; ++ bias-pull-up; ++ }; ++ rp1_i2c1_2_3: rp1_i2c1_2_3 { ++ function = "i2c1"; ++ pins = "gpio2", "gpio3"; ++ bias-pull-up; ++ }; ++ rp1_i2c1_10_11: rp1_i2c1_10_11 { ++ function = "i2c1"; ++ pins = "gpio10", "gpio11"; ++ bias-pull-up; ++ }; ++ rp1_i2c2_4_5: rp1_i2c2_4_5 { ++ function = "i2c2"; ++ pins = "gpio4", "gpio5"; ++ bias-pull-up; ++ }; ++ rp1_i2c2_12_13: rp1_i2c2_12_13 { ++ function = "i2c2"; ++ pins = "gpio12", "gpio13"; ++ bias-pull-up; ++ }; ++ rp1_i2c3_6_7: rp1_i2c3_6_7 { ++ function = "i2c3"; ++ pins = "gpio6", "gpio7"; ++ bias-pull-up; ++ }; ++ rp1_i2c3_14_15: rp1_i2c3_14_15 { ++ function = "i2c3"; ++ pins = "gpio14", "gpio15"; ++ bias-pull-up; ++ }; ++ rp1_i2c3_22_23: rp1_i2c3_22_23 { ++ function = "i2c3"; ++ pins = "gpio22", "gpio23"; ++ bias-pull-up; ++ }; ++ ++ // DPI mappings with HSYNC,VSYNC but without PIXCLK,DE ++ rp1_dpi_16bit_gpio2: rp1_dpi_16bit_gpio2 { /* Mode 2, not fully supported by RP1 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", "gpio4", "gpio5", ++ "gpio6", "gpio7", "gpio8", "gpio9", ++ "gpio10", "gpio11", "gpio12", "gpio13", ++ "gpio14", "gpio15", "gpio16", "gpio17", ++ "gpio18", "gpio19"; ++ bias-disable; ++ }; ++ rp1_dpi_16bit_cpadhi_gpio2: rp1_dpi_16bit_cpadhi_gpio2 { /* Mode 3 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", "gpio4", "gpio5", ++ "gpio6", "gpio7", "gpio8", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio20", "gpio21", "gpio22", "gpio23", ++ "gpio24"; ++ bias-disable; ++ }; ++ rp1_dpi_16bit_pad666_gpio2: rp1_dpi_16bit_pad666_gpio2 { /* Mode 4 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", ++ "gpio5", "gpio6", "gpio7", "gpio8", ++ "gpio9", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio21", "gpio22", "gpio23", "gpio24", ++ "gpio25"; ++ bias-disable; ++ }; ++ rp1_dpi_18bit_gpio2: rp1_dpi_18bit_gpio2 { /* Mode 5, not fully supported by RP1 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", "gpio4", "gpio5", ++ "gpio6", "gpio7", "gpio8", "gpio9", ++ "gpio10", "gpio11", "gpio12", "gpio13", ++ "gpio14", "gpio15", "gpio16", "gpio17", ++ "gpio18", "gpio19", "gpio20", "gpio21"; ++ bias-disable; ++ }; ++ rp1_dpi_18bit_cpadhi_gpio2: rp1_dpi_18bit_cpadhi_gpio2 { /* Mode 6 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", "gpio4", "gpio5", ++ "gpio6", "gpio7", "gpio8", "gpio9", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio20", "gpio21", "gpio22", "gpio23", ++ "gpio24", "gpio25"; ++ bias-disable; ++ }; ++ rp1_dpi_24bit_gpio2: rp1_dpi_24bit_gpio2 { /* Mode 7 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", "gpio4", "gpio5", ++ "gpio6", "gpio7", "gpio8", "gpio9", ++ "gpio10", "gpio11", "gpio12", "gpio13", ++ "gpio14", "gpio15", "gpio16", "gpio17", ++ "gpio18", "gpio19", "gpio20", "gpio21", ++ "gpio22", "gpio23", "gpio24", "gpio25", ++ "gpio26", "gpio27"; ++ bias-disable; ++ }; ++ rp1_dpi_hvsync: rp1_dpi_hvsync { /* Sync only, for use with int VDAC */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3"; ++ bias-disable; ++ }; ++ ++ // More DPI mappings, including PIXCLK,DE on GPIOs 0,1 ++ rp1_dpi_16bit_gpio0: rp1_dpi_16bit_gpio0 { /* Mode 2, not fully supported by RP1 */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio4", "gpio5", "gpio6", "gpio7", ++ "gpio8", "gpio9", "gpio10", "gpio11", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", "gpio18", "gpio19"; ++ bias-disable; ++ }; ++ rp1_dpi_16bit_cpadhi_gpio0: rp1_dpi_16bit_cpadhi_gpio0 { /* Mode 3 */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio4", "gpio5", "gpio6", "gpio7", ++ "gpio8", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio20", "gpio21", "gpio22", "gpio23", ++ "gpio24"; ++ bias-disable; ++ }; ++ rp1_dpi_16bit_pad666_gpio0: rp1_dpi_16bit_pad666_gpio0 { /* Mode 4 */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio5", "gpio6", "gpio7", "gpio8", ++ "gpio9", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio21", "gpio22", "gpio23", "gpio24", ++ "gpio25"; ++ bias-disable; ++ }; ++ rp1_dpi_18bit_gpio0: rp1_dpi_18bit_gpio0 { /* Mode 5, not fully supported by RP1 */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio4", "gpio5", "gpio6", "gpio7", ++ "gpio8", "gpio9", "gpio10", "gpio11", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", "gpio18", "gpio19", ++ "gpio20", "gpio21"; ++ bias-disable; ++ }; ++ rp1_dpi_18bit_cpadhi_gpio0: rp1_dpi_18bit_cpadhi_gpio0 { /* Mode 6 */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio4", "gpio5", "gpio6", "gpio7", ++ "gpio8", "gpio9", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio20", "gpio21", "gpio22", "gpio23", ++ "gpio24", "gpio25"; ++ bias-disable; ++ }; ++ rp1_dpi_24bit_gpio0: rp1_dpi_24bit_gpio0 { /* Mode 7 -- All GPIOs used! */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio4", "gpio5", "gpio6", "gpio7", ++ "gpio8", "gpio9", "gpio10", "gpio11", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", "gpio18", "gpio19", ++ "gpio20", "gpio21", "gpio22", "gpio23", ++ "gpio24", "gpio25", "gpio26", "gpio27"; ++ bias-disable; ++ }; ++ ++ rp1_pwm1_gpio45: rp1_pwm1_gpio45 { ++ function = "pwm1"; ++ pins = "gpio45"; ++ bias-pull-down; ++ }; ++ ++ rp1_spi0_gpio9: rp1_spi0_gpio9 { ++ function = "spi0"; ++ pins = "gpio9", "gpio10", "gpio11"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi0_cs_gpio7: rp1_spi0_cs_gpio7 { ++ function = "spi0"; ++ pins = "gpio7", "gpio8"; ++ bias-pull-up; ++ }; ++ ++ rp1_spi1_gpio19: rp1_spi1_gpio19 { ++ function = "spi1"; ++ pins = "gpio19", "gpio20", "gpio21"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi2_gpio1: rp1_spi2_gpio1 { ++ function = "spi2"; ++ pins = "gpio1", "gpio2", "gpio3"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi3_gpio5: rp1_spi3_gpio5 { ++ function = "spi3"; ++ pins = "gpio5", "gpio6", "gpio7"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi4_gpio9: rp1_spi4_gpio9 { ++ function = "spi4"; ++ pins = "gpio9", "gpio10", "gpio11"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi5_gpio13: rp1_spi5_gpio13 { ++ function = "spi5"; ++ pins = "gpio13", "gpio14", "gpio15"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi8_gpio49: rp1_spi8_gpio49 { ++ function = "spi8"; ++ pins = "gpio49", "gpio50", "gpio51"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi8_cs_gpio52: rp1_spi8_cs_gpio52 { ++ function = "spi0"; ++ pins = "gpio52", "gpio53"; ++ bias-pull-up; ++ }; ++ }; ++ ++ rp1_eth: ethernet@100000 { ++ reg = <0xc0 0x40100000 0x0 0x4000>; ++ compatible = "cdns,macb"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clocks = <&macb_pclk &macb_hclk &rp1_clocks RP1_CLK_ETH_TSU>; ++ clock-names = "pclk", "hclk", "tsu_clk"; ++ phy-mode = "rgmii-id"; ++ cdns,aw2w-max-pipe = /bits/ 8 <8>; ++ cdns,ar2r-max-pipe = /bits/ 8 <8>; ++ cdns,use-aw2b-fill; ++ local-mac-address = [00 00 00 00 00 00]; ++ status = "disabled"; ++ }; ++ ++ rp1_csi0: csi@110000 { ++ compatible = "raspberrypi,rp1-cfe"; ++ reg = <0xc0 0x40110000 0x0 0x100>, // CSI2 DMA address ++ <0xc0 0x40114000 0x0 0x100>, // PHY/CSI Host address ++ <0xc0 0x40120000 0x0 0x100>, // MIPI CFG address ++ <0xc0 0x40124000 0x0 0x1000>; // PiSP FE address ++ ++ // interrupts must match rp1_pisp_fe setup ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>; ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>; ++ assigned-clock-rates = <25000000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ rp1_csi1: csi@128000 { ++ compatible = "raspberrypi,rp1-cfe"; ++ reg = <0xc0 0x40128000 0x0 0x100>, // CSI2 DMA address ++ <0xc0 0x4012c000 0x0 0x100>, // PHY/CSI Host address ++ <0xc0 0x40138000 0x0 0x100>, // MIPI CFG address ++ <0xc0 0x4013c000 0x0 0x1000>; // PiSP FE address ++ ++ // interrupts must match rp1_pisp_fe setup ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>; ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>; ++ assigned-clock-rates = <25000000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ rp1_mmc0: mmc@180000 { ++ reg = <0xc0 0x40180000 0x0 0x100>; ++ compatible = "snps,dwcmshc-sdhci"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core ++ &rp1_clocks RP1_CLK_SDIO_TIMER ++ &rp1_sdio_clk0>; ++ clock-names = "bus", "core", "timeout", "sdio"; ++ /* Bank 0 VDDIO is fixed */ ++ no-1-8-v; ++ bus-width = <4>; ++ vmmc-supply = <&rp1_vdd_3v3>; ++ broken-cd; ++ status = "disabled"; ++ }; ++ ++ rp1_mmc1: mmc@184000 { ++ reg = <0xc0 0x40184000 0x0 0x100>; ++ compatible = "snps,dwcmshc-sdhci"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core ++ &rp1_clocks RP1_CLK_SDIO_TIMER ++ &rp1_sdio_clk1>; ++ clock-names = "bus", "core", "timeout", "sdio"; ++ bus-width = <4>; ++ vmmc-supply = <&rp1_vdd_3v3>; ++ /* Nerf SDR speeds */ ++ sdhci-caps-mask = <0x3 0x0>; ++ broken-cd; ++ status = "disabled"; ++ }; ++ ++ rp1_dma: dma@188000 { ++ reg = <0xc0 0x40188000 0x0 0x1000>; ++ compatible = "snps,axi-dma-1.01a"; ++ interrupts = ; ++ clocks = <&sdhci_core &rp1_clocks RP1_CLK_SYS>; ++ clock-names = "core-clk", "cfgr-clk"; ++ ++ #dma-cells = <1>; ++ dma-channels = <8>; ++ snps,dma-masters = <1>; ++ snps,dma-targets = <64>; ++ snps,data-width = <4>; // (8 << 4) == 128 bits ++ snps,block-size = <0x40000 0x40000 0x40000 0x40000 0x40000 0x40000 0x40000 0x40000>; ++ snps,priority = <0 1 2 3 4 5 6 7>; ++ snps,axi-max-burst-len = <8>; ++ status = "disabled"; ++ }; ++ ++ rp1_usb0: usb@200000 { ++ reg = <0xc0 0x40200000 0x0 0x100000>; ++ compatible = "snps,dwc3"; ++ dr_mode = "host"; ++ usb3-lpm-capable; ++ snps,axi-pipe-limit = /bits/ 8 <8>; ++ snps,dis_rxdet_inp3_quirk; ++ snps,tx-max-burst-prd = <8>; ++ snps,tx-thr-num-pkt-prd = <2>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ rp1_usb1: usb@300000 { ++ reg = <0xc0 0x40300000 0x0 0x100000>; ++ compatible = "snps,dwc3"; ++ dr_mode = "host"; ++ usb3-lpm-capable; ++ snps,axi-pipe-limit = /bits/ 8 <8>; ++ snps,dis_rxdet_inp3_quirk; ++ snps,tx-max-burst-prd = <8>; ++ snps,tx-thr-num-pkt-prd = <2>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ rp1_dsi0: dsi@110000 { ++ compatible = "raspberrypi,rp1dsi"; ++ status = "disabled"; ++ reg = <0xc0 0x40118000 0x0 0x1000>, // MIPI0 DSI DMA (ArgonDPI) ++ <0xc0 0x4011c000 0x0 0x1000>, // MIPI0 DSI Host (SNPS) ++ <0xc0 0x40120000 0x0 0x1000>; // MIPI0 CFG ++ ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>, // required, config bus clock ++ <&rp1_clocks RP1_CLK_MIPI0_DPI>, // required, pixel clock ++ <&clksrc_mipi0_dsi_byteclk>, // internal, parent for divide ++ <&clk_xosc>; // hardwired to DSI "refclk" ++ clock-names = "cfgclk", "dpiclk", "byteclk", "refclk"; ++ ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>, ++ <&rp1_clocks RP1_CLK_MIPI0_DPI>; ++ assigned-clock-rates = <25000000>; ++ assigned-clock-parents = <0>, <&clksrc_mipi0_dsi_byteclk>; ++ }; ++ ++ rp1_dsi1: dsi@128000 { ++ compatible = "raspberrypi,rp1dsi"; ++ status = "disabled"; ++ reg = <0xc0 0x40130000 0x0 0x1000>, // MIPI1 DSI DMA (ArgonDPI) ++ <0xc0 0x40134000 0x0 0x1000>, // MIPI1 DSI Host (SNPS) ++ <0xc0 0x40138000 0x0 0x1000>; // MIPI1 CFG ++ ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>, // required, config bus clock ++ <&rp1_clocks RP1_CLK_MIPI1_DPI>, // required, pixel clock ++ <&clksrc_mipi1_dsi_byteclk>, // internal, parent for divide ++ <&clk_xosc>; // hardwired to DSI "refclk" ++ clock-names = "cfgclk", "dpiclk", "byteclk", "refclk"; ++ ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>, ++ <&rp1_clocks RP1_CLK_MIPI1_DPI>; ++ assigned-clock-rates = <25000000>; ++ assigned-clock-parents = <0>, <&clksrc_mipi1_dsi_byteclk>; ++ }; ++ ++ /* VEC and DPI both need to control PLL_VIDEO and cannot work together; */ ++ /* config.txt should enable one or other using dtparam=vec or an overlay. */ ++ rp1_vec: vec@144000 { ++ compatible = "raspberrypi,rp1vec"; ++ status = "disabled"; ++ reg = <0xc0 0x40144000 0x0 0x1000>, // VIDEO_OUT_VEC ++ <0xc0 0x40140000 0x0 0x1000>; // VIDEO_OUT_CFG ++ ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_VEC>; ++ ++ assigned-clocks = <&rp1_clocks RP1_PLL_VIDEO_CORE>, ++ <&rp1_clocks RP1_PLL_VIDEO_SEC>, ++ <&rp1_clocks RP1_CLK_VEC>; ++ assigned-clock-rates = <1188000000>, ++ <108000000>, ++ <108000000>; ++ assigned-clock-parents = <0>, ++ <&rp1_clocks RP1_PLL_VIDEO_CORE>, ++ <&rp1_clocks RP1_PLL_VIDEO_SEC>; ++ }; ++ ++ rp1_dpi: dpi@148000 { ++ compatible = "raspberrypi,rp1dpi"; ++ status = "disabled"; ++ reg = <0xc0 0x40148000 0x0 0x1000>, // VIDEO_OUT DPI ++ <0xc0 0x40140000 0x0 0x1000>; // VIDEO_OUT_CFG ++ ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_DPI>, // DPI pixel clock ++ <&rp1_clocks RP1_PLL_VIDEO>, // PLL primary divider, and ++ <&rp1_clocks RP1_PLL_VIDEO_CORE>; // VCO, which we also control ++ clock-names = "dpiclk", "plldiv", "pllcore"; ++ ++ assigned-clocks = <&rp1_clocks RP1_CLK_DPI>; ++ assigned-clock-parents = <&rp1_clocks RP1_PLL_VIDEO>; ++ }; ++ }; ++}; ++ ++&clocks { ++ clk_xosc: clk_xosc { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "xosc"; ++ clock-frequency = <50000000>; ++ }; ++ macb_pclk: macb_pclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "pclk"; ++ clock-frequency = <200000000>; ++ }; ++ macb_hclk: macb_hclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "hclk"; ++ clock-frequency = <200000000>; ++ }; ++ sdio_src: sdio_src { ++ // 400 MHz on FPGA. PLL sys VCO on asic ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "src"; ++ clock-frequency = <1000000000>; ++ }; ++ sdhci_core: sdhci_core { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "core"; ++ clock-frequency = <50000000>; ++ }; ++ clksrc_mipi0_dsi_byteclk: clksrc_mipi0_dsi_byteclk { ++ // This clock is synthesized by MIPI0 D-PHY, when DSI is running. ++ // Its frequency is not known a priori (until a panel driver attaches) ++ // so assign a made-up frequency of 72MHz so it can be divided for DPI. ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "clksrc_mipi0_dsi_byteclk"; ++ clock-frequency = <72000000>; ++ }; ++ clksrc_mipi1_dsi_byteclk: clksrc_mipi1_dsi_byteclk { ++ // This clock is synthesized by MIPI1 D-PHY, when DSI is running. ++ // Its frequency is not known a priori (until a panel driver attaches) ++ // so assign a made-up frequency of 72MHz so it can be divided for DPI. ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "clksrc_mipi1_dsi_byteclk"; ++ clock-frequency = <72000000>; ++ }; ++}; ++ ++/ { ++ rp1_vdd_3v3: rp1_vdd_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd-3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; ++}; +--- a/arch/arm64/boot/dts/broadcom/Makefile ++++ b/arch/arm64/boot/dts/broadcom/Makefile +@@ -16,6 +16,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rp + dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-cm3.dtb + dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-cm4.dtb + dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-cm4s.dtb ++dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rpi-5-b.dtb + + subdir-y += bcmbca + subdir-y += northstar2 +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts +@@ -0,0 +1 @@ ++#include "../../../../arm/boot/dts/bcm2712-rpi-5-b.dts" diff --git a/target/linux/bcm27xx/patches-6.1/950-0855-gpio_brcmstb-Allow-to-build-for-ARCH_BCM2835.patch b/target/linux/bcm27xx/patches-6.1/950-0855-gpio_brcmstb-Allow-to-build-for-ARCH_BCM2835.patch new file mode 100644 index 0000000000..7e39ac8abf --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0855-gpio_brcmstb-Allow-to-build-for-ARCH_BCM2835.patch @@ -0,0 +1,282 @@ +From fa18902ee1e53ad391a455a01be3ab2ea1c5af5f Mon Sep 17 00:00:00 2001 +From: Dom Cobley +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 + +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 + +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 +--- + 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); diff --git a/target/linux/bcm27xx/patches-6.1/950-0856-Allow-RESET_BRCMSTB-on-ARCH_BCM2835.patch b/target/linux/bcm27xx/patches-6.1/950-0856-Allow-RESET_BRCMSTB-on-ARCH_BCM2835.patch new file mode 100644 index 0000000000..7e0886d7e6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0856-Allow-RESET_BRCMSTB-on-ARCH_BCM2835.patch @@ -0,0 +1,20 @@ +From 22ae3b2ee3293278e647877b269a5aebad3f077d Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0857-pinctrl-bcm2712-pinctrl-pinconf-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0857-pinctrl-bcm2712-pinctrl-pinconf-driver.patch new file mode 100644 index 0000000000..429c3e2fd2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0857-pinctrl-bcm2712-pinctrl-pinconf-driver.patch @@ -0,0 +1,1324 @@ +From af7e60a33f0b5ce84bffb69ba084ba1edd180195 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 9 Jun 2021 15:48:28 +0100 +Subject: [PATCH] pinctrl: bcm2712 pinctrl/pinconf driver + +pinctrl: bcm2712: Reject invalid pulls + +Reject attempts to set pulls on aon-sgpios, and fix pull shift +values. + +pinctrl: bcm2712: Add 7712 support, fix 2712 count + +Signed-off-by: Phil Elwell + +pinctrl-bcm2712: add EMMC pins so pulls can be set + +These pins have pad controls but not mux controls. They look enough like +GPIOs to squeeze in at the end of the list though. + +pinctrl: bcm2712: correct BCM2712C0 AON_GPIO pad pull control offset + +Signed-off-by: Jonathan Bell + +pinctrl: bcm2712: on C0 the regular GPIO pad control register moves too + +Signed-off-by: Jonathan Bell + +pinctrl: bcm2712: Implement (partially) pinconf_get + +Signed-off-by: Phil Elwell + +pinctrl: bcm2712: Convert to generic pinconf + +Remove the legacy brcm,* pin configuration support and replace it with +a proper generic pinconf interface, using named functions instead of +alt function numbers. This is nicer for users, less error-prone, and +immune to some of the C0->D0 changes. + +Signed-off-by: Phil Elwell + +pinctrl: bcm2712: Remove vestigial pull parameter + +Now the legacy brcm, pinconf parameters are no longer supported, this +custom pin config parameter is not needed. + +Signed-off-by: Phil Elwell + +pinctrl: bcm2712: Guard against bad func numbers + +Signed-off-by: Phil Elwell + +pinctrl: bcm2712: A better attempt at D0 support + +The BCM2712D0 sparse pinctrl maps play havoc with the old GPIO_REGS +macro, so make the bit positions explicit. And delete the unwanted +GPIO and pinmux declarations on D0. + +Note that a Pi 5 with D0 requires a separate DTS file with "bcm2712d0" +compatible strings. + +Signed-off-by: Phil Elwell + +pinctrl: bcm2712: Delete base register constants + +BCM2712D0 deletes many GPIOs and their associated mux and pad bits, +so much so that the offsets to the start of the pad control registers +changes. Remove the constant offsets from the *GPIO_REGS macros, +compensating by adjusting the per-GPIO values. + +Signed-off-by: Phil Elwell +--- + drivers/pinctrl/bcm/Kconfig | 9 + + drivers/pinctrl/bcm/Makefile | 1 + + drivers/pinctrl/bcm/pinctrl-bcm2712.c | 1216 +++++++++++++++++++++++++ + 3 files changed, 1226 insertions(+) + create mode 100644 drivers/pinctrl/bcm/pinctrl-bcm2712.c + +--- a/drivers/pinctrl/bcm/Kconfig ++++ b/drivers/pinctrl/bcm/Kconfig +@@ -3,6 +3,15 @@ + # Broadcom pinctrl drivers + # + ++config PINCTRL_BCM2712 ++ bool "Broadcom BCM2712 PINCONF driver" ++ depends on OF && (ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST) ++ select PINMUX ++ select PINCONF ++ select GENERIC_PINCONF ++ help ++ Say Y here to enable the Broadcom BCM2835 GPIO driver. ++ + config PINCTRL_BCM281XX + bool "Broadcom BCM281xx pinctrl driver" + depends on OF && (ARCH_BCM_MOBILE || COMPILE_TEST) +--- a/drivers/pinctrl/bcm/Makefile ++++ b/drivers/pinctrl/bcm/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + # Broadcom pinctrl support + ++obj-$(CONFIG_PINCTRL_BCM2712) += pinctrl-bcm2712.o + obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o + obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o + obj-$(CONFIG_PINCTRL_BCM4908) += pinctrl-bcm4908.o +--- /dev/null ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2712.c +@@ -0,0 +1,1216 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Driver for Broadcom BCM2712 GPIO units (pinctrl only) ++ * ++ * Copyright (C) 2021-3 Raspberry Pi Ltd. ++ * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren ++ * ++ * Based heavily on the BCM2835 GPIO & pinctrl driver, which was inspired by: ++ * pinctrl-nomadik.c, please see original file for copyright information ++ * pinctrl-tegra.c, please see original file for copyright information ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "pinctrl-bcm2712" ++ ++/* Register offsets */ ++ ++#define BCM2712_PULL_NONE 0 ++#define BCM2712_PULL_DOWN 1 ++#define BCM2712_PULL_UP 2 ++#define BCM2712_PULL_MASK 0x3 ++ ++#define BCM2712_FSEL_COUNT 9 ++#define BCM2712_FSEL_MASK 0xf ++ ++#define FUNC(f) \ ++ [func_##f] = #f ++#define PIN(i, f1, f2, f3, f4, f5, f6, f7, f8) \ ++ [i] = { \ ++ .funcs = { \ ++ func_##f1, \ ++ func_##f2, \ ++ func_##f3, \ ++ func_##f4, \ ++ func_##f5, \ ++ func_##f6, \ ++ func_##f7, \ ++ func_##f8, \ ++ }, \ ++ } ++ ++#define REG_BIT_INVALID 0xffff ++ ++#define BIT_TO_REG(b) (((b) >> 5) << 2) ++#define BIT_TO_SHIFT(b) ((b) & 0x1f) ++ ++#define GPIO_REGS(n, mr, mb, pr, pb) \ ++ [n] = { ((mr)*4)*8 + (mb)*4, ((pr)*4)*8 + (pb)*2 } ++ ++#define EMMC_REGS(n, r, b) \ ++ [n] = { 0, ((r)*4)*8 + (b)*2 } ++ ++#define AGPIO_REGS(n, mr, mb, pr, pb) \ ++ [n] = { ((mr)*4)*8 + (mb)*4, ((pr)*4)*8 + (pb)*2 } ++ ++#define SGPIO_REGS(n, mr, mb) \ ++ [n+32] = { ((mr)*4)*8 + (mb)*4, REG_BIT_INVALID } ++ ++#define GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a) ++#define AGPIO_PIN(a) PINCTRL_PIN(a, "aon_gpio" #a) ++#define SGPIO_PIN(a) PINCTRL_PIN(a+32, "aon_sgpio" #a) ++ ++struct pin_regs { ++ u16 mux_bit; ++ u16 pad_bit; ++}; ++ ++struct bcm2712_pinctrl { ++ struct device *dev; ++ void __iomem *base; ++ struct pinctrl_dev *pctl_dev; ++ struct pinctrl_desc pctl_desc; ++ const struct pin_regs *pin_regs; ++ const struct bcm2712_pin_funcs *pin_funcs; ++ const char *const *gpio_groups; ++ struct pinctrl_gpio_range gpio_range; ++ spinlock_t lock; ++}; ++ ++struct bcm_plat_data { ++ const struct pinctrl_desc *pctl_desc; ++ const struct pinctrl_gpio_range *gpio_range; ++ const struct pin_regs *pin_regs; ++ const struct bcm2712_pin_funcs *pin_funcs; ++}; ++ ++struct bcm2712_pin_funcs { ++ u8 funcs[BCM2712_FSEL_COUNT - 1]; ++}; ++ ++enum bcm2712_funcs { ++ func_gpio, ++ func_alt1, ++ func_alt2, ++ func_alt3, ++ func_alt4, ++ func_alt5, ++ func_alt6, ++ func_alt7, ++ func_alt8, ++ func_aon_cpu_standbyb, ++ func_aon_fp_4sec_resetb, ++ func_aon_gpclk, ++ func_aon_pwm, ++ func_arm_jtag, ++ func_aud_fs_clk0, ++ func_avs_pmu_bsc, ++ func_bsc_m0, ++ func_bsc_m1, ++ func_bsc_m2, ++ func_bsc_m3, ++ func_clk_observe, ++ func_ctl_hdmi_5v, ++ func_enet0, ++ func_enet0_mii, ++ func_enet0_rgmii, ++ func_ext_sc_clk, ++ func_fl0, ++ func_fl1, ++ func_gpclk0, ++ func_gpclk1, ++ func_gpclk2, ++ func_hdmi_tx0_auto_i2c, ++ func_hdmi_tx0_bsc, ++ func_hdmi_tx1_auto_i2c, ++ func_hdmi_tx1_bsc, ++ func_i2s_in, ++ func_i2s_out, ++ func_ir_in, ++ func_mtsif, ++ func_mtsif_alt, ++ func_mtsif_alt1, ++ func_pdm, ++ func_pkt, ++ func_pm_led_out, ++ func_sc0, ++ func_sd0, ++ func_sd2, ++ func_sd_card_a, ++ func_sd_card_b, ++ func_sd_card_c, ++ func_sd_card_d, ++ func_sd_card_e, ++ func_sd_card_f, ++ func_sd_card_g, ++ func_spdif_out, ++ func_spi_m, ++ func_spi_s, ++ func_sr_edm_sense, ++ func_te0, ++ func_te1, ++ func_tsio, ++ func_uart0, ++ func_uart1, ++ func_uart2, ++ func_usb_pwr, ++ func_usb_vbus, ++ func_uui, ++ func_vc_i2c0, ++ func_vc_i2c3, ++ func_vc_i2c4, ++ func_vc_i2c5, ++ func_vc_i2csl, ++ func_vc_pcm, ++ func_vc_pwm0, ++ func_vc_pwm1, ++ func_vc_spi0, ++ func_vc_spi3, ++ func_vc_spi4, ++ func_vc_spi5, ++ func_vc_uart0, ++ func_vc_uart2, ++ func_vc_uart3, ++ func_vc_uart4, ++ func__, ++ func_count = func__ ++}; ++ ++static const struct pin_regs bcm2712_c0_gpio_pin_regs[] = { ++ GPIO_REGS(0, 0, 0, 7, 7), ++ GPIO_REGS(1, 0, 1, 7, 8), ++ GPIO_REGS(2, 0, 2, 7, 9), ++ GPIO_REGS(3, 0, 3, 7, 10), ++ GPIO_REGS(4, 0, 4, 7, 11), ++ GPIO_REGS(5, 0, 5, 7, 12), ++ GPIO_REGS(6, 0, 6, 7, 13), ++ GPIO_REGS(7, 0, 7, 7, 14), ++ GPIO_REGS(8, 1, 0, 8, 0), ++ GPIO_REGS(9, 1, 1, 8, 1), ++ GPIO_REGS(10, 1, 2, 8, 2), ++ GPIO_REGS(11, 1, 3, 8, 3), ++ GPIO_REGS(12, 1, 4, 8, 4), ++ GPIO_REGS(13, 1, 5, 8, 5), ++ GPIO_REGS(14, 1, 6, 8, 6), ++ GPIO_REGS(15, 1, 7, 8, 7), ++ GPIO_REGS(16, 2, 0, 8, 8), ++ GPIO_REGS(17, 2, 1, 8, 9), ++ GPIO_REGS(18, 2, 2, 8, 10), ++ GPIO_REGS(19, 2, 3, 8, 11), ++ GPIO_REGS(20, 2, 4, 8, 12), ++ GPIO_REGS(21, 2, 5, 8, 13), ++ GPIO_REGS(22, 2, 6, 8, 14), ++ GPIO_REGS(23, 2, 7, 9, 0), ++ GPIO_REGS(24, 3, 0, 9, 1), ++ GPIO_REGS(25, 3, 1, 9, 2), ++ GPIO_REGS(26, 3, 2, 9, 3), ++ GPIO_REGS(27, 3, 3, 9, 4), ++ GPIO_REGS(28, 3, 4, 9, 5), ++ GPIO_REGS(29, 3, 5, 9, 6), ++ GPIO_REGS(30, 3, 6, 9, 7), ++ GPIO_REGS(31, 3, 7, 9, 8), ++ GPIO_REGS(32, 4, 0, 9, 9), ++ GPIO_REGS(33, 4, 1, 9, 10), ++ GPIO_REGS(34, 4, 2, 9, 11), ++ GPIO_REGS(35, 4, 3, 9, 12), ++ GPIO_REGS(36, 4, 4, 9, 13), ++ GPIO_REGS(37, 4, 5, 9, 14), ++ GPIO_REGS(38, 4, 6, 10, 0), ++ GPIO_REGS(39, 4, 7, 10, 1), ++ GPIO_REGS(40, 5, 0, 10, 2), ++ GPIO_REGS(41, 5, 1, 10, 3), ++ GPIO_REGS(42, 5, 2, 10, 4), ++ GPIO_REGS(43, 5, 3, 10, 5), ++ GPIO_REGS(44, 5, 4, 10, 6), ++ GPIO_REGS(45, 5, 5, 10, 7), ++ GPIO_REGS(46, 5, 6, 10, 8), ++ GPIO_REGS(47, 5, 7, 10, 9), ++ GPIO_REGS(48, 6, 0, 10, 10), ++ GPIO_REGS(49, 6, 1, 10, 11), ++ GPIO_REGS(50, 6, 2, 10, 12), ++ GPIO_REGS(51, 6, 3, 10, 13), ++ GPIO_REGS(52, 6, 4, 10, 14), ++ GPIO_REGS(53, 6, 5, 11, 0), ++ EMMC_REGS(54, 11, 1), /* EMMC_CMD */ ++ EMMC_REGS(55, 11, 2), /* EMMC_DS */ ++ EMMC_REGS(56, 11, 3), /* EMMC_CLK */ ++ EMMC_REGS(57, 11, 4), /* EMMC_DAT0 */ ++ EMMC_REGS(58, 11, 5), /* EMMC_DAT1 */ ++ EMMC_REGS(59, 11, 6), /* EMMC_DAT2 */ ++ EMMC_REGS(60, 11, 7), /* EMMC_DAT3 */ ++ EMMC_REGS(61, 11, 8), /* EMMC_DAT4 */ ++ EMMC_REGS(62, 11, 9), /* EMMC_DAT5 */ ++ EMMC_REGS(63, 11, 10), /* EMMC_DAT6 */ ++ EMMC_REGS(64, 11, 11), /* EMMC_DAT7 */ ++}; ++ ++static struct pin_regs bcm2712_c0_aon_gpio_pin_regs[] = { ++ AGPIO_REGS(0, 3, 0, 6, 10), ++ AGPIO_REGS(1, 3, 1, 6, 11), ++ AGPIO_REGS(2, 3, 2, 6, 12), ++ AGPIO_REGS(3, 3, 3, 6, 13), ++ AGPIO_REGS(4, 3, 4, 6, 14), ++ AGPIO_REGS(5, 3, 5, 7, 0), ++ AGPIO_REGS(6, 3, 6, 7, 1), ++ AGPIO_REGS(7, 3, 7, 7, 2), ++ AGPIO_REGS(8, 4, 0, 7, 3), ++ AGPIO_REGS(9, 4, 1, 7, 4), ++ AGPIO_REGS(10, 4, 2, 7, 5), ++ AGPIO_REGS(11, 4, 3, 7, 6), ++ AGPIO_REGS(12, 4, 4, 7, 7), ++ AGPIO_REGS(13, 4, 5, 7, 8), ++ AGPIO_REGS(14, 4, 6, 7, 9), ++ AGPIO_REGS(15, 4, 7, 7, 10), ++ AGPIO_REGS(16, 5, 0, 7, 11), ++ SGPIO_REGS(0, 0, 0), ++ SGPIO_REGS(1, 0, 1), ++ SGPIO_REGS(2, 0, 2), ++ SGPIO_REGS(3, 0, 3), ++ SGPIO_REGS(4, 1, 0), ++ SGPIO_REGS(5, 2, 0), ++}; ++ ++static const struct pinctrl_pin_desc bcm2712_c0_gpio_pins[] = { ++ GPIO_PIN(0), ++ GPIO_PIN(1), ++ GPIO_PIN(2), ++ GPIO_PIN(3), ++ GPIO_PIN(4), ++ GPIO_PIN(5), ++ GPIO_PIN(6), ++ GPIO_PIN(7), ++ GPIO_PIN(8), ++ GPIO_PIN(9), ++ GPIO_PIN(10), ++ GPIO_PIN(11), ++ GPIO_PIN(12), ++ GPIO_PIN(13), ++ GPIO_PIN(14), ++ GPIO_PIN(15), ++ GPIO_PIN(16), ++ GPIO_PIN(17), ++ GPIO_PIN(18), ++ GPIO_PIN(19), ++ GPIO_PIN(20), ++ GPIO_PIN(21), ++ GPIO_PIN(22), ++ GPIO_PIN(23), ++ GPIO_PIN(24), ++ GPIO_PIN(25), ++ GPIO_PIN(26), ++ GPIO_PIN(27), ++ GPIO_PIN(28), ++ GPIO_PIN(29), ++ GPIO_PIN(30), ++ GPIO_PIN(31), ++ GPIO_PIN(32), ++ GPIO_PIN(33), ++ GPIO_PIN(34), ++ GPIO_PIN(35), ++ GPIO_PIN(36), ++ GPIO_PIN(37), ++ GPIO_PIN(38), ++ GPIO_PIN(39), ++ GPIO_PIN(40), ++ GPIO_PIN(41), ++ GPIO_PIN(42), ++ GPIO_PIN(43), ++ GPIO_PIN(44), ++ GPIO_PIN(45), ++ GPIO_PIN(46), ++ GPIO_PIN(47), ++ GPIO_PIN(48), ++ GPIO_PIN(49), ++ GPIO_PIN(50), ++ GPIO_PIN(51), ++ GPIO_PIN(52), ++ GPIO_PIN(53), ++ PINCTRL_PIN(54, "emmc_cmd"), ++ PINCTRL_PIN(55, "emmc_ds"), ++ PINCTRL_PIN(56, "emmc_clk"), ++ PINCTRL_PIN(57, "emmc_dat0"), ++ PINCTRL_PIN(58, "emmc_dat1"), ++ PINCTRL_PIN(59, "emmc_dat2"), ++ PINCTRL_PIN(60, "emmc_dat3"), ++ PINCTRL_PIN(61, "emmc_dat4"), ++ PINCTRL_PIN(62, "emmc_dat5"), ++ PINCTRL_PIN(63, "emmc_dat6"), ++ PINCTRL_PIN(64, "emmc_dat7"), ++}; ++ ++static struct pinctrl_pin_desc bcm2712_c0_aon_gpio_pins[] = { ++ AGPIO_PIN(0), ++ AGPIO_PIN(1), ++ AGPIO_PIN(2), ++ AGPIO_PIN(3), ++ AGPIO_PIN(4), ++ AGPIO_PIN(5), ++ AGPIO_PIN(6), ++ AGPIO_PIN(7), ++ AGPIO_PIN(8), ++ AGPIO_PIN(9), ++ AGPIO_PIN(10), ++ AGPIO_PIN(11), ++ AGPIO_PIN(12), ++ AGPIO_PIN(13), ++ AGPIO_PIN(14), ++ AGPIO_PIN(15), ++ AGPIO_PIN(16), ++ SGPIO_PIN(0), ++ SGPIO_PIN(1), ++ SGPIO_PIN(2), ++ SGPIO_PIN(3), ++ SGPIO_PIN(4), ++ SGPIO_PIN(5), ++}; ++ ++static const struct pin_regs bcm2712_d0_gpio_pin_regs[] = { ++ GPIO_REGS(1, 0, 0, 4, 5), ++ GPIO_REGS(2, 0, 1, 4, 6), ++ GPIO_REGS(3, 0, 2, 4, 7), ++ GPIO_REGS(4, 0, 3, 4, 8), ++ GPIO_REGS(10, 0, 4, 4, 9), ++ GPIO_REGS(11, 0, 5, 4, 10), ++ GPIO_REGS(12, 0, 6, 4, 11), ++ GPIO_REGS(13, 0, 7, 4, 12), ++ GPIO_REGS(14, 1, 0, 4, 13), ++ GPIO_REGS(15, 1, 1, 4, 14), ++ GPIO_REGS(18, 1, 2, 5, 0), ++ GPIO_REGS(19, 1, 3, 5, 1), ++ GPIO_REGS(20, 1, 4, 5, 2), ++ GPIO_REGS(21, 1, 5, 5, 3), ++ GPIO_REGS(22, 1, 6, 5, 4), ++ GPIO_REGS(23, 1, 7, 5, 5), ++ GPIO_REGS(24, 2, 0, 5, 6), ++ GPIO_REGS(25, 2, 1, 5, 7), ++ GPIO_REGS(26, 2, 2, 5, 8), ++ GPIO_REGS(27, 2, 3, 5, 9), ++ GPIO_REGS(28, 2, 4, 5, 10), ++ GPIO_REGS(29, 2, 5, 5, 11), ++ GPIO_REGS(30, 2, 6, 5, 12), ++ GPIO_REGS(31, 2, 7, 5, 13), ++ GPIO_REGS(32, 3, 0, 5, 14), ++ GPIO_REGS(33, 3, 1, 6, 0), ++ GPIO_REGS(34, 3, 2, 6, 1), ++ GPIO_REGS(35, 3, 3, 6, 2), ++}; ++ ++static struct pin_regs bcm2712_d0_aon_gpio_pin_regs[] = { ++ AGPIO_REGS(0, 3, 0, 5, 9), ++ AGPIO_REGS(1, 3, 1, 5, 10), ++ AGPIO_REGS(2, 3, 2, 5, 11), ++ AGPIO_REGS(3, 3, 3, 5, 12), ++ AGPIO_REGS(4, 3, 4, 5, 13), ++ AGPIO_REGS(5, 3, 5, 5, 14), ++ AGPIO_REGS(6, 3, 6, 6, 0), ++ AGPIO_REGS(8, 3, 7, 6, 1), ++ AGPIO_REGS(9, 4, 0, 6, 2), ++ AGPIO_REGS(12, 4, 1, 6, 3), ++ AGPIO_REGS(13, 4, 2, 6, 4), ++ AGPIO_REGS(14, 4, 3, 6, 5), ++ SGPIO_REGS(0, 0, 0), ++ SGPIO_REGS(1, 0, 1), ++ SGPIO_REGS(2, 0, 2), ++ SGPIO_REGS(3, 0, 3), ++ SGPIO_REGS(4, 1, 0), ++ SGPIO_REGS(5, 2, 0), ++}; ++ ++static const struct pinctrl_pin_desc bcm2712_d0_gpio_pins[] = { ++ GPIO_PIN(1), ++ GPIO_PIN(2), ++ GPIO_PIN(3), ++ GPIO_PIN(4), ++ GPIO_PIN(10), ++ GPIO_PIN(11), ++ GPIO_PIN(12), ++ GPIO_PIN(13), ++ GPIO_PIN(14), ++ GPIO_PIN(15), ++ GPIO_PIN(18), ++ GPIO_PIN(19), ++ GPIO_PIN(20), ++ GPIO_PIN(21), ++ GPIO_PIN(22), ++ GPIO_PIN(23), ++ GPIO_PIN(24), ++ GPIO_PIN(25), ++ GPIO_PIN(26), ++ GPIO_PIN(27), ++ GPIO_PIN(28), ++ GPIO_PIN(29), ++ GPIO_PIN(30), ++ GPIO_PIN(31), ++ GPIO_PIN(32), ++ GPIO_PIN(33), ++ GPIO_PIN(34), ++ GPIO_PIN(35), ++}; ++ ++static struct pinctrl_pin_desc bcm2712_d0_aon_gpio_pins[] = { ++ AGPIO_PIN(0), ++ AGPIO_PIN(1), ++ AGPIO_PIN(2), ++ AGPIO_PIN(3), ++ AGPIO_PIN(4), ++ AGPIO_PIN(5), ++ AGPIO_PIN(6), ++ AGPIO_PIN(8), ++ AGPIO_PIN(9), ++ AGPIO_PIN(12), ++ AGPIO_PIN(13), ++ AGPIO_PIN(14), ++ SGPIO_PIN(0), ++ SGPIO_PIN(1), ++ SGPIO_PIN(2), ++ SGPIO_PIN(3), ++ SGPIO_PIN(4), ++ SGPIO_PIN(5), ++}; ++ ++static const char * const bcm2712_func_names[] = { ++ FUNC(gpio), ++ FUNC(alt1), ++ FUNC(alt2), ++ FUNC(alt3), ++ FUNC(alt4), ++ FUNC(alt5), ++ FUNC(alt6), ++ FUNC(alt7), ++ FUNC(alt8), ++ FUNC(aon_cpu_standbyb), ++ FUNC(aon_fp_4sec_resetb), ++ FUNC(aon_gpclk), ++ FUNC(aon_pwm), ++ FUNC(arm_jtag), ++ FUNC(aud_fs_clk0), ++ FUNC(avs_pmu_bsc), ++ FUNC(bsc_m0), ++ FUNC(bsc_m1), ++ FUNC(bsc_m2), ++ FUNC(bsc_m3), ++ FUNC(clk_observe), ++ FUNC(ctl_hdmi_5v), ++ FUNC(enet0), ++ FUNC(enet0_mii), ++ FUNC(enet0_rgmii), ++ FUNC(ext_sc_clk), ++ FUNC(fl0), ++ FUNC(fl1), ++ FUNC(gpclk0), ++ FUNC(gpclk1), ++ FUNC(gpclk2), ++ FUNC(hdmi_tx0_auto_i2c), ++ FUNC(hdmi_tx0_bsc), ++ FUNC(hdmi_tx1_auto_i2c), ++ FUNC(hdmi_tx1_bsc), ++ FUNC(i2s_in), ++ FUNC(i2s_out), ++ FUNC(ir_in), ++ FUNC(mtsif), ++ FUNC(mtsif_alt), ++ FUNC(mtsif_alt1), ++ FUNC(pdm), ++ FUNC(pkt), ++ FUNC(pm_led_out), ++ FUNC(sc0), ++ FUNC(sd0), ++ FUNC(sd2), ++ FUNC(sd_card_a), ++ FUNC(sd_card_b), ++ FUNC(sd_card_c), ++ FUNC(sd_card_d), ++ FUNC(sd_card_e), ++ FUNC(sd_card_f), ++ FUNC(sd_card_g), ++ FUNC(spdif_out), ++ FUNC(spi_m), ++ FUNC(spi_s), ++ FUNC(sr_edm_sense), ++ FUNC(te0), ++ FUNC(te1), ++ FUNC(tsio), ++ FUNC(uart0), ++ FUNC(uart1), ++ FUNC(uart2), ++ FUNC(usb_pwr), ++ FUNC(usb_vbus), ++ FUNC(uui), ++ FUNC(vc_i2c0), ++ FUNC(vc_i2c3), ++ FUNC(vc_i2c4), ++ FUNC(vc_i2c5), ++ FUNC(vc_i2csl), ++ FUNC(vc_pcm), ++ FUNC(vc_pwm0), ++ FUNC(vc_pwm1), ++ FUNC(vc_spi0), ++ FUNC(vc_spi3), ++ FUNC(vc_spi4), ++ FUNC(vc_spi5), ++ FUNC(vc_uart0), ++ FUNC(vc_uart2), ++ FUNC(vc_uart3), ++ FUNC(vc_uart4), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_c0_aon_gpio_pin_funcs[] = { ++ PIN(0, ir_in, vc_spi0, vc_uart3, vc_i2c3, te0, vc_i2c0, _, _), ++ PIN(1, vc_pwm0, vc_spi0, vc_uart3, vc_i2c3, te1, aon_pwm, vc_i2c0, vc_pwm1), ++ PIN(2, vc_pwm0, vc_spi0, vc_uart3, ctl_hdmi_5v, fl0, aon_pwm, ir_in, vc_pwm1), ++ PIN(3, ir_in, vc_spi0, vc_uart3, aon_fp_4sec_resetb, fl1, sd_card_g, aon_gpclk, _), ++ PIN(4, gpclk0, vc_spi0, vc_i2csl, aon_gpclk, pm_led_out, aon_pwm, sd_card_g, vc_pwm0), ++ PIN(5, gpclk1, ir_in, vc_i2csl, clk_observe, aon_pwm, sd_card_g, vc_pwm0, _), ++ PIN(6, uart1, vc_uart4, gpclk2, ctl_hdmi_5v, vc_uart0, vc_spi3, _, _), ++ PIN(7, uart1, vc_uart4, gpclk0, aon_pwm, vc_uart0, vc_spi3, _, _), ++ PIN(8, uart1, vc_uart4, vc_i2csl, ctl_hdmi_5v, vc_uart0, vc_spi3, _, _), ++ PIN(9, uart1, vc_uart4, vc_i2csl, aon_pwm, vc_uart0, vc_spi3, _, _), ++ PIN(10, tsio, ctl_hdmi_5v, sc0, spdif_out, vc_spi5, usb_pwr, aon_gpclk, sd_card_f), ++ PIN(11, tsio, uart0, sc0, aud_fs_clk0, vc_spi5, usb_vbus, vc_uart2, sd_card_f), ++ PIN(12, tsio, uart0, vc_uart0, tsio, vc_spi5, usb_pwr, vc_uart2, sd_card_f), ++ PIN(13, bsc_m1, uart0, vc_uart0, uui, vc_spi5, arm_jtag, vc_uart2, vc_i2c3), ++ PIN(14, bsc_m1, uart0, vc_uart0, uui, vc_spi5, arm_jtag, vc_uart2, vc_i2c3), ++ PIN(15, ir_in, aon_fp_4sec_resetb, vc_uart0, pm_led_out, ctl_hdmi_5v, aon_pwm, aon_gpclk, _), ++ PIN(16, aon_cpu_standbyb, gpclk0, pm_led_out, ctl_hdmi_5v, vc_pwm0, usb_pwr, aud_fs_clk0, _), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_c0_aon_sgpio_pin_funcs[] = { ++ PIN(0, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _), ++ PIN(1, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _), ++ PIN(2, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c4, ctl_hdmi_5v, _, _, _), ++ PIN(3, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c4, _, _, _, _), ++ PIN(4, avs_pmu_bsc, bsc_m2, vc_i2c5, ctl_hdmi_5v, _, _, _, _), ++ PIN(5, avs_pmu_bsc, bsc_m2, vc_i2c5, _, _, _, _, _), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_c0_gpio_pin_funcs[] = { ++ PIN(0, bsc_m3, vc_i2c0, gpclk0, enet0, vc_pwm1, vc_spi0, ir_in, _), ++ PIN(1, bsc_m3, vc_i2c0, gpclk1, enet0, vc_pwm1, sr_edm_sense, vc_spi0, vc_uart3), ++ PIN(2, pdm, i2s_in, gpclk2, vc_spi4, pkt, vc_spi0, vc_uart3, _), ++ PIN(3, pdm, i2s_in, vc_spi4, pkt, vc_spi0, vc_uart3, _, _), ++ PIN(4, pdm, i2s_in, arm_jtag, vc_spi4, pkt, vc_spi0, vc_uart3, _), ++ PIN(5, pdm, vc_i2c3, arm_jtag, sd_card_e, vc_spi4, pkt, vc_pcm, vc_i2c5), ++ PIN(6, pdm, vc_i2c3, arm_jtag, sd_card_e, vc_spi4, pkt, vc_pcm, vc_i2c5), ++ PIN(7, i2s_out, spdif_out, arm_jtag, sd_card_e, vc_i2c3, enet0_rgmii, vc_pcm, vc_spi4), ++ PIN(8, i2s_out, aud_fs_clk0, arm_jtag, sd_card_e, vc_i2c3, enet0_mii, vc_pcm, vc_spi4), ++ PIN(9, i2s_out, aud_fs_clk0, arm_jtag, sd_card_e, enet0_mii, sd_card_c, vc_spi4, _), ++ PIN(10, bsc_m3, mtsif_alt1, i2s_in, i2s_out, vc_spi5, enet0_mii, sd_card_c, vc_spi4), ++ PIN(11, bsc_m3, mtsif_alt1, i2s_in, i2s_out, vc_spi5, enet0_mii, sd_card_c, vc_spi4), ++ PIN(12, spi_s, mtsif_alt1, i2s_in, i2s_out, vc_spi5, vc_i2csl, sd0, sd_card_d), ++ PIN(13, spi_s, mtsif_alt1, i2s_out, usb_vbus, vc_spi5, vc_i2csl, sd0, sd_card_d), ++ PIN(14, spi_s, vc_i2csl, enet0_rgmii, arm_jtag, vc_spi5, vc_pwm0, vc_i2c4, sd_card_d), ++ PIN(15, spi_s, vc_i2csl, vc_spi3, arm_jtag, vc_pwm0, vc_i2c4, gpclk0, _), ++ PIN(16, sd_card_b, i2s_out, vc_spi3, i2s_in, sd0, enet0_rgmii, gpclk1, _), ++ PIN(17, sd_card_b, i2s_out, vc_spi3, i2s_in, ext_sc_clk, sd0, enet0_rgmii, gpclk2), ++ PIN(18, sd_card_b, i2s_out, vc_spi3, i2s_in, sd0, enet0_rgmii, vc_pwm1, _), ++ PIN(19, sd_card_b, usb_pwr, vc_spi3, pkt, spdif_out, sd0, ir_in, vc_pwm1), ++ PIN(20, sd_card_b, uui, vc_uart0, arm_jtag, uart2, usb_pwr, vc_pcm, vc_uart4), ++ PIN(21, usb_pwr, uui, vc_uart0, arm_jtag, uart2, sd_card_b, vc_pcm, vc_uart4), ++ PIN(22, usb_pwr, enet0, vc_uart0, mtsif, uart2, usb_vbus, vc_pcm, vc_i2c5), ++ PIN(23, usb_vbus, enet0, vc_uart0, mtsif, uart2, i2s_out, vc_pcm, vc_i2c5), ++ PIN(24, mtsif, pkt, uart0, enet0_rgmii, enet0_rgmii, vc_i2c4, vc_uart3, _), ++ PIN(25, mtsif, pkt, sc0, uart0, enet0_rgmii, enet0_rgmii, vc_i2c4, vc_uart3), ++ PIN(26, mtsif, pkt, sc0, uart0, enet0_rgmii, vc_uart4, vc_spi5, _), ++ PIN(27, mtsif, pkt, sc0, uart0, enet0_rgmii, vc_uart4, vc_spi5, _), ++ PIN(28, mtsif, pkt, sc0, enet0_rgmii, vc_uart4, vc_spi5, _, _), ++ PIN(29, mtsif, pkt, sc0, enet0_rgmii, vc_uart4, vc_spi5, _, _), ++ PIN(30, mtsif, pkt, sc0, sd2, enet0_rgmii, gpclk0, vc_pwm0, _), ++ PIN(31, mtsif, pkt, sc0, sd2, enet0_rgmii, vc_spi3, vc_pwm0, _), ++ PIN(32, mtsif, pkt, sc0, sd2, enet0_rgmii, vc_spi3, vc_uart3, _), ++ PIN(33, mtsif, pkt, sd2, enet0_rgmii, vc_spi3, vc_uart3, _, _), ++ PIN(34, mtsif, pkt, ext_sc_clk, sd2, enet0_rgmii, vc_spi3, vc_i2c5, _), ++ PIN(35, mtsif, pkt, sd2, enet0_rgmii, vc_spi3, vc_i2c5, _, _), ++ PIN(36, sd0, mtsif, sc0, i2s_in, vc_uart3, vc_uart2, _, _), ++ PIN(37, sd0, mtsif, sc0, vc_spi0, i2s_in, vc_uart3, vc_uart2, _), ++ PIN(38, sd0, mtsif_alt, sc0, vc_spi0, i2s_in, vc_uart3, vc_uart2, _), ++ PIN(39, sd0, mtsif_alt, sc0, vc_spi0, vc_uart3, vc_uart2, _, _), ++ PIN(40, sd0, mtsif_alt, sc0, vc_spi0, bsc_m3, _, _, _), ++ PIN(41, sd0, mtsif_alt, sc0, vc_spi0, bsc_m3, _, _, _), ++ PIN(42, vc_spi0, mtsif_alt, vc_i2c0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m), ++ PIN(43, vc_spi0, mtsif_alt, vc_i2c0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m), ++ PIN(44, vc_spi0, mtsif_alt, enet0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m), ++ PIN(45, vc_spi0, mtsif_alt, enet0, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m), ++ PIN(46, vc_spi0, mtsif_alt, sd_card_a, mtsif_alt1, arm_jtag, pdm, spi_m, _), ++ PIN(47, enet0, mtsif_alt, i2s_out, mtsif_alt1, arm_jtag, _, _, _), ++ PIN(48, sc0, usb_pwr, spdif_out, mtsif, _, _, _, _), ++ PIN(49, sc0, usb_pwr, aud_fs_clk0, mtsif, _, _, _, _), ++ PIN(50, sc0, usb_vbus, sc0, _, _, _, _, _), ++ PIN(51, sc0, enet0, sc0, sr_edm_sense, _, _, _, _), ++ PIN(52, sc0, enet0, vc_pwm1, _, _, _, _, _), ++ PIN(53, sc0, enet0_rgmii, ext_sc_clk, _, _, _, _, _), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_d0_aon_gpio_pin_funcs[] = { ++ PIN(0, ir_in, vc_spi0, vc_uart0, vc_i2c3, uart0, vc_i2c0, _, _), ++ PIN(1, vc_pwm0, vc_spi0, vc_uart0, vc_i2c3, uart0, aon_pwm, vc_i2c0, vc_pwm1), ++ PIN(2, vc_pwm0, vc_spi0, vc_uart0, ctl_hdmi_5v, uart0, aon_pwm, ir_in, vc_pwm1), ++ PIN(3, ir_in, vc_spi0, vc_uart0, uart0, sd_card_g, aon_gpclk, _, _), ++ PIN(4, gpclk0, vc_spi0, pm_led_out, aon_pwm, sd_card_g, vc_pwm0, _, _), ++ PIN(5, gpclk1, ir_in, aon_pwm, sd_card_g, vc_pwm0, _, _, _), ++ PIN(6, uart1, vc_uart2, ctl_hdmi_5v, gpclk2, vc_spi3, _, _, _), ++ PIN(7, _, _, _, _, _, _, _, _), ++ PIN(8, uart1, vc_uart2, ctl_hdmi_5v, vc_spi0, vc_spi3, _, _, _), ++ PIN(9, uart1, vc_uart2, vc_uart0, aon_pwm, vc_spi0, vc_uart2, vc_spi3, _), ++ PIN(10, _, _, _, _, _, _, _, _), ++ PIN(11, _, _, _, _, _, _, _, _), ++ PIN(12, uart1, vc_uart2, vc_uart0, vc_spi0, usb_pwr, vc_uart2, vc_spi3, _), ++ PIN(13, bsc_m1, vc_uart0, uui, vc_spi0, arm_jtag, vc_uart2, vc_i2c3, _), ++ PIN(14, bsc_m1, aon_gpclk, vc_uart0, uui, vc_spi0, arm_jtag, vc_uart2, vc_i2c3), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_d0_aon_sgpio_pin_funcs[] = { ++ PIN(0, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _), ++ PIN(1, hdmi_tx0_bsc, hdmi_tx0_auto_i2c, bsc_m0, vc_i2c0, _, _, _, _), ++ PIN(2, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c0, ctl_hdmi_5v, _, _, _), ++ PIN(3, hdmi_tx1_bsc, hdmi_tx1_auto_i2c, bsc_m1, vc_i2c0, _, _, _, _), ++ PIN(4, avs_pmu_bsc, bsc_m2, vc_i2c3, ctl_hdmi_5v, _, _, _, _), ++ PIN(5, avs_pmu_bsc, bsc_m2, vc_i2c3, _, _, _, _, _), ++}; ++ ++static const struct bcm2712_pin_funcs bcm2712_d0_gpio_pin_funcs[] = { ++ PIN(1, vc_i2c0, usb_pwr, gpclk0, sd_card_e, vc_spi3, sr_edm_sense, vc_spi0, vc_uart0), ++ PIN(2, vc_i2c0, usb_pwr, gpclk1, sd_card_e, vc_spi3, clk_observe, vc_spi0, vc_uart0), ++ PIN(3, vc_i2c3, usb_vbus, gpclk2, sd_card_e, vc_spi3, vc_spi0, vc_uart0, _), ++ PIN(4, vc_i2c3, vc_pwm1, vc_spi3, sd_card_e, vc_spi3, vc_spi0, vc_uart0, _), ++ PIN(10, bsc_m3, vc_pwm1, vc_spi3, sd_card_e, vc_spi3, gpclk0, _, _), ++ PIN(11, bsc_m3, vc_spi3, clk_observe, sd_card_c, gpclk1, _, _, _), ++ PIN(12, spi_s, vc_spi3, sd_card_c, sd_card_d, _, _, _, _), ++ PIN(13, spi_s, vc_spi3, sd_card_c, sd_card_d, _, _, _, _), ++ PIN(14, spi_s, uui, arm_jtag, vc_pwm0, vc_i2c0, sd_card_d, _, _), ++ PIN(15, spi_s, uui, arm_jtag, vc_pwm0, vc_i2c0, gpclk0, _, _), ++ PIN(18, sd_card_f, vc_pwm1, _, _, _, _, _, _), ++ PIN(19, sd_card_f, usb_pwr, vc_pwm1, _, _, _, _, _), ++ PIN(20, vc_i2c3, uui, vc_uart0, arm_jtag, vc_uart2, _, _, _), ++ PIN(21, vc_i2c3, uui, vc_uart0, arm_jtag, vc_uart2, _, _, _), ++ PIN(22, sd_card_f, vc_uart0, vc_i2c3, _, _, _, _, _), ++ PIN(23, vc_uart0, vc_i2c3, _, _, _, _, _, _), ++ PIN(24, sd_card_b, vc_spi0, arm_jtag, uart0, usb_pwr, vc_uart2, vc_uart0, _), ++ PIN(25, sd_card_b, vc_spi0, arm_jtag, uart0, usb_pwr, vc_uart2, vc_uart0, _), ++ PIN(26, sd_card_b, vc_spi0, arm_jtag, uart0, usb_vbus, vc_uart2, vc_spi0, _), ++ PIN(27, sd_card_b, vc_spi0, arm_jtag, uart0, vc_uart2, vc_spi0, _, _), ++ PIN(28, sd_card_b, vc_spi0, arm_jtag, vc_i2c0, vc_spi0, _, _, _), ++ PIN(29, arm_jtag, vc_i2c0, vc_spi0, _, _, _, _, _), ++ PIN(30, sd2, gpclk0, vc_pwm0, _, _, _, _, _), ++ PIN(31, sd2, vc_spi3, vc_pwm0, _, _, _, _, _), ++ PIN(32, sd2, vc_spi3, vc_uart3, _, _, _, _, _), ++ PIN(33, sd2, vc_spi3, vc_uart3, _, _, _, _, _), ++ PIN(34, sd2, vc_spi3, vc_i2c5, _, _, _, _, _), ++ PIN(35, sd2, vc_spi3, vc_i2c5, _, _, _, _, _), ++}; ++ ++static inline u32 bcm2712_reg_rd(struct bcm2712_pinctrl *pc, unsigned reg) ++{ ++ return readl(pc->base + reg); ++} ++ ++static inline void bcm2712_reg_wr(struct bcm2712_pinctrl *pc, unsigned reg, ++ u32 val) ++{ ++ writel(val, pc->base + reg); ++} ++ ++static enum bcm2712_funcs bcm2712_pinctrl_fsel_get( ++ struct bcm2712_pinctrl *pc, unsigned pin) ++{ ++ u32 bit = pc->pin_regs[pin].mux_bit; ++ enum bcm2712_funcs func; ++ int fsel; ++ u32 val; ++ ++ if (!bit) ++ return func_gpio; ++ ++ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit)); ++ fsel = (val >> BIT_TO_SHIFT(bit)) & BCM2712_FSEL_MASK; ++ func = pc->pin_funcs[pin].funcs[fsel]; ++ if (func >= func_count) ++ func = (enum bcm2712_funcs)fsel; ++ ++ dev_dbg(pc->dev, "get %04x: %08x (%u => %s)\n", ++ BIT_TO_REG(bit), val, pin, ++ bcm2712_func_names[func]); ++ ++ return func; ++} ++ ++static void bcm2712_pinctrl_fsel_set( ++ struct bcm2712_pinctrl *pc, unsigned pin, ++ enum bcm2712_funcs func) ++{ ++ u32 bit = pc->pin_regs[pin].mux_bit, val; ++ const u8 *pin_funcs; ++ unsigned long flags; ++ int fsel; ++ int cur; ++ int i; ++ ++ if (!bit || func >= func_count) ++ return; ++ ++ fsel = BCM2712_FSEL_COUNT; ++ ++ if (func >= BCM2712_FSEL_COUNT) { ++ /* Convert to an fsel number */ ++ pin_funcs = pc->pin_funcs[pin].funcs; ++ for (i = 1; i < BCM2712_FSEL_COUNT; i++) { ++ if (pin_funcs[i - 1] == func) { ++ fsel = i; ++ break; ++ } ++ } ++ } else { ++ fsel = (enum bcm2712_funcs)func; ++ } ++ if (fsel >= BCM2712_FSEL_COUNT) ++ return; ++ ++ spin_lock_irqsave(&pc->lock, flags); ++ ++ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit)); ++ cur = (val >> BIT_TO_SHIFT(bit)) & BCM2712_FSEL_MASK; ++ ++ dev_dbg(pc->dev, "read %04x: %08x (%u => %s)\n", ++ BIT_TO_REG(bit), val, pin, ++ bcm2712_func_names[cur]); ++ ++ if (cur != fsel) { ++ val &= ~(BCM2712_FSEL_MASK << BIT_TO_SHIFT(bit)); ++ val |= fsel << BIT_TO_SHIFT(bit); ++ ++ dev_dbg(pc->dev, "write %04x: %08x (%u <= %s)\n", ++ BIT_TO_REG(bit), val, pin, ++ bcm2712_func_names[fsel]); ++ bcm2712_reg_wr(pc, BIT_TO_REG(bit), val); ++ } ++ ++ spin_unlock_irqrestore(&pc->lock, flags); ++} ++ ++static int bcm2712_pctl_get_groups_count(struct pinctrl_dev *pctldev) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ return pc->pctl_desc.npins; ++} ++ ++static const char *bcm2712_pctl_get_group_name(struct pinctrl_dev *pctldev, ++ unsigned selector) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ return pc->gpio_groups[selector]; ++} ++ ++static int bcm2712_pctl_get_group_pins(struct pinctrl_dev *pctldev, ++ unsigned selector, ++ const unsigned **pins, ++ unsigned *num_pins) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ *pins = &pc->pctl_desc.pins[selector].number; ++ *num_pins = 1; ++ ++ return 0; ++} ++ ++static void bcm2712_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, ++ struct seq_file *s, ++ unsigned offset) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ enum bcm2712_funcs fsel = bcm2712_pinctrl_fsel_get(pc, offset); ++ const char *fname = bcm2712_func_names[fsel]; ++ ++ seq_printf(s, "function %s", fname); ++} ++ ++static void bcm2712_pctl_dt_free_map(struct pinctrl_dev *pctldev, ++ struct pinctrl_map *maps, unsigned num_maps) ++{ ++ int i; ++ ++ for (i = 0; i < num_maps; i++) ++ if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN) ++ kfree(maps[i].data.configs.configs); ++ ++ kfree(maps); ++} ++ ++static const struct pinctrl_ops bcm2712_pctl_ops = { ++ .get_groups_count = bcm2712_pctl_get_groups_count, ++ .get_group_name = bcm2712_pctl_get_group_name, ++ .get_group_pins = bcm2712_pctl_get_group_pins, ++ .pin_dbg_show = bcm2712_pctl_pin_dbg_show, ++ .dt_node_to_map = pinconf_generic_dt_node_to_map_all, ++ .dt_free_map = bcm2712_pctl_dt_free_map, ++}; ++ ++static int bcm2712_pmx_free(struct pinctrl_dev *pctldev, ++ unsigned offset) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ /* disable by setting to GPIO */ ++ bcm2712_pinctrl_fsel_set(pc, offset, func_gpio); ++ return 0; ++} ++ ++static int bcm2712_pmx_get_functions_count(struct pinctrl_dev *pctldev) ++{ ++ return func_count; ++} ++ ++static const char *bcm2712_pmx_get_function_name(struct pinctrl_dev *pctldev, ++ unsigned selector) ++{ ++ return (selector < func_count) ? bcm2712_func_names[selector] : NULL; ++} ++ ++static int bcm2712_pmx_get_function_groups(struct pinctrl_dev *pctldev, ++ unsigned selector, ++ const char * const **groups, ++ unsigned * const num_groups) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ /* every pin can do every function */ ++ *groups = pc->gpio_groups; ++ *num_groups = pc->pctl_desc.npins; ++ ++ return 0; ++} ++ ++static int bcm2712_pmx_set(struct pinctrl_dev *pctldev, ++ unsigned func_selector, ++ unsigned group_selector) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ bcm2712_pinctrl_fsel_set(pc, group_selector, func_selector); ++ ++ return 0; ++} ++static int bcm2712_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned pin) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ bcm2712_pinctrl_fsel_set(pc, pin, func_gpio); ++ ++ return 0; ++} ++ ++static void bcm2712_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned offset) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ /* disable by setting to GPIO */ ++ bcm2712_pinctrl_fsel_set(pc, offset, func_gpio); ++} ++ ++static const struct pinmux_ops bcm2712_pmx_ops = { ++ .free = bcm2712_pmx_free, ++ .get_functions_count = bcm2712_pmx_get_functions_count, ++ .get_function_name = bcm2712_pmx_get_function_name, ++ .get_function_groups = bcm2712_pmx_get_function_groups, ++ .set_mux = bcm2712_pmx_set, ++ .gpio_request_enable = bcm2712_pmx_gpio_request_enable, ++ .gpio_disable_free = bcm2712_pmx_gpio_disable_free, ++}; ++ ++static unsigned int bcm2712_pull_config_get(struct bcm2712_pinctrl *pc, ++ unsigned int pin) ++{ ++ u32 bit = pc->pin_regs[pin].pad_bit, val; ++ ++ if (unlikely(bit == REG_BIT_INVALID)) ++ return BCM2712_PULL_NONE; ++ ++ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit)); ++ return (val >> BIT_TO_SHIFT(bit)) & BCM2712_PULL_MASK; ++} ++ ++static void bcm2712_pull_config_set(struct bcm2712_pinctrl *pc, ++ unsigned int pin, unsigned int arg) ++{ ++ u32 bit = pc->pin_regs[pin].pad_bit, val; ++ unsigned long flags; ++ ++ if (unlikely(bit == REG_BIT_INVALID)) { ++ dev_warn(pc->dev, "can't set pulls for %s\n", pc->gpio_groups[pin]); ++ return; ++ } ++ ++ spin_lock_irqsave(&pc->lock, flags); ++ ++ val = bcm2712_reg_rd(pc, BIT_TO_REG(bit)); ++ val &= ~(BCM2712_PULL_MASK << BIT_TO_SHIFT(bit)); ++ val |= (arg << BIT_TO_SHIFT(bit)); ++ bcm2712_reg_wr(pc, BIT_TO_REG(bit), val); ++ ++ spin_unlock_irqrestore(&pc->lock, flags); ++} ++ ++static int bcm2712_pinconf_get(struct pinctrl_dev *pctldev, ++ unsigned pin, unsigned long *config) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ enum pin_config_param param = pinconf_to_config_param(*config); ++ u32 arg; ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_NONE); ++ break; ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_DOWN); ++ break; ++ case PIN_CONFIG_BIAS_PULL_UP: ++ arg = (bcm2712_pull_config_get(pc, pin) == BCM2712_PULL_UP); ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ ++ *config = pinconf_to_config_packed(param, arg); ++ ++ return -ENOTSUPP; ++} ++ ++static int bcm2712_pinconf_set(struct pinctrl_dev *pctldev, ++ unsigned int pin, unsigned long *configs, ++ unsigned int num_configs) ++{ ++ struct bcm2712_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ u32 param, arg; ++ int i; ++ ++ for (i = 0; i < num_configs; i++) { ++ param = pinconf_to_config_param(configs[i]); ++ arg = pinconf_to_config_argument(configs[i]); ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_NONE); ++ break; ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_DOWN); ++ break; ++ case PIN_CONFIG_BIAS_PULL_UP: ++ bcm2712_pull_config_set(pc, pin, BCM2712_PULL_UP); ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ } /* for each config */ ++ ++ return 0; ++} ++ ++static const struct pinconf_ops bcm2712_pinconf_ops = { ++ .is_generic = true, ++ .pin_config_get = bcm2712_pinconf_get, ++ .pin_config_set = bcm2712_pinconf_set, ++}; ++ ++static const struct pinctrl_desc bcm2712_c0_pinctrl_desc = { ++ .name = "pinctrl-bcm2712", ++ .pins = bcm2712_c0_gpio_pins, ++ .npins = ARRAY_SIZE(bcm2712_c0_gpio_pins), ++ .pctlops = &bcm2712_pctl_ops, ++ .pmxops = &bcm2712_pmx_ops, ++ .confops = &bcm2712_pinconf_ops, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct pinctrl_desc bcm2712_c0_aon_pinctrl_desc = { ++ .name = "aon-pinctrl-bcm2712", ++ .pins = bcm2712_c0_aon_gpio_pins, ++ .npins = ARRAY_SIZE(bcm2712_c0_aon_gpio_pins), ++ .pctlops = &bcm2712_pctl_ops, ++ .pmxops = &bcm2712_pmx_ops, ++ .confops = &bcm2712_pinconf_ops, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct pinctrl_desc bcm2712_d0_pinctrl_desc = { ++ .name = "pinctrl-bcm2712", ++ .pins = bcm2712_d0_gpio_pins, ++ .npins = ARRAY_SIZE(bcm2712_d0_gpio_pins), ++ .pctlops = &bcm2712_pctl_ops, ++ .pmxops = &bcm2712_pmx_ops, ++ .confops = &bcm2712_pinconf_ops, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct pinctrl_desc bcm2712_d0_aon_pinctrl_desc = { ++ .name = "aon-pinctrl-bcm2712", ++ .pins = bcm2712_d0_aon_gpio_pins, ++ .npins = ARRAY_SIZE(bcm2712_d0_aon_gpio_pins), ++ .pctlops = &bcm2712_pctl_ops, ++ .pmxops = &bcm2712_pmx_ops, ++ .confops = &bcm2712_pinconf_ops, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct pinctrl_gpio_range bcm2712_c0_pinctrl_gpio_range = { ++ .name = "pinctrl-bcm2712", ++ .npins = ARRAY_SIZE(bcm2712_c0_gpio_pins), ++}; ++ ++static const struct pinctrl_gpio_range bcm2712_c0_aon_pinctrl_gpio_range = { ++ .name = "aon-pinctrl-bcm2712", ++ .npins = ARRAY_SIZE(bcm2712_c0_aon_gpio_pins), ++}; ++ ++static const struct pinctrl_gpio_range bcm2712_d0_pinctrl_gpio_range = { ++ .name = "pinctrl-bcm2712", ++ .npins = ARRAY_SIZE(bcm2712_d0_gpio_pins), ++}; ++ ++static const struct pinctrl_gpio_range bcm2712_d0_aon_pinctrl_gpio_range = { ++ .name = "aon-pinctrl-bcm2712", ++ .npins = ARRAY_SIZE(bcm2712_d0_aon_gpio_pins), ++}; ++ ++static const struct bcm_plat_data bcm2712_c0_plat_data = { ++ .pctl_desc = &bcm2712_c0_pinctrl_desc, ++ .gpio_range = &bcm2712_c0_pinctrl_gpio_range, ++ .pin_regs = bcm2712_c0_gpio_pin_regs, ++ .pin_funcs = bcm2712_c0_gpio_pin_funcs, ++}; ++ ++static const struct bcm_plat_data bcm2712_c0_aon_plat_data = { ++ .pctl_desc = &bcm2712_c0_aon_pinctrl_desc, ++ .gpio_range = &bcm2712_c0_aon_pinctrl_gpio_range, ++ .pin_regs = bcm2712_c0_aon_gpio_pin_regs, ++ .pin_funcs = bcm2712_c0_aon_gpio_pin_funcs, ++}; ++ ++static const struct bcm_plat_data bcm2712_d0_plat_data = { ++ .pctl_desc = &bcm2712_d0_pinctrl_desc, ++ .gpio_range = &bcm2712_d0_pinctrl_gpio_range, ++ .pin_regs = bcm2712_d0_gpio_pin_regs, ++ .pin_funcs = bcm2712_d0_gpio_pin_funcs, ++}; ++ ++static const struct bcm_plat_data bcm2712_d0_aon_plat_data = { ++ .pctl_desc = &bcm2712_d0_aon_pinctrl_desc, ++ .gpio_range = &bcm2712_d0_aon_pinctrl_gpio_range, ++ .pin_regs = bcm2712_d0_aon_gpio_pin_regs, ++ .pin_funcs = bcm2712_d0_aon_gpio_pin_funcs, ++}; ++ ++static const struct of_device_id bcm2712_pinctrl_match[] = { ++ { ++ .compatible = "brcm,bcm2712-pinctrl", ++ .data = &bcm2712_c0_plat_data, ++ }, ++ { ++ .compatible = "brcm,bcm2712-aon-pinctrl", ++ .data = &bcm2712_c0_aon_plat_data, ++ }, ++ ++ { ++ .compatible = "brcm,bcm2712c0-pinctrl", ++ .data = &bcm2712_c0_plat_data, ++ }, ++ { ++ .compatible = "brcm,bcm2712c0-aon-pinctrl", ++ .data = &bcm2712_c0_aon_plat_data, ++ }, ++ ++ { ++ .compatible = "brcm,bcm2712d0-pinctrl", ++ .data = &bcm2712_d0_plat_data, ++ }, ++ { ++ .compatible = "brcm,bcm2712d0-aon-pinctrl", ++ .data = &bcm2712_d0_aon_plat_data, ++ }, ++ {} ++}; ++ ++static int bcm2712_pinctrl_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ const struct bcm_plat_data *pdata; ++ const struct of_device_id *match; ++ struct bcm2712_pinctrl *pc; ++ const char **names; ++ int num_pins, i; ++ ++ match = of_match_node(bcm2712_pinctrl_match, np); ++ if (!match) ++ return -EINVAL; ++ pdata = match->data; ++ ++ pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); ++ if (!pc) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, pc); ++ pc->dev = dev; ++ spin_lock_init(&pc->lock); ++ ++ pc->base = devm_of_iomap(dev, np, 0, NULL); ++ if (IS_ERR(pc->base)) { ++ dev_err(dev, "could not get IO memory\n"); ++ return PTR_ERR(pc->base); ++ } ++ ++ pc->pctl_desc = *pdata->pctl_desc; ++ num_pins = pc->pctl_desc.npins; ++ names = devm_kmalloc_array(dev, num_pins, sizeof(const char *), ++ GFP_KERNEL); ++ if (!names) ++ return -ENOMEM; ++ for (i = 0; i < num_pins; i++) ++ names[i] = pc->pctl_desc.pins[i].name; ++ pc->gpio_groups = names; ++ pc->pin_regs = pdata->pin_regs; ++ pc->pin_funcs = pdata->pin_funcs; ++ pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); ++ if (IS_ERR(pc->pctl_dev)) ++ return PTR_ERR(pc->pctl_dev); ++ ++ pc->gpio_range = *pdata->gpio_range; ++ pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); ++ ++ return 0; ++} ++ ++static struct platform_driver bcm2712_pinctrl_driver = { ++ .probe = bcm2712_pinctrl_probe, ++ .driver = { ++ .name = MODULE_NAME, ++ .of_match_table = bcm2712_pinctrl_match, ++ .suppress_bind_attrs = true, ++ }, ++}; ++builtin_platform_driver(bcm2712_pinctrl_driver); diff --git a/target/linux/bcm27xx/patches-6.1/950-0859-mmc-brcmstb-add-support-for-BCM2712.patch b/target/linux/bcm27xx/patches-6.1/950-0859-mmc-brcmstb-add-support-for-BCM2712.patch new file mode 100644 index 0000000000..05d403a63e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0859-mmc-brcmstb-add-support-for-BCM2712.patch @@ -0,0 +1,498 @@ +From b627647c4500d39cb026924b608841fdf4d4d7e9 Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +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 + +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 +--- + 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 + #include + #include ++#include ++#include + + #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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0860-sdhci-Add-SD-Express-hook.patch b/target/linux/bcm27xx/patches-6.1/950-0860-sdhci-Add-SD-Express-hook.patch new file mode 100644 index 0000000000..1aea0b3bcd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0860-sdhci-Add-SD-Express-hook.patch @@ -0,0 +1,90 @@ +From 9564939f1a92e5f9807461539de28c50e5bee440 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0861-Add-new-pispbe-driver-though-not-yet-the-Makesfiles-.patch b/target/linux/bcm27xx/patches-6.1/950-0861-Add-new-pispbe-driver-though-not-yet-the-Makesfiles-.patch new file mode 100644 index 0000000000..2ac7b7830c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0861-Add-new-pispbe-driver-though-not-yet-the-Makesfiles-.patch @@ -0,0 +1,3788 @@ +From ce14be51d71bf39893786d380cbb82e81d2a10d5 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 14 Jul 2021 09:32:49 +0100 +Subject: [PATCH] Add new "pispbe" driver (though not yet the Makesfiles or DT + required to use it) + +media: bcm2712: Initial commit of the PiSP BE driver + +Signed-off-by: Naushir Patuck + +media: bcm2712_pisp_be: PiSP driver updates. + +- Start registering video nodes from /dev/video20 +- Formatting fixes +- Define MODULE_DEVICE_TABLE() to probe correctly + +Signed-off-by: Naushir Patuck + +media: pisp_be: Improve image format support + +Add a new format table that lists the V4L2 format enums and their properties. +Keep the exising 'RPBP' format to support the userland verification tools. +This format requires userland to fill all plane properties. Standard V4L2 +formats will derive these properties from the format table. + +Signed-off-by: Naushir Patuck + +media: pisp_be: Advertise the meta output format explictily. + +Signed-off-by: Naushir Patuck + +drivers: pisp_be: Various updates and cleanups + +- Switch to a single node group for now. +- Add a node description table to simplify node handling. +- Switch HoG output to V4L2_CAP_META_CAPTURE type. +- Use string descriptions for node names in logging messages. + +Signed-off-by: Naushir Patuck + +pisp_be: Updates for libcamera usage: + +- Remove indexes from device entity names +- Add enumframesize and enumfmts ioctls +- Add default format to all nodes. + +Signed-off-by: Naushir Patuck + +v4l2: pisp_be: Move format definitions into v4l2 core + +Signed-off-by: Naushir Patuck + +media: raspberrypi: Move PiSP common headers to a single location + +Signed-off-by: Naushir Patuck + +media: raspberrypi: Remove old pispbe driver. + +This is now supersede by the driver in drivers/media/platform/raspberrypi/ + +Signed-off-by: Naushir Patuck + +PISP-BE Driver: Automate buffer-cycling for TDN and Stitch state. +Remove "tdn-input" and "stitch-input" nodes altogether (the output +nodes must still be opened and REQBUFS called with 1 or 2 buffers). +Also, a bit of tidying of buffer address handling and locking. + +PISP-BE driver: Turn debug level right down to reduce overly-chatty messages + +media: bcm2712: Depend on CONFIG_PM + +Depend on CONFIG_PM as the driver uses the runtime_pm infrastructure. + +Signed-off-by: Jacopo Mondi + +drivers: media: pisp_be: Move BE driver to a raspberrypi directory + +Move the pisp_be driver from drivers/media/platform/raspberrypi/ to +drivers/media/platform/raspberrypi/pisp_be/. This seems the accepted +convention in the drivers/media/platform/ directory structure. + +Also rename the driver module from bcm2712_pisp_be to pisp_be. + +Signed-off-by: Naushir Patuck + +pisp_be: Updates for libcamera streaming: + +- Add some required v4l2 formats +- Add buf_prepare ioctl +- Set plane offsets correctly before reprogramming + +pisp_be: Reduce logging verbosity + +Signed-off-by: Naushir Patuck + +pisp_be: Add buffer timestamps + +While at it, remove duplicate code when checking if the HW has completed +multiple jobs. + +Signed-off-by: Naushir Patuck + +pisp_be: Remove queue size allocation constraint + +PISP-BE driver: Fix ISR to handle multiple done/start events. + +PISP-BE: Fix variable-name shadowing bugette + +PISP-BE: Support for two node groups. Reorganize the driver. + +To support 2 concurrent libcamera applications, we need 2 node groups, +need to allow multiple opens of each node (because libcamera does this) +and create a separate media device per group (to support file-locking). + +This triggered significant rearrangement of the driver. Some calls +that we formerly intercepted have been delegated back to v4l2/vb2. +Logging changes arising from multiple v4l2_dev. Refactored probe() +and initialization. Avoid dynamically-allocated entity name strings. + +drivers: media: pisp_be: Add vidioc_enum_fmt_meta_out + +This was missing in the struct v4l2_ioctl_ops definition. + +Signed-off-by: Naushir Patuck + +drivers: media: pispe_be: Add Bayer compressed formats + +Add PiSP Bayer compressed formats to the list of supported pixel formats +for the PiSP backend driver. + +Signed-off-by: Naushir Patuck + +drivers: meida: pisp_be: Fix overflow in plane size calculations + +The calculations for buffer plane sizes can overflow because of the +plane factor shift. Fix this by using u64 integers for the calculations. + +Signed-off-by: Naushir Patuck + +drivers: media: pisp_be: Use 0P3 for plane factors + +Use less precision for the plane factors to avoid any nasty overflows. + +Signed-off-by: Naushir Patuck + +media: pisp: Checkpatch and coding style fixups + +Signed-off-by: Dave Stevenson + +media: pisp_be: More coding style fixups + +media: platform: bcm2712: pisp_be: Fix crash when buffer format not set + +Signed-off-by: Nick Hollinghurst + +media: platform: bcm2712: pisp_be: Allow non-SRGB colour spaces on RGB outputs + +Allow colour spaces other than SRGB when the output format in question +is an RGB output. This commit merely ports over existing changes from +the vc4 ISP driver. + +Signed-off-by: David Plowman + +media: platform: bcm2712: Tweak list of BE supported image formats + +Remove RGB565 and 10- and 12-bit packed raw formats, which ISP-BE +can't support for input or output. Add NV12M and NV21M which it can. +(I didn't bother adding YUV422P, which apparently is not widely used.) + +Signed-off-by: Nick Hollinghurst + +pisp_be: Fill the hardware revision in the media entity struct + +This can be used by userland to determine the hardware capabilities. + +Signed-off-by: Naushir Patuck + +bcm2712: Use BIT() macro + +Use the BIT() macro instead of plain bit shifting. + +Signed-off-by: Jacopo Mondi + +bcm2712: Invert condition in pispbe_schedule_internal() + +Return earlier and save one indentation level + +Signed-off-by: Jacopo Mondi + +bcm2712: Invert condition in for loop + +Save one indentation level by continuing if the node is not streaming. + +Signed-off-by: Jacopo Mondi + +bcm2712: Do not declare a local variable + +There already is a truct pispbe_node *node in the function scope. + +Signed-off-by: Jacopo Mondi + +bcm21712: Siplify pispbe_schedule_one() + +A little more verbose but easier to follow ? + +Signed-off-by: Jacopo Mondi + +bcm2712: Rename pispbe_schedule_all() to pispbe_schedule_any() + +The pispbe_schedule_all() function name is misleading, as the function +schedule a single job from any of the node groups. Rename it. + +Signed-off-by: Jacopo Mondi + +media: platform: bcm2712: Remove buffer auto-cycling from ISP-BE + +Previously, the ISP-BE driver tried to automate "ping pong" buffers +for TDN and HDR state, but did not fully conceal them from users. + +The automation has been removed: there are now separate output and +capture queues for each of TDN and Stitch, which must be managed by +user code (DMABUFs may be used to circulate buffers between queues). + +Signed-off-by: Nick Hollinghurst + +drivers: media: pisp_be: Cache BE config buffer vaddr + +When programming a new job, we access at the config buffer, possibly +from ISR context. So fetch and the virtual address when queuing the +buffer. + +Signed-off-by: Naushir Patuck + +drivers: media: pisp_be: Remove all traces of ctrls and request API + +These APIs are not (and will not) be used by the driver, so remove them. + +Signed-off-by: Naushir Patuck + +media: bcm2712: Replace v4l2_dbg with dev_dbg + +Replace the v4l2 debug helpers with the device debug once, which are +preferred. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Remove of_match_ptr() + +The of_match_ptr() usage could cause a compiler warning if +CONFIG_OF is not enabled, as the pispbe_of_match variable would +result unused. + +As the of_match_table field of struct platform_driver exists +unconditionally, drop of_match_ptr() to avoid a warning. + +Signed-off-by: Jacopo Mondi + +drivers: media: pispbe: Add local config buffer DMA allocation + +When initialiasing the driver, allocate a number of tiles + config +structures used for storing hardware config internally in the driver. + +Signed-off-by: Naushir Patuck + +drivers: media: pispbe: Use local config buffers + +Store a copy of the config + tiles buffer locally when the buffer gets +queued. This resolves the security issue where a userland process may +modify the config buffer after it has been queued. + +Signed-off-by: Naushir Patuck + +drivers: media: pispbe: Validate config buffers + +Perform a basic config validation on the device output nodes to ensure +the buffer size and stride values do not result in a buffer overrun. + +Signed-off-by: Naushir Patuck + +media: bcm2712: Rework probe sequence order + +Rework the probe sequence to: +1) Use dev_err_probe() when failing to get clocks +2) Disable clock on error path +3) Disable the node groups if they have been enabled and + propagate the error up + +Also disable clocks in the remove() function. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Use pm_runtime_ops + +Introduce usage of runtime resume and suspend operations. + +The diver only uses a single clock source which is enable/disabled +at resume and suspend time. + +Implement file open and release operations to control enablement of +the clock provider. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Demote info message + +Demote info message about clock enablement to dev_dbg() + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Move pm_runtime calls to streamon/streamoff + +Move the calls to pm_runtime_resume_and_get() and pm_runtime_put() +to the streamon and streamoff ioctl handlers. + +Remove custom handlers for the open and close file operations and use +the framework provided helpers. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Use pm_runtime_autosuspend() + +Use the _autosuspend() version of runtime_pm_put() in order to avoid +resuming and suspending the peripheral in between streaming sessions +closely apart one from the other. + +Signed-off-by: Jacopo Mondi + +drivers: media: pisp_be: Conditionally check buffers when preparing jobs + +When preparing a job, check the global enables in the config structure +to see if the Output0/1, Tdn and Stitch blocks are enabled, and only +test for a buffer queued if they are. + +This will allow userland to control the outputs selectively without +disabling/re-enabling the respective device nodes. + +Signed-off-by: Naushir Patuck + +media: bcm2712: Rework media controller registration + +The current implementation register the v4l2_device and the video +devices first, then creates the media controller and manually registers +entities there. + +Rework the registration procedure to first create the v4l2_device and +register the media_device with it. Then create the video nodes which +gets automatically registered in the media graph by the core. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Create v4l2_subdev for ISP entity + +Create a v4l2 subdevice to represent the PISPBE ISP entity. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Fix v4l2-compliance warn on QUERYCAP + +Fix: + +warn: v4l2-compliance.cpp(669): media bus_info +'platform:1000880000.pisp_be' differs from V4L2 bus_info +'platform:pispbe' + +by populating the driver caps bus_info by using dev_name(). + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Fix v4l2-compliance warn on invalid pixfmt + +The V4L2 API for the TRY_FMT/S_FMT ioctl allows the ioctl handler to +return an error code only in specific conditions. If an invalid pixel +format is supplied it should be adjusted instead of an error being +returned. + +Albeit, v4l2-compliance treats this situation as a warning and not as +an error because the behaviour has been discussed in length in the past. + +warn: v4l2-test-formats.cpp(794): TRY_FMT cannot handle an invalid pixelformat. +warn: v4l2-test-formats.cpp(795): This may or may not be a problem. For more information see: +warn: v4l2-test-formats.cpp(796): http://www.mail-archive.com/linux-media@vger.kernel.org/msg56550.html +VIDIOC_TRY_FMT returned -1 (Invalid argument) + +Regardless of the warning vs failure decision, adjust the try_format() +function implementation to use V4L2_PIX_FMT_YUV420M as default pixel +format if the supplied one is invalid. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Fix v4l2-compliance warn on HOG pix format + +The try_format() implementation for the HOG video device node returns +an error if the supplied pixel format is not correct. + +As per the video device output and capture video nodes, this contradicts +the V4L2 specification even if it is treated as a warning by +v4l2-compliance. + +Fix this by forcing the buffer pixel format and size to the default +supported one. While at here, use the BIT() macro in the format +initialization function. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Fix formats enumeration + +Right now a single implementation of enum_fmt() is used for all nodes +in a group. This means that all the BE supported formats are listed for +all the nodes. This is incorrect as the meta capture and output node +formats should be restricted, and the meta formats should not be +enumerated for video output and capture devices. + +Fix this by restricting the enumeration of META formats to the config +and hog nodes. Split out from the list of supported_formats the +V4L2_META_FMT_RPI_BE_CFG which is only used for the meta_out node, while +V4L2_PIX_FMT_RPI_BE is kept in the list of supported_formats as it can +be used as an opaque format for both meta_cap, video_cap and video_out +nodes. + +Signed-off-by: Jacopo Mondi + +media: bcm2712: Minor fixes to support PiSP regression tests + +Allow RGB input, not just Bayer (but only of those at once); +Allow Wallpaper image formats. XXX They are not yet size-checked; +Set "chicken bits" to test BURST_TRIM and AXI AWID/BID variation. +Convert some v4l2_err() to dev_err() + +Signed-off-by: Nick Hollinghurst + +drivers: media: pisp_be: Use the maximum number of config buffers + +Set PISP_BE_NUM_CONFIG_BUFFERS the the maximum number of possible +buffers. In the worst case, this overallocates config buffers, but +given their size, it's not too much of a problem. + +Signed-off-by: Naushir Patuck + +media: pisp_be: Fix extra PM runtime put + +vidioc_streamoff callback can be called even if vidioc_streamon was +never called. The driver currently does PM runtime get/put in these +callbacks, which may lead to a put without a matching get. + +Fix this by moving the PM runtime get/put to vb2_ops's start_streaming & +stop_streaming, which the framework makes sure won't get extra calls. + +Signed-off-by: Tomi Valkeinen + +drivers: media: pisp_be: Don't report V4L2_PIX_FMT_RPI_BE format + +This is an internal opaque format, not to be reported in enum_fmt. + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/Kconfig | 1 + + drivers/media/platform/Makefile | 1 + + drivers/media/platform/raspberrypi/Kconfig | 5 + + drivers/media/platform/raspberrypi/Makefile | 3 + + .../platform/raspberrypi/pisp_be/Kconfig | 12 + + .../platform/raspberrypi/pisp_be/Makefile | 6 + + .../platform/raspberrypi/pisp_be/pisp_be.c | 1985 +++++++++++++++++ + .../raspberrypi/pisp_be/pisp_be_config.h | 533 +++++ + .../raspberrypi/pisp_be/pisp_be_formats.h | 469 ++++ + drivers/media/v4l2-core/v4l2-ioctl.c | 2 + + include/media/raspberrypi/pisp_common.h | 65 + + include/media/raspberrypi/pisp_types.h | 144 ++ + include/uapi/linux/videodev2.h | 6 + + 13 files changed, 3232 insertions(+) + create mode 100644 drivers/media/platform/raspberrypi/Kconfig + create mode 100644 drivers/media/platform/raspberrypi/Makefile + create mode 100644 drivers/media/platform/raspberrypi/pisp_be/Kconfig + create mode 100644 drivers/media/platform/raspberrypi/pisp_be/Makefile + create mode 100644 drivers/media/platform/raspberrypi/pisp_be/pisp_be.c + create mode 100644 drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h + create mode 100644 drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h + create mode 100644 include/media/raspberrypi/pisp_common.h + create mode 100644 include/media/raspberrypi/pisp_types.h + +--- a/drivers/media/platform/Kconfig ++++ b/drivers/media/platform/Kconfig +@@ -76,6 +76,7 @@ source "drivers/media/platform/mediatek/ + source "drivers/media/platform/nvidia/Kconfig" + source "drivers/media/platform/nxp/Kconfig" + source "drivers/media/platform/qcom/Kconfig" ++source "drivers/media/platform/raspberrypi/Kconfig" + source "drivers/media/platform/renesas/Kconfig" + source "drivers/media/platform/rockchip/Kconfig" + source "drivers/media/platform/samsung/Kconfig" +--- a/drivers/media/platform/Makefile ++++ b/drivers/media/platform/Makefile +@@ -19,6 +19,7 @@ obj-y += mediatek/ + obj-y += nvidia/ + obj-y += nxp/ + obj-y += qcom/ ++obj-y += raspberrypi/ + obj-y += renesas/ + obj-y += rockchip/ + obj-y += samsung/ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/Kconfig +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++comment "Raspberry Pi media platform drivers" ++ ++source "drivers/media/platform/raspberrypi/pisp_be/Kconfig" +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-y += pisp_be/ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/pisp_be/Kconfig +@@ -0,0 +1,12 @@ ++config VIDEO_RASPBERRYPI_PISP_BE ++ tristate "Raspberry Pi PiSP Backend (BE) ISP driver" ++ depends on VIDEO_DEV && PM ++ select VIDEO_V4L2_SUBDEV_API ++ select MEDIA_CONTROLLER ++ select VIDEOBUF2_DMA_CONTIG ++ select V4L2_FWNODE ++ help ++ Say Y here to enable support for the PiSP Backend (BE) ISP driver. ++ ++ To compile this driver as a module, choose M here. The module will be ++ called pisp-be. +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/pisp_be/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for Raspberry Pi PiSP Backend driver ++# ++pisp-be-objs := pisp_be.o ++obj-$(CONFIG_VIDEO_RASPBERRYPI_PISP_BE) += pisp-be.o +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c +@@ -0,0 +1,1985 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * PiSP Back End driver. ++ * Copyright (c) 2021-2022 Raspberry Pi Limited. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "pisp_be_config.h" ++#include "pisp_be_formats.h" ++ ++MODULE_DESCRIPTION("PiSP Back End driver"); ++MODULE_AUTHOR("David Plowman "); ++MODULE_AUTHOR("Nick Hollinghurst "); ++MODULE_LICENSE("GPL v2"); ++ ++/* Offset to use when registering the /dev/videoX node */ ++#define PISPBE_VIDEO_NODE_OFFSET 20 ++ ++/* Maximum number of config buffers possible */ ++#define PISP_BE_NUM_CONFIG_BUFFERS VB2_MAX_FRAME ++ ++/* ++ * We want to support 2 independent instances allowing 2 simultaneous users ++ * of the ISP-BE (of course they share hardware, platform resources and mutex). ++ * Each such instance comprises a group of device nodes representing input ++ * and output queues, and a media controller device node to describe them. ++ */ ++#define PISPBE_NUM_NODE_GROUPS 2 ++ ++#define PISPBE_NAME "pispbe" ++ ++/* Some ISP-BE registers */ ++#define PISP_BE_VERSION_OFFSET (0x0) ++#define PISP_BE_CONTROL_OFFSET (0x4) ++#define PISP_BE_TILE_ADDR_LO_OFFSET (0x8) ++#define PISP_BE_TILE_ADDR_HI_OFFSET (0xc) ++#define PISP_BE_STATUS_OFFSET (0x10) ++#define PISP_BE_BATCH_STATUS_OFFSET (0x14) ++#define PISP_BE_INTERRUPT_EN_OFFSET (0x18) ++#define PISP_BE_INTERRUPT_STATUS_OFFSET (0x1c) ++#define PISP_BE_AXI_OFFSET (0x20) ++#define PISP_BE_CONFIG_BASE_OFFSET (0x40) ++#define PISP_BE_IO_INPUT_ADDR0_LO_OFFSET (PISP_BE_CONFIG_BASE_OFFSET) ++#define PISP_BE_GLOBAL_BAYER_ENABLE_OFFSET (PISP_BE_CONFIG_BASE_OFFSET + 0x70) ++#define PISP_BE_GLOBAL_RGB_ENABLE_OFFSET (PISP_BE_CONFIG_BASE_OFFSET + 0x74) ++#define N_HW_ADDRESSES 14 ++#define N_HW_ENABLES 2 ++ ++#define PISP_BE_VERSION_2712C1 0x02252700 ++#define PISP_BE_VERSION_MINOR_BITS 0xF ++ ++/* ++ * This maps our nodes onto the inputs/outputs of the actual PiSP Back End. ++ * Be wary of the word "OUTPUT" which is used ambiguously here. In a V4L2 ++ * context it means an input to the hardware (source image or metadata). ++ * Elsewhere it means an output from the hardware. ++ */ ++enum node_ids { ++ MAIN_INPUT_NODE, ++ TDN_INPUT_NODE, ++ STITCH_INPUT_NODE, ++ HOG_OUTPUT_NODE, ++ OUTPUT0_NODE, ++ OUTPUT1_NODE, ++ TDN_OUTPUT_NODE, ++ STITCH_OUTPUT_NODE, ++ CONFIG_NODE, ++ PISPBE_NUM_NODES ++}; ++ ++struct node_description { ++ const char *ent_name; ++ enum v4l2_buf_type buf_type; ++ unsigned int caps; ++}; ++ ++static const struct node_description node_desc[PISPBE_NUM_NODES] = { ++ /* MAIN_INPUT_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-input", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, ++ .caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE, ++ }, ++ /* TDN_INPUT_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-tdn_input", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, ++ .caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE, ++ }, ++ /* STITCH_INPUT_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-stitch_input", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, ++ .caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE, ++ }, ++ /* HOG_OUTPUT_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-hog_output", ++ .buf_type = V4L2_BUF_TYPE_META_CAPTURE, ++ .caps = V4L2_CAP_META_CAPTURE, ++ }, ++ /* OUTPUT0_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-output0", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE, ++ }, ++ /* OUTPUT1_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-output1", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE, ++ }, ++ /* TDN_OUTPUT_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-tdn_output", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE, ++ }, ++ /* STITCH_OUTPUT_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-stitch_output", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE, ++ }, ++ /* CONFIG_NODE */ ++ { ++ .ent_name = PISPBE_NAME "-config", ++ .buf_type = V4L2_BUF_TYPE_META_OUTPUT, ++ .caps = V4L2_CAP_META_OUTPUT, ++ } ++}; ++ ++#define NODE_DESC_IS_OUTPUT(desc) ( \ ++ ((desc)->buf_type == V4L2_BUF_TYPE_META_OUTPUT) || \ ++ ((desc)->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT) || \ ++ ((desc)->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) ++ ++#define NODE_IS_META(node) ( \ ++ ((node)->buf_type == V4L2_BUF_TYPE_META_OUTPUT) || \ ++ ((node)->buf_type == V4L2_BUF_TYPE_META_CAPTURE)) ++#define NODE_IS_OUTPUT(node) ( \ ++ ((node)->buf_type == V4L2_BUF_TYPE_META_OUTPUT) || \ ++ ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT) || \ ++ ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) ++#define NODE_IS_CAPTURE(node) ( \ ++ ((node)->buf_type == V4L2_BUF_TYPE_META_CAPTURE) || \ ++ ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) || \ ++ ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) ++#define NODE_IS_MPLANE(node) ( \ ++ ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) || \ ++ ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) ++ ++/* ++ * Structure to describe a single node /dev/video which represents a single ++ * input or output queue to the PiSP Back End device. ++ */ ++struct pispbe_node { ++ unsigned int id; ++ int vfl_dir; ++ enum v4l2_buf_type buf_type; ++ struct video_device vfd; ++ struct media_pad pad; ++ struct media_intf_devnode *intf_devnode; ++ struct media_link *intf_link; ++ struct pispbe_node_group *node_group; ++ struct mutex node_lock; ++ struct mutex queue_lock; ++ spinlock_t ready_lock; ++ struct list_head ready_queue; ++ struct vb2_queue queue; ++ struct v4l2_format format; ++ const struct pisp_be_format *pisp_format; ++}; ++ ++/* For logging only, use the entity name with "pispbe" and separator removed */ ++#define NODE_NAME(node) \ ++ (node_desc[(node)->id].ent_name + sizeof(PISPBE_NAME)) ++#define NODE_GET_V4L2(node) ((node)->node_group->v4l2_dev) ++ ++/* ++ * Node group structure, which comprises all the input and output nodes that a ++ * single PiSP client will need, along with its own v4l2 and media devices. ++ */ ++struct pispbe_node_group { ++ unsigned int id; ++ struct v4l2_device v4l2_dev; ++ struct v4l2_subdev sd; ++ struct pispbe_dev *pispbe; ++ struct media_device mdev; ++ struct pispbe_node node[PISPBE_NUM_NODES]; ++ u32 streaming_map; /* bitmap of which nodes are streaming */ ++ struct media_pad pad[PISPBE_NUM_NODES]; /* output pads first */ ++ struct pisp_be_tiles_config *config; ++ dma_addr_t config_dma_addr; ++}; ++ ++/* Records details of the jobs currently running or queued on the h/w. */ ++struct pispbe_job { ++ struct pispbe_node_group *node_group; ++ /* ++ * An array of buffer pointers - remember it's source buffers first, ++ * then captures, then metadata last. ++ */ ++ struct pispbe_buffer *buf[PISPBE_NUM_NODES]; ++}; ++ ++/* ++ * Structure representing the entire PiSP Back End device, comprising several ++ * node groups which share platform resources and a mutex for the actual HW. ++ */ ++struct pispbe_dev { ++ struct device *dev; ++ struct pispbe_node_group node_group[PISPBE_NUM_NODE_GROUPS]; ++ int hw_busy; /* non-zero if a job is queued or is being started */ ++ struct pispbe_job queued_job, running_job; ++ void __iomem *be_reg_base; ++ struct clk *clk; ++ int irq; ++ u32 hw_version; ++ u8 done, started; ++ spinlock_t hw_lock; /* protects "hw_busy" flag and streaming_map */ ++}; ++ ++static inline u32 read_reg(struct pispbe_dev *pispbe, unsigned int offset) ++{ ++ return readl(pispbe->be_reg_base + offset); ++} ++ ++static inline void write_reg(struct pispbe_dev *pispbe, unsigned int offset, ++ u32 val) ++{ ++ writel(val, pispbe->be_reg_base + offset); ++} ++ ++/* Check and initialize hardware. */ ++static int hw_init(struct pispbe_dev *pispbe) ++{ ++ u32 u; ++ ++ /* Check the HW is present and has a known version */ ++ u = read_reg(pispbe, PISP_BE_VERSION_OFFSET); ++ dev_info(pispbe->dev, "pispbe_probe: HW version: 0x%08x", u); ++ pispbe->hw_version = u; ++ if ((u & ~PISP_BE_VERSION_MINOR_BITS) != PISP_BE_VERSION_2712C1) ++ return -ENODEV; ++ ++ /* Clear leftover interrupts */ ++ write_reg(pispbe, PISP_BE_INTERRUPT_STATUS_OFFSET, 0xFFFFFFFFu); ++ u = read_reg(pispbe, PISP_BE_BATCH_STATUS_OFFSET); ++ dev_info(pispbe->dev, "pispbe_probe: BatchStatus: 0x%08x", u); ++ pispbe->done = (uint8_t)u; ++ pispbe->started = (uint8_t)(u >> 8); ++ u = read_reg(pispbe, PISP_BE_STATUS_OFFSET); ++ dev_info(pispbe->dev, "pispbe_probe: Status: 0x%08x", u); ++ if (u != 0 || pispbe->done != pispbe->started) { ++ dev_err(pispbe->dev, "pispbe_probe: HW is stuck or busy\n"); ++ return -EBUSY; ++ } ++ /* ++ * AXI QOS=0, CACHE=4'b0010, PROT=3'b011 ++ * Also set "chicken bits" 22:20 which enable sub-64-byte bursts ++ * and AXI AWID/BID variability (on versions which support this). ++ */ ++ write_reg(pispbe, PISP_BE_AXI_OFFSET, 0x32703200u); ++ ++ /* Enable both interrupt flags */ ++ write_reg(pispbe, PISP_BE_INTERRUPT_EN_OFFSET, 0x00000003u); ++ return 0; ++} ++ ++/* ++ * Queue a job to the h/w. If the h/w is idle it will begin immediately. ++ * Caller must ensure it is "safe to queue", i.e. we don't already have a ++ * queued, unstarted job. ++ */ ++static void hw_queue_job(struct pispbe_dev *pispbe, ++ dma_addr_t hw_dma_addrs[N_HW_ADDRESSES], ++ u32 hw_enables[N_HW_ENABLES], ++ struct pisp_be_config *config, dma_addr_t tiles, ++ unsigned int num_tiles) ++{ ++ unsigned int begin, end; ++ unsigned int u; ++ ++ if (read_reg(pispbe, PISP_BE_STATUS_OFFSET) & 1) ++ dev_err(pispbe->dev, "ERROR: not safe to queue new job!\n"); ++ ++ /* ++ * Write configuration to hardware. DMA addresses and enable flags ++ * are passed separately, because the driver needs to sanitize them, ++ * and we don't want to modify (or be vulnerable to modifications of) ++ * the mmap'd buffer. ++ */ ++ for (u = 0; u < N_HW_ADDRESSES; ++u) { ++ write_reg(pispbe, PISP_BE_IO_INPUT_ADDR0_LO_OFFSET + 8 * u, ++ (u32)(hw_dma_addrs[u])); ++ write_reg(pispbe, PISP_BE_IO_INPUT_ADDR0_LO_OFFSET + 8 * u + 4, ++ (u32)(hw_dma_addrs[u] >> 32)); ++ } ++ write_reg(pispbe, PISP_BE_GLOBAL_BAYER_ENABLE_OFFSET, hw_enables[0]); ++ write_reg(pispbe, PISP_BE_GLOBAL_RGB_ENABLE_OFFSET, hw_enables[1]); ++ ++ /* ++ * Everything else is as supplied by the user. XXX Buffer sizes not ++ * checked! ++ */ ++ begin = offsetof(struct pisp_be_config, global.bayer_order) / ++ sizeof(u32); ++ end = offsetof(struct pisp_be_config, axi) / sizeof(u32); ++ for (u = begin; u < end; u++) { ++ unsigned int val = ((u32 *)config)[u]; ++ ++ write_reg(pispbe, PISP_BE_CONFIG_BASE_OFFSET + 4 * u, val); ++ } ++ ++ /* Read back the addresses -- an error here could be fatal */ ++ for (u = 0; u < N_HW_ADDRESSES; ++u) { ++ unsigned int offset = PISP_BE_IO_INPUT_ADDR0_LO_OFFSET + 8 * u; ++ u64 along = read_reg(pispbe, offset); ++ ++ along += ((u64)read_reg(pispbe, offset + 4)) << 32; ++ if (along != (u64)(hw_dma_addrs[u])) { ++ dev_err(pispbe->dev, ++ "ISP BE config error: check if ISP RAMs enabled?\n"); ++ return; ++ } ++ } ++ ++ /* ++ * Write tile pointer to hardware. XXX Tile offsets and sizes not ++ * checked (and even if checked, the user could subsequently modify ++ * them)! ++ */ ++ write_reg(pispbe, PISP_BE_TILE_ADDR_LO_OFFSET, (u32)tiles); ++ write_reg(pispbe, PISP_BE_TILE_ADDR_HI_OFFSET, (u32)(tiles >> 32)); ++ ++ /* Enqueue the job */ ++ write_reg(pispbe, PISP_BE_CONTROL_OFFSET, 3 + 65536 * num_tiles); ++} ++ ++struct pispbe_buffer { ++ struct vb2_v4l2_buffer vb; ++ struct list_head ready_list; ++ unsigned int config_index; ++}; ++ ++static int get_addr_3(dma_addr_t addr[3], struct pispbe_buffer *buf, ++ struct pispbe_node *node) ++{ ++ unsigned int num_planes = node->format.fmt.pix_mp.num_planes; ++ unsigned int plane_factor = 0; ++ unsigned int size; ++ unsigned int p; ++ ++ if (!buf || !node->pisp_format) ++ return 0; ++ ++ WARN_ON(!NODE_IS_MPLANE(node)); ++ ++ /* ++ * Determine the base plane size. This will not be the same ++ * as node->format.fmt.pix_mp.plane_fmt[0].sizeimage for a single ++ * plane buffer in an mplane format. ++ */ ++ size = node->format.fmt.pix_mp.plane_fmt[0].bytesperline * ++ node->format.fmt.pix_mp.height; ++ ++ for (p = 0; p < num_planes && p < 3; p++) { ++ addr[p] = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, p); ++ plane_factor += node->pisp_format->plane_factor[p]; ++ } ++ ++ for (; p < MAX_PLANES && node->pisp_format->plane_factor[p]; p++) { ++ /* ++ * Calculate the address offset of this plane as needed ++ * by the hardware. This is specifically for non-mplane ++ * buffer formats, where there are 3 image planes, e.g. ++ * for the V4L2_PIX_FMT_YUV420 format. ++ */ ++ addr[p] = addr[0] + ((size * plane_factor) >> 3); ++ plane_factor += node->pisp_format->plane_factor[p]; ++ } ++ ++ return num_planes; ++} ++ ++static dma_addr_t get_addr(struct pispbe_buffer *buf) ++{ ++ if (buf) ++ return vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); ++ return 0; ++} ++ ++static void ++fixup_addrs_enables(dma_addr_t addrs[N_HW_ADDRESSES], ++ u32 hw_enables[N_HW_ENABLES], ++ struct pisp_be_tiles_config *config, ++ struct pispbe_buffer *buf[PISPBE_NUM_NODES], ++ struct pispbe_node_group *node_group) ++{ ++ int ret, i; ++ ++ /* Take a copy of the "enable" bitmaps so we can modify them. */ ++ hw_enables[0] = config->config.global.bayer_enables; ++ hw_enables[1] = config->config.global.rgb_enables; ++ ++ /* ++ * Main input first. There are 3 address pointers, corresponding to up ++ * to 3 planes. ++ */ ++ ret = get_addr_3(addrs, buf[MAIN_INPUT_NODE], ++ &node_group->node[MAIN_INPUT_NODE]); ++ if (ret <= 0) { ++ /* ++ * This shouldn't happen; pispbe_schedule_internal should insist ++ * on an input. ++ */ ++ dev_warn(node_group->pispbe->dev, ++ "ISP-BE missing input\n"); ++ hw_enables[0] = 0; ++ hw_enables[1] = 0; ++ return; ++ } ++ ++ /* ++ * Now TDN/Stitch inputs and outputs. These are single-plane and only ++ * used with Bayer input. Input enables must match the requirements ++ * of the processing stages, otherwise the hardware can lock up! ++ */ ++ if (hw_enables[0] & PISP_BE_BAYER_ENABLE_INPUT) { ++ addrs[3] = get_addr(buf[TDN_INPUT_NODE]); ++ if (addrs[3] == 0 || ++ !(hw_enables[0] & PISP_BE_BAYER_ENABLE_TDN_INPUT) || ++ !(hw_enables[0] & PISP_BE_BAYER_ENABLE_TDN) || ++ (config->config.tdn.reset & 1)) { ++ hw_enables[0] &= ~(PISP_BE_BAYER_ENABLE_TDN_INPUT | ++ PISP_BE_BAYER_ENABLE_TDN_DECOMPRESS); ++ if (!(config->config.tdn.reset & 1)) ++ hw_enables[0] &= ~PISP_BE_BAYER_ENABLE_TDN; ++ } ++ ++ addrs[4] = get_addr(buf[STITCH_INPUT_NODE]); ++ if (addrs[4] == 0 || ++ !(hw_enables[0] & PISP_BE_BAYER_ENABLE_STITCH_INPUT) || ++ !(hw_enables[0] & PISP_BE_BAYER_ENABLE_STITCH)) { ++ hw_enables[0] &= ++ ~(PISP_BE_BAYER_ENABLE_STITCH_INPUT | ++ PISP_BE_BAYER_ENABLE_STITCH_DECOMPRESS | ++ PISP_BE_BAYER_ENABLE_STITCH); ++ } ++ ++ addrs[5] = get_addr(buf[TDN_OUTPUT_NODE]); ++ if (addrs[5] == 0) ++ hw_enables[0] &= ~(PISP_BE_BAYER_ENABLE_TDN_COMPRESS | ++ PISP_BE_BAYER_ENABLE_TDN_OUTPUT); ++ ++ addrs[6] = get_addr(buf[STITCH_OUTPUT_NODE]); ++ if (addrs[6] == 0) ++ hw_enables[0] &= ++ ~(PISP_BE_BAYER_ENABLE_STITCH_COMPRESS | ++ PISP_BE_BAYER_ENABLE_STITCH_OUTPUT); ++ } else { ++ /* No Bayer input? Disable entire Bayer pipe (else lockup) */ ++ hw_enables[0] = 0; ++ } ++ ++ /* Main image output channels. */ ++ for (i = 0; i < PISP_BACK_END_NUM_OUTPUTS; i++) { ++ ret = get_addr_3(addrs + 7 + 3 * i, buf[OUTPUT0_NODE + i], ++ &node_group->node[OUTPUT0_NODE + i]); ++ if (ret <= 0) ++ hw_enables[1] &= ~(PISP_BE_RGB_ENABLE_OUTPUT0 << i); ++ } ++ ++ /* HoG output (always single plane). */ ++ addrs[13] = get_addr(buf[HOG_OUTPUT_NODE]); ++ if (addrs[13] == 0) ++ hw_enables[1] &= ~PISP_BE_RGB_ENABLE_HOG; ++} ++ ++/* ++ * Internal function. Called from pispbe_schedule_one/all. Returns non-zero if ++ * we started a job. ++ * ++ * Warning: needs to be called with hw_lock taken, and releases it if it ++ * schedules a job. ++ */ ++static int pispbe_schedule_internal(struct pispbe_node_group *node_group, ++ unsigned long flags) ++{ ++ struct pisp_be_tiles_config *config_tiles_buffer; ++ struct pispbe_dev *pispbe = node_group->pispbe; ++ struct pispbe_buffer *buf[PISPBE_NUM_NODES]; ++ dma_addr_t hw_dma_addrs[N_HW_ADDRESSES]; ++ dma_addr_t tiles; ++ u32 hw_enables[N_HW_ENABLES]; ++ struct pispbe_node *node; ++ unsigned long flags1; ++ unsigned int config_index; ++ int i; ++ ++ /* ++ * To schedule a job, we need all streaming nodes (apart from Output0, ++ * Output1, Tdn and Stitch) to have a buffer ready, which must ++ * include at least a config buffer and a main input image. ++ * ++ * For Output0, Output1, Tdn and Stitch, a buffer only needs to be ++ * available if the blocks are enabled in the config. ++ * ++ * (Note that streaming_map is protected by hw_lock, which is held.) ++ */ ++ if (((BIT(CONFIG_NODE) | BIT(MAIN_INPUT_NODE)) & ++ node_group->streaming_map) != ++ (BIT(CONFIG_NODE) | BIT(MAIN_INPUT_NODE))) { ++ dev_dbg(pispbe->dev, "Nothing to do\n"); ++ return 0; ++ } ++ ++ node = &node_group->node[CONFIG_NODE]; ++ spin_lock_irqsave(&node->ready_lock, flags1); ++ buf[CONFIG_NODE] = ++ list_first_entry_or_null(&node->ready_queue, struct pispbe_buffer, ++ ready_list); ++ spin_unlock_irqrestore(&node->ready_lock, flags1); ++ ++ /* Exit early if no config buffer has been queued. */ ++ if (!buf[CONFIG_NODE]) ++ return 0; ++ ++ config_index = buf[CONFIG_NODE]->vb.vb2_buf.index; ++ config_tiles_buffer = &node_group->config[config_index]; ++ tiles = (dma_addr_t)node_group->config_dma_addr + ++ config_index * sizeof(struct pisp_be_tiles_config) + ++ offsetof(struct pisp_be_tiles_config, tiles); ++ ++ /* remember: srcimages, captures then metadata */ ++ for (i = 0; i < PISPBE_NUM_NODES; i++) { ++ unsigned int bayer_en = ++ config_tiles_buffer->config.global.bayer_enables; ++ unsigned int rgb_en = ++ config_tiles_buffer->config.global.rgb_enables; ++ bool ignore_buffers = false; ++ ++ /* Config node is handled outside the loop above. */ ++ if (i == CONFIG_NODE) ++ continue; ++ ++ buf[i] = NULL; ++ if (!(node_group->streaming_map & BIT(i))) ++ continue; ++ ++ if ((!(rgb_en & PISP_BE_RGB_ENABLE_OUTPUT0) && ++ i == OUTPUT0_NODE) || ++ (!(rgb_en & PISP_BE_RGB_ENABLE_OUTPUT1) && ++ i == OUTPUT1_NODE) || ++ (!(bayer_en & PISP_BE_BAYER_ENABLE_TDN_INPUT) && ++ i == TDN_INPUT_NODE) || ++ (!(bayer_en & PISP_BE_BAYER_ENABLE_TDN_OUTPUT) && ++ i == TDN_OUTPUT_NODE) || ++ (!(bayer_en & PISP_BE_BAYER_ENABLE_STITCH_INPUT) && ++ i == STITCH_INPUT_NODE) || ++ (!(bayer_en & PISP_BE_BAYER_ENABLE_STITCH_OUTPUT) && ++ i == STITCH_OUTPUT_NODE)) { ++ /* ++ * Ignore Output0/Output1/Tdn/Stitch buffer check if the ++ * global enables aren't set for these blocks. If a ++ * buffer has been provided, we dequeue it back to the ++ * user with the other in-use buffers. ++ * ++ */ ++ ignore_buffers = true; ++ } ++ ++ node = &node_group->node[i]; ++ ++ spin_lock_irqsave(&node->ready_lock, flags1); ++ buf[i] = list_first_entry_or_null(&node->ready_queue, ++ struct pispbe_buffer, ++ ready_list); ++ spin_unlock_irqrestore(&node->ready_lock, flags1); ++ if (!buf[i] && !ignore_buffers) { ++ dev_dbg(pispbe->dev, "Nothing to do\n"); ++ return 0; ++ } ++ } ++ ++ /* Pull a buffer from each V4L2 queue to form the queued job */ ++ for (i = 0; i < PISPBE_NUM_NODES; i++) { ++ if (buf[i]) { ++ node = &node_group->node[i]; ++ ++ spin_lock_irqsave(&node->ready_lock, flags1); ++ list_del(&buf[i]->ready_list); ++ spin_unlock_irqrestore(&node->ready_lock, ++ flags1); ++ } ++ pispbe->queued_job.buf[i] = buf[i]; ++ } ++ ++ pispbe->queued_job.node_group = node_group; ++ pispbe->hw_busy = 1; ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ ++ /* ++ * We can kick the job off without the hw_lock, as this can ++ * never run again until hw_busy is cleared, which will happen ++ * only when the following job has been queued. ++ */ ++ dev_dbg(pispbe->dev, "Have buffers - starting hardware\n"); ++ ++ /* Convert buffers to DMA addresses for the hardware */ ++ fixup_addrs_enables(hw_dma_addrs, hw_enables, ++ config_tiles_buffer, buf, node_group); ++ /* ++ * This could be a spot to fill in the ++ * buf[i]->vb.vb2_buf.planes[j].bytesused fields? ++ */ ++ i = config_tiles_buffer->num_tiles; ++ if (i <= 0 || i > PISP_BACK_END_NUM_TILES || ++ !((hw_enables[0] | hw_enables[1]) & ++ PISP_BE_BAYER_ENABLE_INPUT)) { ++ /* ++ * Bad job. We can't let it proceed as it could lock up ++ * the hardware, or worse! ++ * ++ * XXX How to deal with this most cleanly? For now, just ++ * force num_tiles to 0, which causes the H/W to do ++ * something bizarre but survivable. It increments ++ * (started,done) counters by more than 1, but we seem ++ * to survive... ++ */ ++ dev_err(pispbe->dev, "PROBLEM: Bad job"); ++ i = 0; ++ } ++ hw_queue_job(pispbe, hw_dma_addrs, hw_enables, ++ &config_tiles_buffer->config, tiles, i); ++ ++ return 1; ++} ++ ++/* Try and schedule a job for just a single node group. */ ++static void pispbe_schedule_one(struct pispbe_node_group *node_group) ++{ ++ struct pispbe_dev *pispbe = node_group->pispbe; ++ unsigned long flags; ++ int ret; ++ ++ spin_lock_irqsave(&pispbe->hw_lock, flags); ++ if (pispbe->hw_busy) { ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ return; ++ } ++ ++ /* A non-zero return means the lock was released. */ ++ ret = pispbe_schedule_internal(node_group, flags); ++ if (!ret) ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++} ++ ++/* Try and schedule a job for any of the node groups. */ ++static void pispbe_schedule_any(struct pispbe_dev *pispbe, int clear_hw_busy) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&pispbe->hw_lock, flags); ++ ++ if (clear_hw_busy) ++ pispbe->hw_busy = 0; ++ if (pispbe->hw_busy == 0) { ++ unsigned int i; ++ ++ for (i = 0; i < PISPBE_NUM_NODE_GROUPS; i++) { ++ /* ++ * A non-zero return from pispbe_schedule_internal means ++ * the lock was released. ++ */ ++ if (pispbe_schedule_internal(&pispbe->node_group[i], ++ flags)) ++ return; ++ } ++ } ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++} ++ ++static void pispbe_isr_jobdone(struct pispbe_dev *pispbe, ++ struct pispbe_job *job) ++{ ++ struct pispbe_buffer **buf = job->buf; ++ u64 ts = ktime_get_ns(); ++ int i; ++ ++ for (i = 0; i < PISPBE_NUM_NODES; i++) { ++ if (buf[i]) { ++ buf[i]->vb.vb2_buf.timestamp = ts; ++ vb2_buffer_done(&buf[i]->vb.vb2_buf, ++ VB2_BUF_STATE_DONE); ++ } ++ } ++} ++ ++static irqreturn_t pispbe_isr(int irq, void *dev) ++{ ++ struct pispbe_dev *pispbe = (struct pispbe_dev *)dev; ++ u8 started, done; ++ int can_queue_another = 0; ++ u32 u; ++ ++ u = read_reg(pispbe, PISP_BE_INTERRUPT_STATUS_OFFSET); ++ if (u == 0) ++ return IRQ_NONE; ++ ++ write_reg(pispbe, PISP_BE_INTERRUPT_STATUS_OFFSET, u); ++ dev_dbg(pispbe->dev, "Hardware interrupt\n"); ++ u = read_reg(pispbe, PISP_BE_BATCH_STATUS_OFFSET); ++ done = (uint8_t)u; ++ started = (uint8_t)(u >> 8); ++ dev_dbg(pispbe->dev, ++ "H/W started %d done %d, previously started %d done %d\n", ++ (int)started, (int)done, (int)pispbe->started, ++ (int)pispbe->done); ++ ++ /* ++ * Be aware that done can go up by 2 and started by 1 when: a job that ++ * we previously saw "start" now finishes, and we then queued a new job ++ * which we see both start and finish "simultaneously". ++ */ ++ if (pispbe->running_job.node_group && pispbe->done != done) { ++ pispbe_isr_jobdone(pispbe, &pispbe->running_job); ++ memset(&pispbe->running_job, 0, sizeof(pispbe->running_job)); ++ pispbe->done++; ++ dev_dbg(pispbe->dev, "Job done (1)\n"); ++ } ++ ++ if (pispbe->started != started) { ++ pispbe->started++; ++ can_queue_another = 1; ++ dev_dbg(pispbe->dev, "Job started\n"); ++ ++ if (pispbe->done != done && pispbe->queued_job.node_group) { ++ pispbe_isr_jobdone(pispbe, &pispbe->queued_job); ++ pispbe->done++; ++ dev_dbg(pispbe->dev, "Job done (2)\n"); ++ } else { ++ pispbe->running_job = pispbe->queued_job; ++ } ++ ++ memset(&pispbe->queued_job, 0, sizeof(pispbe->queued_job)); ++ } ++ ++ if (pispbe->done != done || pispbe->started != started) { ++ dev_err(pispbe->dev, "PROBLEM: counters not matching!\n"); ++ pispbe->started = started; ++ pispbe->done = done; ++ } ++ ++ /* check if there's more to do before going to sleep */ ++ pispbe_schedule_any(pispbe, can_queue_another); ++ ++ return IRQ_HANDLED; ++} ++ ++static int pisp_be_validate_config(struct pispbe_node_group *node_group, ++ struct pisp_be_tiles_config *config) ++{ ++ u32 bayer_enables = config->config.global.bayer_enables; ++ u32 rgb_enables = config->config.global.rgb_enables; ++ struct device *dev = node_group->pispbe->dev; ++ struct v4l2_format *fmt; ++ unsigned int bpl, size, i, j; ++ ++ if (!(bayer_enables & PISP_BE_BAYER_ENABLE_INPUT) == ++ !(rgb_enables & PISP_BE_RGB_ENABLE_INPUT)) { ++ dev_err(dev, "%s: Not one input enabled\n", __func__); ++ return -EIO; ++ } ++ ++ /* Ensure output config strides and buffer sizes match the V4L2 formats. */ ++ fmt = &node_group->node[TDN_OUTPUT_NODE].format; ++ if (bayer_enables & PISP_BE_BAYER_ENABLE_TDN_OUTPUT) { ++ bpl = config->config.tdn_output_format.stride; ++ size = bpl * config->config.tdn_output_format.height; ++ if (fmt->fmt.pix_mp.plane_fmt[0].bytesperline < bpl) { ++ dev_err(dev, "%s: bpl mismatch on tdn_output\n", ++ __func__); ++ return -EINVAL; ++ } ++ if (fmt->fmt.pix_mp.plane_fmt[0].sizeimage < size) { ++ dev_err(dev, "%s: size mismatch on tdn_output\n", ++ __func__); ++ return -EINVAL; ++ } ++ } ++ ++ fmt = &node_group->node[STITCH_OUTPUT_NODE].format; ++ if (bayer_enables & PISP_BE_BAYER_ENABLE_STITCH_OUTPUT) { ++ bpl = config->config.stitch_output_format.stride; ++ size = bpl * config->config.stitch_output_format.height; ++ if (fmt->fmt.pix_mp.plane_fmt[0].bytesperline < bpl) { ++ dev_err(dev, "%s: bpl mismatch on stitch_output\n", ++ __func__); ++ return -EINVAL; ++ } ++ if (fmt->fmt.pix_mp.plane_fmt[0].sizeimage < size) { ++ dev_err(dev, "%s: size mismatch on stitch_output\n", ++ __func__); ++ return -EINVAL; ++ } ++ } ++ ++ for (j = 0; j < PISP_BACK_END_NUM_OUTPUTS; j++) { ++ if (!(rgb_enables & PISP_BE_RGB_ENABLE_OUTPUT(j))) ++ continue; ++ if (config->config.output_format[j].image.format & ++ PISP_IMAGE_FORMAT_WALLPAPER_ROLL) ++ continue; /* TODO: Size checks for wallpaper formats */ ++ ++ fmt = &node_group->node[OUTPUT0_NODE + j].format; ++ for (i = 0; i < fmt->fmt.pix_mp.num_planes; i++) { ++ bpl = !i ? config->config.output_format[j].image.stride ++ : config->config.output_format[j].image.stride2; ++ size = bpl * config->config.output_format[j].image.height; ++ ++ if (config->config.output_format[j].image.format & ++ PISP_IMAGE_FORMAT_SAMPLING_420) ++ size >>= 1; ++ if (fmt->fmt.pix_mp.plane_fmt[i].bytesperline < bpl) { ++ dev_err(dev, "%s: bpl mismatch on output %d\n", ++ __func__, j); ++ return -EINVAL; ++ } ++ if (fmt->fmt.pix_mp.plane_fmt[i].sizeimage < size) { ++ dev_err(dev, "%s: size mismatch on output\n", ++ __func__); ++ return -EINVAL; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int pispbe_node_queue_setup(struct vb2_queue *q, unsigned int *nbuffers, ++ unsigned int *nplanes, unsigned int sizes[], ++ struct device *alloc_devs[]) ++{ ++ struct pispbe_node *node = vb2_get_drv_priv(q); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ ++ *nplanes = 1; ++ if (NODE_IS_MPLANE(node)) { ++ unsigned int i; ++ ++ *nplanes = node->format.fmt.pix_mp.num_planes; ++ for (i = 0; i < *nplanes; i++) { ++ unsigned int size = ++ node->format.fmt.pix_mp.plane_fmt[i].sizeimage; ++ if (sizes[i] && sizes[i] < size) { ++ dev_err(pispbe->dev, "%s: size %u < %u\n", ++ __func__, sizes[i], size); ++ return -EINVAL; ++ } ++ sizes[i] = size; ++ } ++ } else if (NODE_IS_META(node)) { ++ sizes[0] = node->format.fmt.meta.buffersize; ++ /* ++ * Limit the config node buffer count to the number of internal ++ * buffers allocated. ++ */ ++ if (node->id == CONFIG_NODE) ++ *nbuffers = min_t(unsigned int, *nbuffers, ++ PISP_BE_NUM_CONFIG_BUFFERS); ++ } ++ ++ dev_dbg(pispbe->dev, ++ "Image (or metadata) size %u, nbuffers %u for node %s\n", ++ sizes[0], *nbuffers, NODE_NAME(node)); ++ ++ return 0; ++} ++ ++static int pispbe_node_buffer_prepare(struct vb2_buffer *vb) ++{ ++ struct pispbe_node *node = vb2_get_drv_priv(vb->vb2_queue); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ unsigned long size = 0; ++ unsigned int num_planes = NODE_IS_MPLANE(node) ? ++ node->format.fmt.pix_mp.num_planes : 1; ++ unsigned int i; ++ ++ for (i = 0; i < num_planes; i++) { ++ size = NODE_IS_MPLANE(node) ++ ? node->format.fmt.pix_mp.plane_fmt[i].sizeimage ++ : node->format.fmt.meta.buffersize; ++ ++ if (vb2_plane_size(vb, i) < size) { ++ dev_err(pispbe->dev, ++ "data will not fit into plane %d (%lu < %lu)\n", ++ i, vb2_plane_size(vb, i), size); ++ return -EINVAL; ++ } ++ ++ vb2_set_plane_payload(vb, i, size); ++ } ++ ++ if (node->id == CONFIG_NODE) { ++ void *dst = &node->node_group->config[vb->index]; ++ void *src = vb2_plane_vaddr(vb, 0); ++ ++ memcpy(dst, src, sizeof(struct pisp_be_tiles_config)); ++ return pisp_be_validate_config(node->node_group, dst); ++ } ++ ++ return 0; ++} ++ ++static void pispbe_node_buffer_queue(struct vb2_buffer *buf) ++{ ++ struct vb2_v4l2_buffer *vbuf = ++ container_of(buf, struct vb2_v4l2_buffer, vb2_buf); ++ struct pispbe_buffer *buffer = ++ container_of(vbuf, struct pispbe_buffer, vb); ++ struct pispbe_node *node = vb2_get_drv_priv(buf->vb2_queue); ++ struct pispbe_node_group *node_group = node->node_group; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ unsigned long flags; ++ ++ dev_dbg(pispbe->dev, "%s: for node %s\n", __func__, NODE_NAME(node)); ++ spin_lock_irqsave(&node->ready_lock, flags); ++ list_add_tail(&buffer->ready_list, &node->ready_queue); ++ spin_unlock_irqrestore(&node->ready_lock, flags); ++ ++ /* ++ * Every time we add a buffer, check if there's now some work for the hw ++ * to do, but only for this client. ++ */ ++ pispbe_schedule_one(node_group); ++} ++ ++static int pispbe_node_start_streaming(struct vb2_queue *q, unsigned int count) ++{ ++ unsigned long flags; ++ struct pispbe_node *node = vb2_get_drv_priv(q); ++ struct pispbe_node_group *node_group = node->node_group; ++ struct pispbe_dev *pispbe = node_group->pispbe; ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(pispbe->dev); ++ if (ret < 0) ++ return ret; ++ ++ spin_lock_irqsave(&pispbe->hw_lock, flags); ++ node->node_group->streaming_map |= BIT(node->id); ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ ++ dev_dbg(pispbe->dev, "%s: for node %s (count %u)\n", ++ __func__, NODE_NAME(node), count); ++ dev_dbg(pispbe->dev, "Nodes streaming for this group now 0x%x\n", ++ node->node_group->streaming_map); ++ ++ /* Maybe we're ready to run. */ ++ pispbe_schedule_one(node_group); ++ ++ return 0; ++} ++ ++static void pispbe_node_stop_streaming(struct vb2_queue *q) ++{ ++ struct pispbe_node *node = vb2_get_drv_priv(q); ++ struct pispbe_node_group *node_group = node->node_group; ++ struct pispbe_dev *pispbe = node_group->pispbe; ++ struct pispbe_buffer *buf; ++ unsigned long flags; ++ ++ /* ++ * Now this is a bit awkward. In a simple M2M device we could just wait ++ * for all queued jobs to complete, but here there's a risk that a ++ * partial set of buffers was queued and cannot be run. For now, just ++ * cancel all buffers stuck in the "ready queue", then wait for any ++ * running job. ++ * XXX This may return buffers out of order. ++ */ ++ dev_dbg(pispbe->dev, "%s: for node %s\n", __func__, NODE_NAME(node)); ++ spin_lock_irqsave(&pispbe->hw_lock, flags); ++ do { ++ unsigned long flags1; ++ ++ spin_lock_irqsave(&node->ready_lock, flags1); ++ buf = list_first_entry_or_null(&node->ready_queue, ++ struct pispbe_buffer, ++ ready_list); ++ if (buf) { ++ list_del(&buf->ready_list); ++ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); ++ } ++ spin_unlock_irqrestore(&node->ready_lock, flags1); ++ } while (buf); ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ ++ vb2_wait_for_all_buffers(&node->queue); ++ ++ spin_lock_irqsave(&pispbe->hw_lock, flags); ++ node_group->streaming_map &= ~BIT(node->id); ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ ++ pm_runtime_mark_last_busy(pispbe->dev); ++ pm_runtime_put_autosuspend(pispbe->dev); ++ ++ dev_dbg(pispbe->dev, "Nodes streaming for this group now 0x%x\n", ++ node_group->streaming_map); ++} ++ ++static const struct vb2_ops pispbe_node_queue_ops = { ++ .queue_setup = pispbe_node_queue_setup, ++ .buf_prepare = pispbe_node_buffer_prepare, ++ .buf_queue = pispbe_node_buffer_queue, ++ .start_streaming = pispbe_node_start_streaming, ++ .stop_streaming = pispbe_node_stop_streaming, ++}; ++ ++static const struct v4l2_file_operations pispbe_fops = { ++ .owner = THIS_MODULE, ++ .open = v4l2_fh_open, ++ .release = vb2_fop_release, ++ .poll = vb2_fop_poll, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = vb2_fop_mmap ++}; ++ ++static int pispbe_node_querycap(struct file *file, void *priv, ++ struct v4l2_capability *cap) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ ++ strscpy(cap->driver, PISPBE_NAME, sizeof(cap->driver)); ++ strscpy(cap->card, PISPBE_NAME, sizeof(cap->card)); ++ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", ++ dev_name(pispbe->dev)); ++ ++ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE | ++ V4L2_CAP_VIDEO_OUTPUT_MPLANE | ++ V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS | ++ V4L2_CAP_META_OUTPUT | V4L2_CAP_META_CAPTURE; ++ cap->device_caps = node->vfd.device_caps; ++ ++ dev_dbg(pispbe->dev, "Caps for node %s: %x and %x (dev %x)\n", ++ NODE_NAME(node), cap->capabilities, cap->device_caps, ++ node->vfd.device_caps); ++ return 0; ++} ++ ++static int pispbe_node_g_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ ++ if (!NODE_IS_CAPTURE(node) || NODE_IS_META(node)) { ++ dev_err(pispbe->dev, ++ "Cannot get capture fmt for output node %s\n", ++ NODE_NAME(node)); ++ return -EINVAL; ++ } ++ *f = node->format; ++ dev_dbg(pispbe->dev, "Get capture format for node %s\n", ++ NODE_NAME(node)); ++ return 0; ++} ++ ++static int pispbe_node_g_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ ++ if (NODE_IS_CAPTURE(node) || NODE_IS_META(node)) { ++ dev_err(pispbe->dev, ++ "Cannot get capture fmt for output node %s\n", ++ NODE_NAME(node)); ++ return -EINVAL; ++ } ++ *f = node->format; ++ dev_dbg(pispbe->dev, "Get output format for node %s\n", ++ NODE_NAME(node)); ++ return 0; ++} ++ ++static int pispbe_node_g_fmt_meta_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ ++ if (!NODE_IS_META(node) || NODE_IS_CAPTURE(node)) { ++ dev_err(pispbe->dev, ++ "Cannot get capture fmt for meta output node %s\n", ++ NODE_NAME(node)); ++ return -EINVAL; ++ } ++ *f = node->format; ++ dev_dbg(pispbe->dev, "Get output format for meta node %s\n", ++ NODE_NAME(node)); ++ return 0; ++} ++ ++static int pispbe_node_g_fmt_meta_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ ++ if (!NODE_IS_META(node) || NODE_IS_OUTPUT(node)) { ++ dev_err(pispbe->dev, ++ "Cannot get capture fmt for meta output node %s\n", ++ NODE_NAME(node)); ++ return -EINVAL; ++ } ++ *f = node->format; ++ dev_dbg(pispbe->dev, "Get output format for meta node %s\n", ++ NODE_NAME(node)); ++ return 0; ++} ++ ++static int verify_be_pix_format(const struct v4l2_format *f, ++ struct pispbe_node *node) ++{ ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ unsigned int nplanes = f->fmt.pix_mp.num_planes; ++ unsigned int i; ++ ++ if (f->fmt.pix_mp.width == 0 || f->fmt.pix_mp.height == 0) { ++ dev_err(pispbe->dev, "Details incorrect for output node %s\n", ++ NODE_NAME(node)); ++ return -EINVAL; ++ } ++ ++ if (nplanes == 0 || nplanes > MAX_PLANES) { ++ dev_err(pispbe->dev, ++ "Bad number of planes for output node %s, req =%d\n", ++ NODE_NAME(node), nplanes); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < nplanes; i++) { ++ const struct v4l2_plane_pix_format *p; ++ ++ p = &f->fmt.pix_mp.plane_fmt[i]; ++ if (p->bytesperline == 0 || p->sizeimage == 0) { ++ dev_err(pispbe->dev, ++ "Invalid plane %d for output node %s\n", ++ i, NODE_NAME(node)); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct pisp_be_format *find_format(unsigned int fourcc) ++{ ++ const struct pisp_be_format *fmt; ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(supported_formats); i++) { ++ fmt = &supported_formats[i]; ++ if (fmt->fourcc == fourcc) ++ return fmt; ++ } ++ ++ return NULL; ++} ++ ++static void set_plane_params(struct v4l2_format *f, ++ const struct pisp_be_format *fmt) ++{ ++ unsigned int nplanes = f->fmt.pix_mp.num_planes; ++ unsigned int total_plane_factor = 0; ++ unsigned int i; ++ ++ for (i = 0; i < MAX_PLANES; i++) ++ total_plane_factor += fmt->plane_factor[i]; ++ ++ for (i = 0; i < nplanes; i++) { ++ struct v4l2_plane_pix_format *p = &f->fmt.pix_mp.plane_fmt[i]; ++ unsigned int bpl, plane_size; ++ ++ bpl = (f->fmt.pix_mp.width * fmt->bit_depth) >> 3; ++ bpl = ALIGN(max(p->bytesperline, bpl), fmt->align); ++ ++ plane_size = bpl * f->fmt.pix_mp.height * ++ (nplanes > 1 ? fmt->plane_factor[i] : total_plane_factor); ++ /* ++ * The shift is to divide out the plane_factor fixed point ++ * scaling of 8. ++ */ ++ plane_size = max(p->sizeimage, plane_size >> 3); ++ ++ p->bytesperline = bpl; ++ p->sizeimage = plane_size; ++ } ++} ++ ++static int try_format(struct v4l2_format *f, struct pispbe_node *node) ++{ ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ const struct pisp_be_format *fmt; ++ unsigned int i; ++ bool is_rgb; ++ u32 pixfmt = f->fmt.pix_mp.pixelformat; ++ ++ dev_dbg(pispbe->dev, ++ "%s: [%s] req %ux%u " V4L2_FOURCC_CONV ", planes %d\n", ++ __func__, NODE_NAME(node), f->fmt.pix_mp.width, ++ f->fmt.pix_mp.height, V4L2_FOURCC_CONV_ARGS(pixfmt), ++ f->fmt.pix_mp.num_planes); ++ ++ if (pixfmt == V4L2_PIX_FMT_RPI_BE) ++ return verify_be_pix_format(f, node); ++ ++ fmt = find_format(pixfmt); ++ if (!fmt) ++ fmt = find_format(V4L2_PIX_FMT_YUV420M); ++ ++ f->fmt.pix_mp.pixelformat = fmt->fourcc; ++ f->fmt.pix_mp.num_planes = fmt->num_planes; ++ f->fmt.pix_mp.field = V4L2_FIELD_NONE; ++ f->fmt.pix_mp.width = max(min(f->fmt.pix_mp.width, 65536u), ++ PISP_BACK_END_MIN_TILE_WIDTH); ++ f->fmt.pix_mp.height = max(min(f->fmt.pix_mp.height, 65536u), ++ PISP_BACK_END_MIN_TILE_HEIGHT); ++ ++ /* ++ * Fill in the actual colour space when the requested one was ++ * not supported. This also catches the case when the "default" ++ * colour space was requested (as that's never in the mask). ++ */ ++ if (!(V4L2_COLORSPACE_MASK(f->fmt.pix_mp.colorspace) & fmt->colorspace_mask)) ++ f->fmt.pix_mp.colorspace = fmt->colorspace_default; ++ ++ /* In all cases, we only support the defaults for these: */ ++ f->fmt.pix_mp.ycbcr_enc = ++ V4L2_MAP_YCBCR_ENC_DEFAULT(f->fmt.pix_mp.colorspace); ++ f->fmt.pix_mp.xfer_func = ++ V4L2_MAP_XFER_FUNC_DEFAULT(f->fmt.pix_mp.colorspace); ++ ++ is_rgb = f->fmt.pix_mp.colorspace == V4L2_COLORSPACE_SRGB; ++ f->fmt.pix_mp.quantization = ++ V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb, f->fmt.pix_mp.colorspace, ++ f->fmt.pix_mp.ycbcr_enc); ++ ++ /* Set plane size and bytes/line for each plane. */ ++ set_plane_params(f, fmt); ++ ++ for (i = 0; i < f->fmt.pix_mp.num_planes; i++) { ++ dev_dbg(pispbe->dev, ++ "%s: [%s] calc plane %d, %ux%u, depth %u, bpl %u size %u\n", ++ __func__, NODE_NAME(node), i, f->fmt.pix_mp.width, ++ f->fmt.pix_mp.height, fmt->bit_depth, ++ f->fmt.pix_mp.plane_fmt[i].bytesperline, ++ f->fmt.pix_mp.plane_fmt[i].sizeimage); ++ } ++ ++ return 0; ++} ++ ++static int pispbe_node_try_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ int ret; ++ ++ if (!NODE_IS_CAPTURE(node) || NODE_IS_META(node)) { ++ dev_err(pispbe->dev, ++ "Cannot set capture fmt for output node %s\n", ++ NODE_NAME(node)); ++ return -EINVAL; ++ } ++ ++ ret = try_format(f, node); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int pispbe_node_try_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ int ret; ++ ++ if (!NODE_IS_OUTPUT(node) || NODE_IS_META(node)) { ++ dev_err(pispbe->dev, ++ "Cannot set capture fmt for output node %s\n", ++ NODE_NAME(node)); ++ return -EINVAL; ++ } ++ ++ ret = try_format(f, node); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int pispbe_node_try_fmt_meta_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ ++ if (!NODE_IS_META(node) || NODE_IS_CAPTURE(node)) { ++ dev_err(pispbe->dev, ++ "Cannot set capture fmt for meta output node %s\n", ++ NODE_NAME(node)); ++ return -EINVAL; ++ } ++ ++ f->fmt.meta.dataformat = V4L2_META_FMT_RPI_BE_CFG; ++ f->fmt.meta.buffersize = sizeof(struct pisp_be_tiles_config); ++ ++ return 0; ++} ++ ++static int pispbe_node_try_fmt_meta_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ ++ if (!NODE_IS_META(node) || NODE_IS_OUTPUT(node)) { ++ dev_err(pispbe->dev, ++ "Cannot set capture fmt for meta output node %s\n", ++ NODE_NAME(node)); ++ return -EINVAL; ++ } ++ ++ f->fmt.meta.dataformat = V4L2_PIX_FMT_RPI_BE; ++ if (!f->fmt.meta.buffersize) ++ f->fmt.meta.buffersize = BIT(20); ++ ++ return 0; ++} ++ ++static int pispbe_node_s_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ int ret = pispbe_node_try_fmt_vid_cap(file, priv, f); ++ ++ if (ret < 0) ++ return ret; ++ ++ node->format = *f; ++ node->pisp_format = find_format(f->fmt.pix_mp.pixelformat); ++ ++ dev_dbg(pispbe->dev, ++ "Set capture format for node %s to " V4L2_FOURCC_CONV "\n", ++ NODE_NAME(node), ++ V4L2_FOURCC_CONV_ARGS(f->fmt.pix_mp.pixelformat)); ++ return 0; ++} ++ ++static int pispbe_node_s_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ int ret = pispbe_node_try_fmt_vid_out(file, priv, f); ++ ++ if (ret < 0) ++ return ret; ++ ++ node->format = *f; ++ node->pisp_format = find_format(f->fmt.pix_mp.pixelformat); ++ ++ dev_dbg(pispbe->dev, ++ "Set output format for node %s to " V4L2_FOURCC_CONV "\n", ++ NODE_NAME(node), ++ V4L2_FOURCC_CONV_ARGS(f->fmt.pix_mp.pixelformat)); ++ return 0; ++} ++ ++static int pispbe_node_s_fmt_meta_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ int ret = pispbe_node_try_fmt_meta_out(file, priv, f); ++ ++ if (ret < 0) ++ return ret; ++ ++ node->format = *f; ++ node->pisp_format = &meta_out_supported_formats[0]; ++ ++ dev_dbg(pispbe->dev, ++ "Set output format for meta node %s to " V4L2_FOURCC_CONV "\n", ++ NODE_NAME(node), ++ V4L2_FOURCC_CONV_ARGS(f->fmt.meta.dataformat)); ++ return 0; ++} ++ ++static int pispbe_node_s_fmt_meta_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ int ret = pispbe_node_try_fmt_meta_cap(file, priv, f); ++ ++ if (ret < 0) ++ return ret; ++ ++ node->format = *f; ++ node->pisp_format = find_format(f->fmt.meta.dataformat); ++ ++ dev_dbg(pispbe->dev, ++ "Set capture format for meta node %s to " V4L2_FOURCC_CONV "\n", ++ NODE_NAME(node), ++ V4L2_FOURCC_CONV_ARGS(f->fmt.meta.dataformat)); ++ return 0; ++} ++ ++static int pispbe_node_enum_fmt(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ ++ if (f->type != node->queue.type) ++ return -EINVAL; ++ ++ if (NODE_IS_META(node)) { ++ if (f->index) ++ return -EINVAL; ++ ++ if (NODE_IS_OUTPUT(node)) ++ f->pixelformat = V4L2_META_FMT_RPI_BE_CFG; ++ else ++ f->pixelformat = V4L2_PIX_FMT_RPI_BE; ++ f->flags = 0; ++ return 0; ++ } ++ ++ if (f->index >= ARRAY_SIZE(supported_formats)) ++ return -EINVAL; ++ ++ f->pixelformat = supported_formats[f->index].fourcc; ++ f->flags = 0; ++ ++ return 0; ++} ++ ++static int pispbe_enum_framesizes(struct file *file, void *priv, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ ++ if (NODE_IS_META(node) || fsize->index) ++ return -EINVAL; ++ ++ if (!find_format(fsize->pixel_format)) { ++ dev_err(pispbe->dev, "Invalid pixel code: %x\n", ++ fsize->pixel_format); ++ return -EINVAL; ++ } ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; ++ fsize->stepwise.min_width = 32; ++ fsize->stepwise.max_width = 65535; ++ fsize->stepwise.step_width = 2; ++ ++ fsize->stepwise.min_height = 32; ++ fsize->stepwise.max_height = 65535; ++ fsize->stepwise.step_height = 2; ++ ++ return 0; ++} ++ ++static int pispbe_node_streamon(struct file *file, void *priv, ++ enum v4l2_buf_type type) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ struct pispbe_dev *pispbe = node->node_group->pispbe; ++ ++ /* Do we need a node->stream_lock mutex? */ ++ ++ dev_dbg(pispbe->dev, "Stream on for node %s\n", NODE_NAME(node)); ++ ++ /* Do we care about the type? Each node has only one queue. */ ++ ++ INIT_LIST_HEAD(&node->ready_queue); ++ ++ /* locking should be handled by the queue->lock? */ ++ return vb2_streamon(&node->queue, type); ++} ++ ++static int pispbe_node_streamoff(struct file *file, void *priv, ++ enum v4l2_buf_type type) ++{ ++ struct pispbe_node *node = video_drvdata(file); ++ ++ return vb2_streamoff(&node->queue, type); ++} ++ ++static const struct v4l2_ioctl_ops pispbe_node_ioctl_ops = { ++ .vidioc_querycap = pispbe_node_querycap, ++ .vidioc_g_fmt_vid_cap_mplane = pispbe_node_g_fmt_vid_cap, ++ .vidioc_g_fmt_vid_out_mplane = pispbe_node_g_fmt_vid_out, ++ .vidioc_g_fmt_meta_out = pispbe_node_g_fmt_meta_out, ++ .vidioc_g_fmt_meta_cap = pispbe_node_g_fmt_meta_cap, ++ .vidioc_try_fmt_vid_cap_mplane = pispbe_node_try_fmt_vid_cap, ++ .vidioc_try_fmt_vid_out_mplane = pispbe_node_try_fmt_vid_out, ++ .vidioc_try_fmt_meta_out = pispbe_node_try_fmt_meta_out, ++ .vidioc_try_fmt_meta_cap = pispbe_node_try_fmt_meta_cap, ++ .vidioc_s_fmt_vid_cap_mplane = pispbe_node_s_fmt_vid_cap, ++ .vidioc_s_fmt_vid_out_mplane = pispbe_node_s_fmt_vid_out, ++ .vidioc_s_fmt_meta_out = pispbe_node_s_fmt_meta_out, ++ .vidioc_s_fmt_meta_cap = pispbe_node_s_fmt_meta_cap, ++ .vidioc_enum_fmt_vid_cap = pispbe_node_enum_fmt, ++ .vidioc_enum_fmt_vid_out = pispbe_node_enum_fmt, ++ .vidioc_enum_fmt_meta_cap = pispbe_node_enum_fmt, ++ .vidioc_enum_fmt_meta_out = pispbe_node_enum_fmt, ++ .vidioc_enum_framesizes = pispbe_enum_framesizes, ++ .vidioc_create_bufs = vb2_ioctl_create_bufs, ++ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, ++ .vidioc_querybuf = vb2_ioctl_querybuf, ++ .vidioc_qbuf = vb2_ioctl_qbuf, ++ .vidioc_dqbuf = vb2_ioctl_dqbuf, ++ .vidioc_expbuf = vb2_ioctl_expbuf, ++ .vidioc_reqbufs = vb2_ioctl_reqbufs, ++ .vidioc_streamon = pispbe_node_streamon, ++ .vidioc_streamoff = pispbe_node_streamoff, ++}; ++ ++static const struct video_device pispbe_videodev = { ++ .name = PISPBE_NAME, ++ .vfl_dir = VFL_DIR_M2M, /* gets overwritten */ ++ .fops = &pispbe_fops, ++ .ioctl_ops = &pispbe_node_ioctl_ops, ++ .minor = -1, ++ .release = video_device_release_empty, ++}; ++ ++static void node_set_default_format(struct pispbe_node *node) ++{ ++ if (NODE_IS_META(node) && NODE_IS_OUTPUT(node)) { ++ /* Config node */ ++ struct v4l2_format *f = &node->format; ++ ++ f->fmt.meta.dataformat = V4L2_META_FMT_RPI_BE_CFG; ++ f->fmt.meta.buffersize = sizeof(struct pisp_be_tiles_config); ++ f->type = node->buf_type; ++ } else if (NODE_IS_META(node) && NODE_IS_CAPTURE(node)) { ++ /* HOG output node */ ++ struct v4l2_format *f = &node->format; ++ ++ f->fmt.meta.dataformat = V4L2_PIX_FMT_RPI_BE; ++ f->fmt.meta.buffersize = BIT(20); ++ f->type = node->buf_type; ++ } else { ++ struct v4l2_format f = {0}; ++ ++ f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M; ++ f.fmt.pix_mp.width = 1920; ++ f.fmt.pix_mp.height = 1080; ++ f.type = node->buf_type; ++ try_format(&f, node); ++ node->format = f; ++ } ++ ++ node->pisp_format = find_format(node->format.fmt.pix_mp.pixelformat); ++} ++ ++/* ++ * Initialise a struct pispbe_node and register it as /dev/video ++ * to represent one of the PiSP Back End's input or output streams. ++ */ ++static int ++pispbe_init_node(struct pispbe_node_group *node_group, unsigned int id) ++{ ++ bool output = NODE_DESC_IS_OUTPUT(&node_desc[id]); ++ struct pispbe_node *node = &node_group->node[id]; ++ struct pispbe_dev *pispbe = node_group->pispbe; ++ struct media_entity *entity = &node->vfd.entity; ++ struct video_device *vdev = &node->vfd; ++ struct vb2_queue *q = &node->queue; ++ int ret; ++ ++ node->id = id; ++ node->node_group = node_group; ++ node->buf_type = node_desc[id].buf_type; ++ ++ mutex_init(&node->node_lock); ++ mutex_init(&node->queue_lock); ++ INIT_LIST_HEAD(&node->ready_queue); ++ spin_lock_init(&node->ready_lock); ++ ++ node->format.type = node->buf_type; ++ node_set_default_format(node); ++ ++ q->type = node->buf_type; ++ q->io_modes = VB2_MMAP | VB2_DMABUF; ++ q->mem_ops = &vb2_dma_contig_memops; ++ q->drv_priv = node; ++ q->ops = &pispbe_node_queue_ops; ++ q->buf_struct_size = sizeof(struct pispbe_buffer); ++ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ q->dev = node->node_group->pispbe->dev; ++ /* get V4L2 to handle node->queue locking */ ++ q->lock = &node->queue_lock; ++ ++ ret = vb2_queue_init(q); ++ if (ret < 0) { ++ dev_err(pispbe->dev, "vb2_queue_init failed\n"); ++ return ret; ++ } ++ ++ *vdev = pispbe_videodev; /* default initialization */ ++ strscpy(vdev->name, node_desc[id].ent_name, sizeof(vdev->name)); ++ vdev->v4l2_dev = &node_group->v4l2_dev; ++ vdev->vfl_dir = output ? VFL_DIR_TX : VFL_DIR_RX; ++ /* get V4L2 to serialise our ioctls */ ++ vdev->lock = &node->node_lock; ++ vdev->queue = &node->queue; ++ vdev->device_caps = V4L2_CAP_STREAMING | node_desc[id].caps; ++ ++ node->pad.flags = output ? MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK; ++ ret = media_entity_pads_init(entity, 1, &node->pad); ++ if (ret) { ++ dev_err(pispbe->dev, ++ "Failed to register media pads for %s device node\n", ++ NODE_NAME(node)); ++ goto err_unregister_queue; ++ } ++ ++ ret = video_register_device(vdev, VFL_TYPE_VIDEO, ++ PISPBE_VIDEO_NODE_OFFSET); ++ if (ret) { ++ dev_err(pispbe->dev, ++ "Failed to register video %s device node\n", ++ NODE_NAME(node)); ++ goto err_unregister_queue; ++ } ++ video_set_drvdata(vdev, node); ++ ++ if (output) ++ ret = media_create_pad_link(entity, 0, &node_group->sd.entity, ++ id, MEDIA_LNK_FL_IMMUTABLE | ++ MEDIA_LNK_FL_ENABLED); ++ else ++ ret = media_create_pad_link(&node_group->sd.entity, id, entity, ++ 0, MEDIA_LNK_FL_IMMUTABLE | ++ MEDIA_LNK_FL_ENABLED); ++ if (ret) ++ goto err_unregister_video_dev; ++ ++ dev_info(pispbe->dev, ++ "%s device node registered as /dev/video%d\n", ++ NODE_NAME(node), node->vfd.num); ++ return 0; ++ ++err_unregister_video_dev: ++ video_unregister_device(&node->vfd); ++err_unregister_queue: ++ vb2_queue_release(&node->queue); ++ return ret; ++} ++ ++static const struct v4l2_subdev_pad_ops pispbe_pad_ops = { ++ .link_validate = v4l2_subdev_link_validate_default, ++}; ++ ++static const struct v4l2_subdev_ops pispbe_sd_ops = { ++ .pad = &pispbe_pad_ops, ++}; ++ ++static int pispbe_init_subdev(struct pispbe_node_group *node_group) ++{ ++ struct pispbe_dev *pispbe = node_group->pispbe; ++ struct v4l2_subdev *sd = &node_group->sd; ++ unsigned int i; ++ int ret; ++ ++ v4l2_subdev_init(sd, &pispbe_sd_ops); ++ sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; ++ sd->owner = THIS_MODULE; ++ sd->dev = pispbe->dev; ++ strscpy(sd->name, PISPBE_NAME, sizeof(sd->name)); ++ ++ for (i = 0; i < PISPBE_NUM_NODES; i++) ++ node_group->pad[i].flags = ++ NODE_DESC_IS_OUTPUT(&node_desc[i]) ? ++ MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; ++ ++ ret = media_entity_pads_init(&sd->entity, PISPBE_NUM_NODES, ++ node_group->pad); ++ if (ret) ++ goto error; ++ ++ ret = v4l2_device_register_subdev(&node_group->v4l2_dev, sd); ++ if (ret) ++ goto error; ++ ++ return 0; ++ ++error: ++ media_entity_cleanup(&sd->entity); ++ return ret; ++} ++ ++static int pispbe_init_group(struct pispbe_dev *pispbe, unsigned int id) ++{ ++ struct pispbe_node_group *node_group = &pispbe->node_group[id]; ++ struct v4l2_device *v4l2_dev; ++ struct media_device *mdev; ++ unsigned int num_registered = 0; ++ int ret; ++ ++ node_group->id = id; ++ node_group->pispbe = pispbe; ++ node_group->streaming_map = 0; ++ ++ dev_info(pispbe->dev, "Register nodes for group %u\n", id); ++ ++ /* Register v4l2_device and media_device */ ++ mdev = &node_group->mdev; ++ mdev->hw_revision = node_group->pispbe->hw_version; ++ mdev->dev = node_group->pispbe->dev; ++ strscpy(mdev->model, PISPBE_NAME, sizeof(mdev->model)); ++ snprintf(mdev->bus_info, sizeof(mdev->bus_info), ++ "platform:%s", dev_name(node_group->pispbe->dev)); ++ media_device_init(mdev); ++ ++ v4l2_dev = &node_group->v4l2_dev; ++ v4l2_dev->mdev = &node_group->mdev; ++ strscpy(v4l2_dev->name, PISPBE_NAME, sizeof(v4l2_dev->name)); ++ ++ ret = v4l2_device_register(pispbe->dev, &node_group->v4l2_dev); ++ if (ret) ++ goto err_media_dev_cleanup; ++ ++ /* Register the PISPBE subdevice. */ ++ ret = pispbe_init_subdev(node_group); ++ if (ret) ++ goto err_unregister_v4l2; ++ ++ /* Create device video nodes */ ++ for (; num_registered < PISPBE_NUM_NODES; num_registered++) { ++ ret = pispbe_init_node(node_group, num_registered); ++ if (ret) ++ goto err_unregister_nodes; ++ } ++ ++ ret = media_device_register(mdev); ++ if (ret) ++ goto err_unregister_nodes; ++ ++ node_group->config = ++ dma_alloc_coherent(pispbe->dev, ++ sizeof(struct pisp_be_tiles_config) * ++ PISP_BE_NUM_CONFIG_BUFFERS, ++ &node_group->config_dma_addr, GFP_KERNEL); ++ if (!node_group->config) { ++ dev_err(pispbe->dev, "Unable to allocate cached config buffers.\n"); ++ ret = -ENOMEM; ++ goto err_unregister_mdev; ++ } ++ ++ return 0; ++ ++err_unregister_mdev: ++ media_device_unregister(mdev); ++err_unregister_nodes: ++ while (num_registered-- > 0) { ++ video_unregister_device(&node_group->node[num_registered].vfd); ++ vb2_queue_release(&node_group->node[num_registered].queue); ++ } ++ v4l2_device_unregister_subdev(&node_group->sd); ++ media_entity_cleanup(&node_group->sd.entity); ++err_unregister_v4l2: ++ v4l2_device_unregister(v4l2_dev); ++err_media_dev_cleanup: ++ media_device_cleanup(mdev); ++ return ret; ++} ++ ++static void pispbe_destroy_node_group(struct pispbe_node_group *node_group) ++{ ++ struct pispbe_dev *pispbe = node_group->pispbe; ++ int i; ++ ++ if (node_group->config) { ++ dma_free_coherent(node_group->pispbe->dev, ++ sizeof(struct pisp_be_tiles_config) * ++ PISP_BE_NUM_CONFIG_BUFFERS, ++ node_group->config, ++ node_group->config_dma_addr); ++ } ++ ++ dev_info(pispbe->dev, "Unregister from media controller\n"); ++ ++ v4l2_device_unregister_subdev(&node_group->sd); ++ media_entity_cleanup(&node_group->sd.entity); ++ media_device_unregister(&node_group->mdev); ++ ++ for (i = PISPBE_NUM_NODES - 1; i >= 0; i--) { ++ video_unregister_device(&node_group->node[i].vfd); ++ vb2_queue_release(&node_group->node[i].queue); ++ } ++ ++ media_device_cleanup(&node_group->mdev); ++ v4l2_device_unregister(&node_group->v4l2_dev); ++} ++ ++static int pispbe_runtime_suspend(struct device *dev) ++{ ++ struct pispbe_dev *pispbe = dev_get_drvdata(dev); ++ ++ clk_disable_unprepare(pispbe->clk); ++ ++ return 0; ++} ++ ++static int pispbe_runtime_resume(struct device *dev) ++{ ++ struct pispbe_dev *pispbe = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = clk_prepare_enable(pispbe->clk); ++ if (ret) { ++ dev_err(dev, "Unable to enable clock\n"); ++ return ret; ++ } ++ ++ dev_dbg(dev, "%s: Enabled clock, rate=%lu\n", ++ __func__, clk_get_rate(pispbe->clk)); ++ ++ return 0; ++} ++ ++/* ++ * Probe the ISP-BE hardware block, as a single platform device. ++ * This will instantiate multiple "node groups" each with many device nodes. ++ */ ++static int pispbe_probe(struct platform_device *pdev) ++{ ++ unsigned int num_groups = 0; ++ struct pispbe_dev *pispbe; ++ int ret; ++ ++ pispbe = devm_kzalloc(&pdev->dev, sizeof(*pispbe), GFP_KERNEL); ++ if (!pispbe) ++ return -ENOMEM; ++ ++ dev_set_drvdata(&pdev->dev, pispbe); ++ pispbe->dev = &pdev->dev; ++ platform_set_drvdata(pdev, pispbe); ++ ++ pispbe->be_reg_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(pispbe->be_reg_base)) { ++ dev_err(&pdev->dev, "Failed to get ISP-BE registers address\n"); ++ return PTR_ERR(pispbe->be_reg_base); ++ } ++ ++ pispbe->irq = platform_get_irq(pdev, 0); ++ if (pispbe->irq <= 0) { ++ dev_err(&pdev->dev, "No IRQ resource\n"); ++ return -EINVAL; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, pispbe->irq, pispbe_isr, 0, ++ PISPBE_NAME, pispbe); ++ if (ret) { ++ dev_err(&pdev->dev, "Unable to request interrupt\n"); ++ return ret; ++ } ++ ++ ret = dma_set_mask_and_coherent(pispbe->dev, DMA_BIT_MASK(36)); ++ if (ret) ++ return ret; ++ ++ pispbe->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(pispbe->clk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(pispbe->clk), ++ "Failed to get clock"); ++ ++ /* Hardware initialisation */ ++ pm_runtime_set_autosuspend_delay(pispbe->dev, 200); ++ pm_runtime_use_autosuspend(pispbe->dev); ++ pm_runtime_enable(pispbe->dev); ++ ++ ret = pm_runtime_resume_and_get(pispbe->dev); ++ if (ret) ++ goto pm_runtime_disable_err; ++ ++ pispbe->hw_busy = 0; ++ spin_lock_init(&pispbe->hw_lock); ++ ret = hw_init(pispbe); ++ if (ret) ++ goto pm_runtime_put_err; ++ ++ /* ++ * Initialise and register devices for each node_group, including media ++ * device ++ */ ++ for (num_groups = 0; ++ num_groups < PISPBE_NUM_NODE_GROUPS; ++ num_groups++) { ++ ret = pispbe_init_group(pispbe, num_groups); ++ if (ret) ++ goto disable_nodes_err; ++ } ++ ++ pm_runtime_mark_last_busy(pispbe->dev); ++ pm_runtime_put_autosuspend(pispbe->dev); ++ ++ return 0; ++ ++disable_nodes_err: ++ while (num_groups-- > 0) ++ pispbe_destroy_node_group(&pispbe->node_group[num_groups]); ++pm_runtime_put_err: ++ pm_runtime_put(pispbe->dev); ++pm_runtime_disable_err: ++ pm_runtime_dont_use_autosuspend(pispbe->dev); ++ pm_runtime_disable(pispbe->dev); ++ ++ dev_err(&pdev->dev, "%s: returning %d", __func__, ret); ++ ++ return ret; ++} ++ ++static int pispbe_remove(struct platform_device *pdev) ++{ ++ struct pispbe_dev *pispbe = platform_get_drvdata(pdev); ++ int i; ++ ++ for (i = PISPBE_NUM_NODE_GROUPS - 1; i >= 0; i--) ++ pispbe_destroy_node_group(&pispbe->node_group[i]); ++ ++ pm_runtime_dont_use_autosuspend(pispbe->dev); ++ pm_runtime_disable(pispbe->dev); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops pispbe_pm_ops = { ++ SET_RUNTIME_PM_OPS(pispbe_runtime_suspend, pispbe_runtime_resume, NULL) ++}; ++ ++static const struct of_device_id pispbe_of_match[] = { ++ { ++ .compatible = "raspberrypi,pispbe", ++ }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, pispbe_of_match); ++ ++static struct platform_driver pispbe_pdrv = { ++ .probe = pispbe_probe, ++ .remove = pispbe_remove, ++ .driver = { ++ .name = PISPBE_NAME, ++ .of_match_table = pispbe_of_match, ++ .pm = &pispbe_pm_ops, ++ }, ++}; ++ ++module_platform_driver(pispbe_pdrv); +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h +@@ -0,0 +1,533 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * PiSP Back End configuration definitions. ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd ++ * ++ */ ++#ifndef _PISP_BE_CONFIG_H_ ++#define _PISP_BE_CONFIG_H_ ++ ++#include ++ ++#include ++ ++/* byte alignment for inputs */ ++#define PISP_BACK_END_INPUT_ALIGN 4u ++/* alignment for compressed inputs */ ++#define PISP_BACK_END_COMPRESSED_ALIGN 8u ++/* minimum required byte alignment for outputs */ ++#define PISP_BACK_END_OUTPUT_MIN_ALIGN 16u ++/* preferred byte alignment for outputs */ ++#define PISP_BACK_END_OUTPUT_MAX_ALIGN 64u ++ ++/* minimum allowed tile width anywhere in the pipeline */ ++#define PISP_BACK_END_MIN_TILE_WIDTH 16u ++/* minimum allowed tile width anywhere in the pipeline */ ++#define PISP_BACK_END_MIN_TILE_HEIGHT 16u ++ ++#define PISP_BACK_END_NUM_OUTPUTS 2 ++#define PISP_BACK_END_HOG_OUTPUT 1 ++ ++#define PISP_BACK_END_NUM_TILES 64 ++ ++enum pisp_be_bayer_enable { ++ PISP_BE_BAYER_ENABLE_INPUT = 0x000001, ++ PISP_BE_BAYER_ENABLE_DECOMPRESS = 0x000002, ++ PISP_BE_BAYER_ENABLE_DPC = 0x000004, ++ PISP_BE_BAYER_ENABLE_GEQ = 0x000008, ++ PISP_BE_BAYER_ENABLE_TDN_INPUT = 0x000010, ++ PISP_BE_BAYER_ENABLE_TDN_DECOMPRESS = 0x000020, ++ PISP_BE_BAYER_ENABLE_TDN = 0x000040, ++ PISP_BE_BAYER_ENABLE_TDN_COMPRESS = 0x000080, ++ PISP_BE_BAYER_ENABLE_TDN_OUTPUT = 0x000100, ++ PISP_BE_BAYER_ENABLE_SDN = 0x000200, ++ PISP_BE_BAYER_ENABLE_BLC = 0x000400, ++ PISP_BE_BAYER_ENABLE_STITCH_INPUT = 0x000800, ++ PISP_BE_BAYER_ENABLE_STITCH_DECOMPRESS = 0x001000, ++ PISP_BE_BAYER_ENABLE_STITCH = 0x002000, ++ PISP_BE_BAYER_ENABLE_STITCH_COMPRESS = 0x004000, ++ PISP_BE_BAYER_ENABLE_STITCH_OUTPUT = 0x008000, ++ PISP_BE_BAYER_ENABLE_WBG = 0x010000, ++ PISP_BE_BAYER_ENABLE_CDN = 0x020000, ++ PISP_BE_BAYER_ENABLE_LSC = 0x040000, ++ PISP_BE_BAYER_ENABLE_TONEMAP = 0x080000, ++ PISP_BE_BAYER_ENABLE_CAC = 0x100000, ++ PISP_BE_BAYER_ENABLE_DEBIN = 0x200000, ++ PISP_BE_BAYER_ENABLE_DEMOSAIC = 0x400000, ++}; ++ ++enum pisp_be_rgb_enable { ++ PISP_BE_RGB_ENABLE_INPUT = 0x000001, ++ PISP_BE_RGB_ENABLE_CCM = 0x000002, ++ PISP_BE_RGB_ENABLE_SAT_CONTROL = 0x000004, ++ PISP_BE_RGB_ENABLE_YCBCR = 0x000008, ++ PISP_BE_RGB_ENABLE_FALSE_COLOUR = 0x000010, ++ PISP_BE_RGB_ENABLE_SHARPEN = 0x000020, ++ /* Preferred colours would occupy 0x000040 */ ++ PISP_BE_RGB_ENABLE_YCBCR_INVERSE = 0x000080, ++ PISP_BE_RGB_ENABLE_GAMMA = 0x000100, ++ PISP_BE_RGB_ENABLE_CSC0 = 0x000200, ++ PISP_BE_RGB_ENABLE_CSC1 = 0x000400, ++ PISP_BE_RGB_ENABLE_DOWNSCALE0 = 0x001000, ++ PISP_BE_RGB_ENABLE_DOWNSCALE1 = 0x002000, ++ PISP_BE_RGB_ENABLE_RESAMPLE0 = 0x008000, ++ PISP_BE_RGB_ENABLE_RESAMPLE1 = 0x010000, ++ PISP_BE_RGB_ENABLE_OUTPUT0 = 0x040000, ++ PISP_BE_RGB_ENABLE_OUTPUT1 = 0x080000, ++ PISP_BE_RGB_ENABLE_HOG = 0x200000 ++}; ++ ++#define PISP_BE_RGB_ENABLE_CSC(i) (PISP_BE_RGB_ENABLE_CSC0 << (i)) ++#define PISP_BE_RGB_ENABLE_DOWNSCALE(i) (PISP_BE_RGB_ENABLE_DOWNSCALE0 << (i)) ++#define PISP_BE_RGB_ENABLE_RESAMPLE(i) (PISP_BE_RGB_ENABLE_RESAMPLE0 << (i)) ++#define PISP_BE_RGB_ENABLE_OUTPUT(i) (PISP_BE_RGB_ENABLE_OUTPUT0 << (i)) ++ ++/* ++ * We use the enable flags to show when blocks are "dirty", but we need some ++ * extra ones too. ++ */ ++enum pisp_be_dirty { ++ PISP_BE_DIRTY_GLOBAL = 0x0001, ++ PISP_BE_DIRTY_SH_FC_COMBINE = 0x0002, ++ PISP_BE_DIRTY_CROP = 0x0004 ++}; ++ ++struct pisp_be_global_config { ++ u32 bayer_enables; ++ u32 rgb_enables; ++ u8 bayer_order; ++ u8 pad[3]; ++}; ++ ++struct pisp_be_input_buffer_config { ++ /* low 32 bits followed by high 32 bits (for each of up to 3 planes) */ ++ u32 addr[3][2]; ++}; ++ ++struct pisp_be_dpc_config { ++ u8 coeff_level; ++ u8 coeff_range; ++ u8 pad; ++#define PISP_BE_DPC_FLAG_FOLDBACK 1 ++ u8 flags; ++}; ++ ++struct pisp_be_geq_config { ++ u16 offset; ++#define PISP_BE_GEQ_SHARPER BIT(15) ++#define PISP_BE_GEQ_SLOPE ((1 << 10) - 1) ++ /* top bit is the "sharper" flag, slope value is bottom 10 bits */ ++ u16 slope_sharper; ++ u16 min; ++ u16 max; ++}; ++ ++struct pisp_be_tdn_input_buffer_config { ++ /* low 32 bits followed by high 32 bits */ ++ u32 addr[2]; ++}; ++ ++struct pisp_be_tdn_config { ++ u16 black_level; ++ u16 ratio; ++ u16 noise_constant; ++ u16 noise_slope; ++ u16 threshold; ++ u8 reset; ++ u8 pad; ++}; ++ ++struct pisp_be_tdn_output_buffer_config { ++ /* low 32 bits followed by high 32 bits */ ++ u32 addr[2]; ++}; ++ ++struct pisp_be_sdn_config { ++ u16 black_level; ++ u8 leakage; ++ u8 pad; ++ u16 noise_constant; ++ u16 noise_slope; ++ u16 noise_constant2; ++ u16 noise_slope2; ++}; ++ ++struct pisp_be_stitch_input_buffer_config { ++ /* low 32 bits followed by high 32 bits */ ++ u32 addr[2]; ++}; ++ ++#define PISP_BE_STITCH_STREAMING_LONG 0x8000 ++#define PISP_BE_STITCH_EXPOSURE_RATIO_MASK 0x7fff ++ ++struct pisp_be_stitch_config { ++ u16 threshold_lo; ++ u8 threshold_diff_power; ++ u8 pad; ++ ++ /* top bit indicates whether streaming input is the long exposure */ ++ u16 exposure_ratio; ++ ++ u8 motion_threshold_256; ++ u8 motion_threshold_recip; ++}; ++ ++struct pisp_be_stitch_output_buffer_config { ++ /* low 32 bits followed by high 32 bits */ ++ u32 addr[2]; ++}; ++ ++struct pisp_be_cdn_config { ++ u16 thresh; ++ u8 iir_strength; ++ u8 g_adjust; ++}; ++ ++#define PISP_BE_LSC_LOG_GRID_SIZE 5 ++#define PISP_BE_LSC_GRID_SIZE (1 << PISP_BE_LSC_LOG_GRID_SIZE) ++#define PISP_BE_LSC_STEP_PRECISION 18 ++ ++struct pisp_be_lsc_config { ++ /* (1<<18) / grid_cell_width */ ++ u16 grid_step_x; ++ /* (1<<18) / grid_cell_height */ ++ u16 grid_step_y; ++ /* RGB gains jointly encoded in 32 bits */ ++ u32 lut_packed[PISP_BE_LSC_GRID_SIZE + 1] ++ [PISP_BE_LSC_GRID_SIZE + 1]; ++}; ++ ++struct pisp_be_lsc_extra { ++ u16 offset_x; ++ u16 offset_y; ++}; ++ ++#define PISP_BE_CAC_LOG_GRID_SIZE 3 ++#define PISP_BE_CAC_GRID_SIZE (1 << PISP_BE_CAC_LOG_GRID_SIZE) ++#define PISP_BE_CAC_STEP_PRECISION 20 ++ ++struct pisp_be_cac_config { ++ /* (1<<20) / grid_cell_width */ ++ u16 grid_step_x; ++ /* (1<<20) / grid_cell_height */ ++ u16 grid_step_y; ++ /* [gridy][gridx][rb][xy] */ ++ s8 lut[PISP_BE_CAC_GRID_SIZE + 1][PISP_BE_CAC_GRID_SIZE + 1][2][2]; ++}; ++ ++struct pisp_be_cac_extra { ++ u16 offset_x; ++ u16 offset_y; ++}; ++ ++#define PISP_BE_DEBIN_NUM_COEFFS 4 ++ ++struct pisp_be_debin_config { ++ s8 coeffs[PISP_BE_DEBIN_NUM_COEFFS]; ++ s8 h_enable; ++ s8 v_enable; ++ s8 pad[2]; ++}; ++ ++#define PISP_BE_TONEMAP_LUT_SIZE 64 ++ ++struct pisp_be_tonemap_config { ++ u16 detail_constant; ++ u16 detail_slope; ++ u16 iir_strength; ++ u16 strength; ++ u32 lut[PISP_BE_TONEMAP_LUT_SIZE]; ++}; ++ ++struct pisp_be_demosaic_config { ++ u8 sharper; ++ u8 fc_mode; ++ u8 pad[2]; ++}; ++ ++struct pisp_be_ccm_config { ++ s16 coeffs[9]; ++ u8 pad[2]; ++ s32 offsets[3]; ++}; ++ ++struct pisp_be_sat_control_config { ++ u8 shift_r; ++ u8 shift_g; ++ u8 shift_b; ++ u8 pad; ++}; ++ ++struct pisp_be_false_colour_config { ++ u8 distance; ++ u8 pad[3]; ++}; ++ ++#define PISP_BE_SHARPEN_SIZE 5 ++#define PISP_BE_SHARPEN_FUNC_NUM_POINTS 9 ++ ++struct pisp_be_sharpen_config { ++ s8 kernel0[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; ++ s8 pad0[3]; ++ s8 kernel1[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; ++ s8 pad1[3]; ++ s8 kernel2[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; ++ s8 pad2[3]; ++ s8 kernel3[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; ++ s8 pad3[3]; ++ s8 kernel4[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; ++ s8 pad4[3]; ++ u16 threshold_offset0; ++ u16 threshold_slope0; ++ u16 scale0; ++ u16 pad5; ++ u16 threshold_offset1; ++ u16 threshold_slope1; ++ u16 scale1; ++ u16 pad6; ++ u16 threshold_offset2; ++ u16 threshold_slope2; ++ u16 scale2; ++ u16 pad7; ++ u16 threshold_offset3; ++ u16 threshold_slope3; ++ u16 scale3; ++ u16 pad8; ++ u16 threshold_offset4; ++ u16 threshold_slope4; ++ u16 scale4; ++ u16 pad9; ++ u16 positive_strength; ++ u16 positive_pre_limit; ++ u16 positive_func[PISP_BE_SHARPEN_FUNC_NUM_POINTS]; ++ u16 positive_limit; ++ u16 negative_strength; ++ u16 negative_pre_limit; ++ u16 negative_func[PISP_BE_SHARPEN_FUNC_NUM_POINTS]; ++ u16 negative_limit; ++ u8 enables; ++ u8 white; ++ u8 black; ++ u8 grey; ++}; ++ ++struct pisp_be_sh_fc_combine_config { ++ u8 y_factor; ++ u8 c1_factor; ++ u8 c2_factor; ++ u8 pad; ++}; ++ ++#define PISP_BE_GAMMA_LUT_SIZE 64 ++ ++struct pisp_be_gamma_config { ++ u32 lut[PISP_BE_GAMMA_LUT_SIZE]; ++}; ++ ++struct pisp_be_crop_config { ++ u16 offset_x, offset_y; ++ u16 width, height; ++}; ++ ++#define PISP_BE_RESAMPLE_FILTER_SIZE 96 ++ ++struct pisp_be_resample_config { ++ u16 scale_factor_h, scale_factor_v; ++ s16 coef[PISP_BE_RESAMPLE_FILTER_SIZE]; ++}; ++ ++struct pisp_be_resample_extra { ++ u16 scaled_width; ++ u16 scaled_height; ++ s16 initial_phase_h[3]; ++ s16 initial_phase_v[3]; ++}; ++ ++struct pisp_be_downscale_config { ++ u16 scale_factor_h; ++ u16 scale_factor_v; ++ u16 scale_recip_h; ++ u16 scale_recip_v; ++}; ++ ++struct pisp_be_downscale_extra { ++ u16 scaled_width; ++ u16 scaled_height; ++}; ++ ++struct pisp_be_hog_config { ++ u8 compute_signed; ++ u8 channel_mix[3]; ++ u32 stride; ++}; ++ ++struct pisp_be_axi_config { ++ u8 r_qos; /* Read QoS */ ++ u8 r_cache_prot; /* Read { prot[2:0], cache[3:0] } */ ++ u8 w_qos; /* Write QoS */ ++ u8 w_cache_prot; /* Write { prot[2:0], cache[3:0] } */ ++}; ++ ++enum pisp_be_transform { ++ PISP_BE_TRANSFORM_NONE = 0x0, ++ PISP_BE_TRANSFORM_HFLIP = 0x1, ++ PISP_BE_TRANSFORM_VFLIP = 0x2, ++ PISP_BE_TRANSFORM_ROT180 = ++ (PISP_BE_TRANSFORM_HFLIP | PISP_BE_TRANSFORM_VFLIP) ++}; ++ ++struct pisp_be_output_format_config { ++ struct pisp_image_format_config image; ++ u8 transform; ++ u8 pad[3]; ++ u16 lo; ++ u16 hi; ++ u16 lo2; ++ u16 hi2; ++}; ++ ++struct pisp_be_output_buffer_config { ++ /* low 32 bits followed by high 32 bits (for each of 3 planes) */ ++ u32 addr[3][2]; ++}; ++ ++struct pisp_be_hog_buffer_config { ++ /* low 32 bits followed by high 32 bits */ ++ u32 addr[2]; ++}; ++ ++struct pisp_be_config { ++ /* I/O configuration: */ ++ struct pisp_be_input_buffer_config input_buffer; ++ struct pisp_be_tdn_input_buffer_config tdn_input_buffer; ++ struct pisp_be_stitch_input_buffer_config stitch_input_buffer; ++ struct pisp_be_tdn_output_buffer_config tdn_output_buffer; ++ struct pisp_be_stitch_output_buffer_config stitch_output_buffer; ++ struct pisp_be_output_buffer_config ++ output_buffer[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_hog_buffer_config hog_buffer; ++ /* Processing configuration: */ ++ struct pisp_be_global_config global; ++ struct pisp_image_format_config input_format; ++ struct pisp_decompress_config decompress; ++ struct pisp_be_dpc_config dpc; ++ struct pisp_be_geq_config geq; ++ struct pisp_image_format_config tdn_input_format; ++ struct pisp_decompress_config tdn_decompress; ++ struct pisp_be_tdn_config tdn; ++ struct pisp_compress_config tdn_compress; ++ struct pisp_image_format_config tdn_output_format; ++ struct pisp_be_sdn_config sdn; ++ struct pisp_bla_config blc; ++ struct pisp_compress_config stitch_compress; ++ struct pisp_image_format_config stitch_output_format; ++ struct pisp_image_format_config stitch_input_format; ++ struct pisp_decompress_config stitch_decompress; ++ struct pisp_be_stitch_config stitch; ++ struct pisp_be_lsc_config lsc; ++ struct pisp_wbg_config wbg; ++ struct pisp_be_cdn_config cdn; ++ struct pisp_be_cac_config cac; ++ struct pisp_be_debin_config debin; ++ struct pisp_be_tonemap_config tonemap; ++ struct pisp_be_demosaic_config demosaic; ++ struct pisp_be_ccm_config ccm; ++ struct pisp_be_sat_control_config sat_control; ++ struct pisp_be_ccm_config ycbcr; ++ struct pisp_be_sharpen_config sharpen; ++ struct pisp_be_false_colour_config false_colour; ++ struct pisp_be_sh_fc_combine_config sh_fc_combine; ++ struct pisp_be_ccm_config ycbcr_inverse; ++ struct pisp_be_gamma_config gamma; ++ struct pisp_be_ccm_config csc[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_downscale_config downscale[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_resample_config resample[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_output_format_config ++ output_format[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_hog_config hog; ++ struct pisp_be_axi_config axi; ++ /* Non-register fields: */ ++ struct pisp_be_lsc_extra lsc_extra; ++ struct pisp_be_cac_extra cac_extra; ++ struct pisp_be_downscale_extra ++ downscale_extra[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_resample_extra resample_extra[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_crop_config crop; ++ struct pisp_image_format_config hog_format; ++ u32 dirty_flags_bayer; /* these use pisp_be_bayer_enable */ ++ u32 dirty_flags_rgb; /* use pisp_be_rgb_enable */ ++ u32 dirty_flags_extra; /* these use pisp_be_dirty_t */ ++}; ++ ++/* ++ * We also need a tile structure to describe the size of the tiles going ++ * through the pipeline. ++ */ ++ ++enum pisp_tile_edge { ++ PISP_LEFT_EDGE = (1 << 0), ++ PISP_RIGHT_EDGE = (1 << 1), ++ PISP_TOP_EDGE = (1 << 2), ++ PISP_BOTTOM_EDGE = (1 << 3) ++}; ++ ++struct pisp_tile { ++ u8 edge; // enum pisp_tile_edge ++ u8 pad0[3]; ++ // 4 bytes ++ u32 input_addr_offset; ++ u32 input_addr_offset2; ++ u16 input_offset_x; ++ u16 input_offset_y; ++ u16 input_width; ++ u16 input_height; ++ // 20 bytes ++ u32 tdn_input_addr_offset; ++ u32 tdn_output_addr_offset; ++ u32 stitch_input_addr_offset; ++ u32 stitch_output_addr_offset; ++ // 36 bytes ++ u32 lsc_grid_offset_x; ++ u32 lsc_grid_offset_y; ++ // 44 bytes ++ u32 cac_grid_offset_x; ++ u32 cac_grid_offset_y; ++ // 52 bytes ++ u16 crop_x_start[PISP_BACK_END_NUM_OUTPUTS]; ++ u16 crop_x_end[PISP_BACK_END_NUM_OUTPUTS]; ++ u16 crop_y_start[PISP_BACK_END_NUM_OUTPUTS]; ++ u16 crop_y_end[PISP_BACK_END_NUM_OUTPUTS]; ++ // 68 bytes ++ /* Ordering is planes then branches */ ++ u16 downscale_phase_x[3 * PISP_BACK_END_NUM_OUTPUTS]; ++ u16 downscale_phase_y[3 * PISP_BACK_END_NUM_OUTPUTS]; ++ // 92 bytes ++ u16 resample_in_width[PISP_BACK_END_NUM_OUTPUTS]; ++ u16 resample_in_height[PISP_BACK_END_NUM_OUTPUTS]; ++ // 100 bytes ++ /* Ordering is planes then branches */ ++ u16 resample_phase_x[3 * PISP_BACK_END_NUM_OUTPUTS]; ++ u16 resample_phase_y[3 * PISP_BACK_END_NUM_OUTPUTS]; ++ // 124 bytes ++ u16 output_offset_x[PISP_BACK_END_NUM_OUTPUTS]; ++ u16 output_offset_y[PISP_BACK_END_NUM_OUTPUTS]; ++ u16 output_width[PISP_BACK_END_NUM_OUTPUTS]; ++ u16 output_height[PISP_BACK_END_NUM_OUTPUTS]; ++ // 140 bytes ++ u32 output_addr_offset[PISP_BACK_END_NUM_OUTPUTS]; ++ u32 output_addr_offset2[PISP_BACK_END_NUM_OUTPUTS]; ++ // 156 bytes ++ u32 output_hog_addr_offset; ++ // 160 bytes ++}; ++ ++static_assert(sizeof(struct pisp_tile) == 160); ++ ++struct pisp_be_tiles_config { ++ struct pisp_be_config config; ++ struct pisp_tile tiles[PISP_BACK_END_NUM_TILES]; ++ int num_tiles; ++}; ++ ++#endif /* _PISP_BE_CONFIG_H_ */ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h +@@ -0,0 +1,469 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * PiSP Back End driver image format definitions. ++ * ++ * Copyright (c) 2021 Raspberry Pi Ltd ++ */ ++ ++#ifndef _PISP_BE_FORMATS_ ++#define _PISP_BE_FORMATS_ ++ ++#include ++#include ++ ++#define MAX_PLANES 3 ++#define P3(x) ((x) * 8) ++ ++struct pisp_be_format { ++ unsigned int fourcc; ++ unsigned int align; ++ unsigned int bit_depth; ++ /* 0P3 factor for plane sizing */ ++ unsigned int plane_factor[MAX_PLANES]; ++ unsigned int num_planes; ++ unsigned int colorspace_mask; ++ enum v4l2_colorspace colorspace_default; ++}; ++ ++#define V4L2_COLORSPACE_MASK(colorspace) BIT(colorspace) ++ ++#define V4L2_COLORSPACE_MASK_JPEG V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_JPEG) ++#define V4L2_COLORSPACE_MASK_SMPTE170M V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_SMPTE170M) ++#define V4L2_COLORSPACE_MASK_REC709 V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_REC709) ++#define V4L2_COLORSPACE_MASK_SRGB V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_SRGB) ++#define V4L2_COLORSPACE_MASK_RAW V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_RAW) ++ ++/* ++ * All three colour spaces JPEG, SMPTE170M and REC709 are fundamentally sRGB ++ * underneath (as near as makes no difference to us), just with different YCbCr ++ * encodings. Therefore the ISP can generate sRGB on its main output and any of ++ * the others on its low resolution output. Applications should, when using both ++ * outputs, program the colour spaces on them to be the same, matching whatever ++ * is requested for the low resolution output, even if the main output is ++ * producing an RGB format. In turn this requires us to allow all these colour ++ * spaces for every YUV/RGB output format. ++ */ ++#define V4L2_COLORSPACE_MASK_ALL_SRGB (V4L2_COLORSPACE_MASK_JPEG | \ ++ V4L2_COLORSPACE_MASK_SRGB | \ ++ V4L2_COLORSPACE_MASK_SMPTE170M | \ ++ V4L2_COLORSPACE_MASK_REC709) ++ ++static const struct pisp_be_format supported_formats[] = { ++ /* Single plane YUV formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_YUV420, ++ /* 128 alignment to ensure U/V planes are 64 byte aligned. */ ++ .align = 128, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.25), P3(0.25) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_JPEG, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVU420, ++ /* 128 alignment to ensure U/V planes are 64 byte aligned. */ ++ .align = 128, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.25), P3(0.25) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_NV12, ++ .align = 32, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.5) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_NV21, ++ .align = 32, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.5) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .align = 64, ++ .bit_depth = 16, ++ .plane_factor = { P3(1) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_UYVY, ++ .align = 64, ++ .bit_depth = 16, ++ .plane_factor = { P3(1) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVYU, ++ .align = 64, ++ .bit_depth = 16, ++ .plane_factor = { P3(1) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_VYUY, ++ .align = 64, ++ .bit_depth = 16, ++ .plane_factor = { P3(1) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ /* Multiplane YUV formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_YUV420M, ++ .align = 64, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.25), P3(0.25) }, ++ .num_planes = 3, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_JPEG, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_NV12M, ++ .align = 32, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.5) }, ++ .num_planes = 2, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_NV21M, ++ .align = 32, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.5) }, ++ .num_planes = 2, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVU420M, ++ .align = 64, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.25), P3(0.25) }, ++ .num_planes = 3, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YUV422M, ++ .align = 64, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.5), P3(0.5) }, ++ .num_planes = 3, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_JPEG, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVU422M, ++ .align = 64, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(0.5), P3(0.5) }, ++ .num_planes = 3, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YUV444M, ++ .align = 64, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(1), P3(1) }, ++ .num_planes = 3, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_JPEG, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVU444M, ++ .align = 64, ++ .bit_depth = 8, ++ .plane_factor = { P3(1), P3(1), P3(1) }, ++ .num_planes = 3, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, ++ }, ++ /* RGB formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_RGB24, ++ .align = 32, ++ .bit_depth = 24, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_BGR24, ++ .align = 32, ++ .bit_depth = 24, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_XBGR32, ++ .align = 64, ++ .bit_depth = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGBX32, ++ .align = 64, ++ .bit_depth = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, ++ /* Bayer formats - 8-bit */ ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB8, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR8, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG8, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG8, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ /* Bayer formats - 16-bit */ ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB16, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR16, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG16, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG16, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ /* Bayer formats unpacked to 16bpp */ ++ /* 10 bit */ ++ .fourcc = V4L2_PIX_FMT_SRGGB10, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR10, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG10, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG10, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ /* 12 bit */ ++ .fourcc = V4L2_PIX_FMT_SRGGB12, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR12, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG12, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG12, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ /* 14 bit */ ++ .fourcc = V4L2_PIX_FMT_SRGGB14, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR14, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG14, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG14, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ /* Bayer formats - 16-bit PiSP Compressed */ ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_BGGR, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_RGGB, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_GRBG, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_GBRG, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++}; ++ ++static const struct pisp_be_format meta_out_supported_formats[] = { ++ /* Configuration buffer format. */ ++ { ++ .fourcc = V4L2_META_FMT_RPI_BE_CFG, ++ }, ++}; ++ ++#endif /* _PISP_BE_FORMATS_ */ +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1452,6 +1452,7 @@ 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; + + default: + /* Compressed formats */ +@@ -1503,6 +1504,7 @@ static void v4l_fill_fmtdesc(struct v4l2 + case V4L2_PIX_FMT_MT21C: descr = "Mediatek Compressed Format"; break; + 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; + default: + if (fmt->description[0]) + return; +--- /dev/null ++++ b/include/media/raspberrypi/pisp_common.h +@@ -0,0 +1,65 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Raspberry Pi PiSP common configuration definitions. ++ * ++ * Copyright (C) 2021 - Raspberry Pi (Trading) Ltd. ++ * ++ */ ++#ifndef _PISP_COMMON_H_ ++#define _PISP_COMMON_H_ ++ ++#include ++ ++#include "pisp_types.h" ++ ++struct pisp_bla_config { ++ uint16_t black_level_r; ++ uint16_t black_level_gr; ++ uint16_t black_level_gb; ++ uint16_t black_level_b; ++ uint16_t output_black_level; ++ uint8_t pad[2]; ++}; ++ ++struct pisp_wbg_config { ++ uint16_t gain_r; ++ uint16_t gain_g; ++ uint16_t gain_b; ++ uint8_t pad[2]; ++}; ++ ++struct pisp_compress_config { ++ /* value subtracted from incoming data */ ++ uint16_t offset; ++ uint8_t pad; ++ /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */ ++ uint8_t mode; ++}; ++ ++struct pisp_decompress_config { ++ /* value added to reconstructed data */ ++ uint16_t offset; ++ uint8_t pad; ++ /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */ ++ uint8_t mode; ++}; ++ ++enum pisp_axi_flags { ++ /* round down bursts to end at a 32-byte boundary, to align following bursts */ ++ PISP_AXI_FLAG_ALIGN = 128, ++ /* for FE writer: force WSTRB high, to pad output to 16-byte boundary */ ++ PISP_AXI_FLAG_PAD = 64, ++ /* for FE writer: Use Output FIFO level to trigger "panic" */ ++ PISP_AXI_FLAG_PANIC = 32 ++}; ++ ++struct pisp_axi_config { ++ /* burst length minus one, which must be in the range 0:15; OR'd with flags */ ++ uint8_t maxlen_flags; ++ /* { prot[2:0], cache[3:0] } fields, echoed on AXI bus */ ++ uint8_t cache_prot; ++ /* QoS field(s) (4x4 bits for FE writer; 4 bits for other masters) */ ++ uint16_t qos; ++}; ++ ++#endif /* _PISP_COMMON_H_ */ +--- /dev/null ++++ b/include/media/raspberrypi/pisp_types.h +@@ -0,0 +1,144 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Raspberry Pi PiSP common types. ++ * ++ * Copyright (C) 2021 - Raspberry Pi (Trading) Ltd. ++ * ++ */ ++#ifndef _PISP_TYPES_H_ ++#define _PISP_TYPES_H_ ++ ++/* This definition must match the format description in the hardware exactly! */ ++struct pisp_image_format_config { ++ /* size in pixels */ ++ uint16_t width, height; ++ /* must match struct pisp_image_format below */ ++ uint32_t format; ++ int32_t stride; ++ /* some planar image formats will need a second stride */ ++ int32_t stride2; ++}; ++ ++static_assert(sizeof(struct pisp_image_format_config) == 16); ++ ++enum pisp_bayer_order { ++ /* ++ * Note how bayer_order&1 tells you if G is on the even pixels of the ++ * checkerboard or not, and bayer_order&2 tells you if R is on the even ++ * rows or is swapped with B. Note that if the top (of the 8) bits is ++ * set, this denotes a monochrome or greyscale image, and the lower bits ++ * should all be ignored. ++ */ ++ PISP_BAYER_ORDER_RGGB = 0, ++ PISP_BAYER_ORDER_GBRG = 1, ++ PISP_BAYER_ORDER_BGGR = 2, ++ PISP_BAYER_ORDER_GRBG = 3, ++ PISP_BAYER_ORDER_GREYSCALE = 128 ++}; ++ ++enum pisp_image_format { ++ /* ++ * Precise values are mostly tbd. Generally these will be portmanteau ++ * values comprising bit fields and flags. This format must be shared ++ * throughout the PiSP. ++ */ ++ PISP_IMAGE_FORMAT_BPS_8 = 0x00000000, ++ PISP_IMAGE_FORMAT_BPS_10 = 0x00000001, ++ PISP_IMAGE_FORMAT_BPS_12 = 0x00000002, ++ PISP_IMAGE_FORMAT_BPS_16 = 0x00000003, ++ PISP_IMAGE_FORMAT_BPS_MASK = 0x00000003, ++ ++ PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED = 0x00000000, ++ PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR = 0x00000010, ++ PISP_IMAGE_FORMAT_PLANARITY_PLANAR = 0x00000020, ++ PISP_IMAGE_FORMAT_PLANARITY_MASK = 0x00000030, ++ ++ PISP_IMAGE_FORMAT_SAMPLING_444 = 0x00000000, ++ PISP_IMAGE_FORMAT_SAMPLING_422 = 0x00000100, ++ PISP_IMAGE_FORMAT_SAMPLING_420 = 0x00000200, ++ PISP_IMAGE_FORMAT_SAMPLING_MASK = 0x00000300, ++ ++ PISP_IMAGE_FORMAT_ORDER_NORMAL = 0x00000000, ++ PISP_IMAGE_FORMAT_ORDER_SWAPPED = 0x00001000, ++ ++ PISP_IMAGE_FORMAT_SHIFT_0 = 0x00000000, ++ PISP_IMAGE_FORMAT_SHIFT_1 = 0x00010000, ++ PISP_IMAGE_FORMAT_SHIFT_2 = 0x00020000, ++ PISP_IMAGE_FORMAT_SHIFT_3 = 0x00030000, ++ PISP_IMAGE_FORMAT_SHIFT_4 = 0x00040000, ++ PISP_IMAGE_FORMAT_SHIFT_5 = 0x00050000, ++ PISP_IMAGE_FORMAT_SHIFT_6 = 0x00060000, ++ PISP_IMAGE_FORMAT_SHIFT_7 = 0x00070000, ++ PISP_IMAGE_FORMAT_SHIFT_8 = 0x00080000, ++ PISP_IMAGE_FORMAT_SHIFT_MASK = 0x000f0000, ++ ++ PISP_IMAGE_FORMAT_UNCOMPRESSED = 0x00000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MODE_1 = 0x01000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MODE_2 = 0x02000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MODE_3 = 0x03000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MASK = 0x03000000, ++ ++ PISP_IMAGE_FORMAT_HOG_SIGNED = 0x04000000, ++ PISP_IMAGE_FORMAT_HOG_UNSIGNED = 0x08000000, ++ PISP_IMAGE_FORMAT_INTEGRAL_IMAGE = 0x10000000, ++ PISP_IMAGE_FORMAT_WALLPAPER_ROLL = 0x20000000, ++ PISP_IMAGE_FORMAT_THREE_CHANNEL = 0x40000000, ++ ++ /* Lastly a few specific instantiations of the above. */ ++ PISP_IMAGE_FORMAT_SINGLE_16 = PISP_IMAGE_FORMAT_BPS_16, ++ PISP_IMAGE_FORMAT_THREE_16 = ++ PISP_IMAGE_FORMAT_BPS_16 | PISP_IMAGE_FORMAT_THREE_CHANNEL ++}; ++ ++#define PISP_IMAGE_FORMAT_bps_8(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_8) ++#define PISP_IMAGE_FORMAT_bps_10(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_10) ++#define PISP_IMAGE_FORMAT_bps_12(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_12) ++#define PISP_IMAGE_FORMAT_bps_16(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_16) ++#define PISP_IMAGE_FORMAT_bps(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_BPS_MASK) ? \ ++ 8 + (2 << (((fmt)&PISP_IMAGE_FORMAT_BPS_MASK) - 1)) : \ ++ 8) ++#define PISP_IMAGE_FORMAT_shift(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_SHIFT_MASK) / PISP_IMAGE_FORMAT_SHIFT_1) ++#define PISP_IMAGE_FORMAT_three_channel(fmt) \ ++ ((fmt)&PISP_IMAGE_FORMAT_THREE_CHANNEL) ++#define PISP_IMAGE_FORMAT_single_channel(fmt) \ ++ (!((fmt)&PISP_IMAGE_FORMAT_THREE_CHANNEL)) ++#define PISP_IMAGE_FORMAT_compressed(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_COMPRESSION_MASK) != \ ++ PISP_IMAGE_FORMAT_UNCOMPRESSED) ++#define PISP_IMAGE_FORMAT_sampling_444(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ ++ PISP_IMAGE_FORMAT_SAMPLING_444) ++#define PISP_IMAGE_FORMAT_sampling_422(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ ++ PISP_IMAGE_FORMAT_SAMPLING_422) ++#define PISP_IMAGE_FORMAT_sampling_420(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ ++ PISP_IMAGE_FORMAT_SAMPLING_420) ++#define PISP_IMAGE_FORMAT_order_normal(fmt) \ ++ (!((fmt)&PISP_IMAGE_FORMAT_ORDER_SWAPPED)) ++#define PISP_IMAGE_FORMAT_order_swapped(fmt) \ ++ ((fmt)&PISP_IMAGE_FORMAT_ORDER_SWAPPED) ++#define PISP_IMAGE_FORMAT_interleaved(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ ++ PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED) ++#define PISP_IMAGE_FORMAT_semiplanar(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ ++ PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR) ++#define PISP_IMAGE_FORMAT_planar(fmt) \ ++ (((fmt)&PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ ++ PISP_IMAGE_FORMAT_PLANARITY_PLANAR) ++#define PISP_IMAGE_FORMAT_wallpaper(fmt) \ ++ ((fmt)&PISP_IMAGE_FORMAT_WALLPAPER_ROLL) ++#define PISP_IMAGE_FORMAT_HOG(fmt) \ ++ ((fmt) & \ ++ (PISP_IMAGE_FORMAT_HOG_SIGNED | PISP_IMAGE_FORMAT_HOG_UNSIGNED)) ++ ++#define PISP_WALLPAPER_WIDTH 128 // in bytes ++ ++#endif /* _PISP_TYPES_H_ */ +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -793,6 +793,9 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_IPU3_SGRBG10 v4l2_fourcc('i', 'p', '3', 'G') /* IPU3 packed 10-bit GRBG bayer */ + #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') ++ + /* SDR formats - used only for Software Defined Radio devices */ + #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ + #define V4L2_SDR_FMT_CU16LE v4l2_fourcc('C', 'U', '1', '6') /* IQ u16le */ +@@ -822,6 +825,9 @@ struct v4l2_pix_format { + #define V4L2_META_FMT_RK_ISP1_PARAMS v4l2_fourcc('R', 'K', '1', 'P') /* Rockchip ISP1 3A Parameters */ + #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. */ ++#define V4L2_META_FMT_RPI_BE_CFG v4l2_fourcc('R', 'P', 'B', 'C') ++ + /* priv field value to indicates that subsequent fields are valid. */ + #define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe + diff --git a/target/linux/bcm27xx/patches-6.1/950-0862-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch b/target/linux/bcm27xx/patches-6.1/950-0862-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch new file mode 100644 index 0000000000..022a94af1c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0862-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch @@ -0,0 +1,386 @@ +From 89b748416358e4e04765b9a4f20e1c3d256b9d9e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 + +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 +--- + 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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); diff --git a/target/linux/bcm27xx/patches-6.1/950-0863-reset-reset-brcmstb-rescal-Support-shared-use.patch b/target/linux/bcm27xx/patches-6.1/950-0863-reset-reset-brcmstb-rescal-Support-shared-use.patch new file mode 100644 index 0000000000..a4328e5bc7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0863-reset-reset-brcmstb-rescal-Support-shared-use.patch @@ -0,0 +1,47 @@ +From 87b1126181f79fb2558652af0d7fafd9deaab5f3 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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) diff --git a/target/linux/bcm27xx/patches-6.1/950-0864-net-macb-Also-set-DMA-coherent-mask.patch b/target/linux/bcm27xx/patches-6.1/950-0864-net-macb-Also-set-DMA-coherent-mask.patch new file mode 100644 index 0000000000..88d92fbb20 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0864-net-macb-Also-set-DMA-coherent-mask.patch @@ -0,0 +1,418 @@ +From bd36586dd9e05bde8e23dc3d99771269b48b65f8 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 + +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 + +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 + +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 + +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 + +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 + +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 +--- + 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 + #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), diff --git a/target/linux/bcm27xx/patches-6.1/950-0865-usb-dwc3-Set-DMA-and-coherent-masks-early.patch b/target/linux/bcm27xx/patches-6.1/950-0865-usb-dwc3-Set-DMA-and-coherent-masks-early.patch new file mode 100644 index 0000000000..f6944e226f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0865-usb-dwc3-Set-DMA-and-coherent-masks-early.patch @@ -0,0 +1,384 @@ +From 4ffa5f2c5fc7854683964bb2f2bf23907c18213f Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +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 + +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 + +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 + +drivers: usb: dwc3: remove downstream quirk dis-in-autoretry + +Upstream have unilaterally disabled the feature. + +Partially reverts 6e9142a26ee0fdc3a5adc49ed6cedc0b16ec2ed1 (downstream) + +Signed-off-by: Jonathan Bell +--- + 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; diff --git a/target/linux/bcm27xx/patches-6.1/950-0866-drm-panel-raspberrypi-touchscreen-Insert-more-delays.patch b/target/linux/bcm27xx/patches-6.1/950-0866-drm-panel-raspberrypi-touchscreen-Insert-more-delays.patch new file mode 100644 index 0000000000..a6f0c1961c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0866-drm-panel-raspberrypi-touchscreen-Insert-more-delays.patch @@ -0,0 +1,37 @@ +From 480c8e9f48f8a96c457eb3dc0079a73598fb7477 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +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); diff --git a/target/linux/bcm27xx/patches-6.1/950-0867-PCI-brcmstb-Add-BCM2712-support.patch b/target/linux/bcm27xx/patches-6.1/950-0867-PCI-brcmstb-Add-BCM2712-support.patch new file mode 100644 index 0000000000..179d03733e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0867-PCI-brcmstb-Add-BCM2712-support.patch @@ -0,0 +1,1108 @@ +From 29702857d1ab71243ea6c247dfe9b5bc43dd422f Mon Sep 17 00:00:00 2001 +From: Jim Quinlan +Date: Fri, 23 Jun 2023 10:40:57 -0400 +Subject: [PATCH] PCI: brcmstb: Add BCM2712 support + +PCI: brcmstb: differing register offsets on 2712 + +pcie-brcmstb: Add 2712 bridge reset support + +pcie: 2712 PORT_MASK and rescal support + +pcie-brcmstb: don't alter the L1SS debug register + +For reasons unknown, this disables the reference clock + +pcie-brcmstb: fix BAR2 enable and window decode + +Set UBUS ACCESS_EN to let inbound DMA work. Also BCM2712 has grown +an index in the inbound window size decode register. + +PCIe: brcmstb: Enable support for 64 MSI-Xs + +Signed-off-by: Phil Elwell + +pcie-brcmstb: Suppress read error responses + +If the link is down or the EP fails to return a read completion, the +RC's default behaviour is to return an AXI error. This causes fatal +exceptions on A76, so it's better to respond with all 1s instead. + +pcie-brcmstb: increase UBUS timeout to cater for link retrain events + +pcie-brcmstb: Handle additional inbound regions + +Signed-off-by: Phil Elwell + +pcie-brcmstb: Add support for external MSI controller + +pcie-brcmstb: add a reasonable default traffic class to priority map + +BCM2712 supports multiple traffic classes (TCs) with independent +maximally sized transfer queues for each TC. Traffic classes have no +transaction ordering requirements between them, which facilitates +out-of-order completions and arbitration between posted writes for +data streams that have no dependence on each other. + +In addition to the above benefits of splitting endpoint traffic into +individual queues, priorities can be assigned to traffic classes by +a heuristic or deterministic mechanism. The heuristic elevates AXI +QOS priority in accordance with the number of pending transfers in +each TC's queue, but for true priority signalling a forwarding +mechanism using vendor-defined messages is implemented. + +Receipt of a 3 DWORD VDM assigns a priority tag to a TC on-the-fly, +and this tag corresponds to a configurable AXI QOS value. + +As a simple baseline, assign a linear map of AXI QOS to each tag. + +pcie: brcmstb: set up the VDM forwarding interface when setting up QoS + +pcie-brcmstb: add DT bindings for MPS-size Read Completion Mode + +This controller has an optional feature that allows read completion +TLPs to be sized up to the Maximum Packet Size of a configured link. + +This can exceed the Read Completion Boundary of 128B specified in +the PCIe specification, but depending on endpoint support may increase +link read bandwidth significantly. + +pcie-brcmstb: clean up debug messages + +pcie-brcmstb: fix BCM2712A0 PHY PM errata + +The power management clock is 54MHz not 50MHz, so adjust the PM clock period +to suit. Powering off the PHY PLL in L1.2 is unsafe, so force it on. + +pcie-brcmstb: set CLKREQ functionality according to link partner support + +The RC supports either L1 with clock PM or L1 sub-state control, not both +at the same time. Examine the link partner's capabilities to determine +which is the most suitable scheme to use. + +pcie: brcmstb: don't reset block bridges in suspend or removal cases + +BCM2712 has a single rescal block for all three root complexes, and +holding PCIE1's bridge in reset will hang the chip if a different +RC wants to access any of the rescal registers. + +pcie: brcmstb: guard 2712-specific setup with a RC type check + +BCM2711 doesn't implement the UBUS control registers. + +pcie: brcmstb: On 2712 keeping the PLL powered in L1.x is not required + +A separate misconfiguration when enabling SSC (the MDIO registers no +longer do the same thing on BCM2712) had the side-effect of breaking +PLL powerdown and resume sequencing. + +Allow entry into a true L1.2 state where analogue is depowered. + +pcie: brcmstb: Fix reset warning on probe failure + +Signed-off-by: Phil Elwell + +bcm2712: pcie: adjust PHY PLL setup to use a 54MHz input refclk + +Use canned MDIO writes from Broadcom that switch the ref_clk output +pair to run from the internal fractional PLL, and set the internal PLL +to expect a 54MHz input reference clock. + +Gen3 operation is not guaranteed to be stable in this setup, so default +to gen2. + +This only works if the LCPLL is bypassed (requires latest bootloader). + +pcie: brcmstb: add missing register writes + +drivers: pcie: brcmstb: cater for BCM2712C0 bug dropping QoS on the floor + +The AXI QoS value extracted from the request fifo ends up as zero forever. +Disabling this means that "panic" signalling doesn't do anything useful, +but static priorites do work. + +Also align the selected TC:QoS map with RP1's expectations of service. + +Signed-off-by: Jonathan Bell + +drivers: pcie: brcmstb: shuffle TC priorities up to 8 + +Use the range 8-11 which puts the highest below HVS but leaves space +below for other 2712 masters. + +Signed-off-by: Jonathan Bell + +drivers: pcie: brcmstb: optionally enable QoS features by DT for BCM2712 + +It's a bad idea to universally enable "realtime" priorities for TCs +across all the RC instances on the chip. Endpoints other than RP1 may +make use of these, so you don't want e.g. NVMe descriptor fetches getting +higher priority than your remote display. + +Add two optional DT properties controlling the behaviour - FIFO-based +backpressure QoS or "message-based". Message-based signalling is +fundamentally broken due to a chip bug, so it collapses into a set of +static assignments that RP1 needs. + +The default if neither property is specified is to assign everything a +QoS of 0. + +Signed-off-by: Jonathan Bell + +drivers: pcie: brcmstb: adjust completion timeouts for bcm2712 + +Setting the RC config retry timeout makes CRS auto-polling work, but +the UBUS timeout will override the config retry. Both need to be large. + +Signed-off-by: Jonathan Bell +--- + drivers/pci/controller/pcie-brcmstb.c | 507 +++++++++++++++++++++++--- + 1 file changed, 458 insertions(+), 49 deletions(-) + +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -47,11 +48,25 @@ + #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc + #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00 + ++#define PCIE_RC_TL_VDM_CTL0 0x0a20 ++#define PCIE_RC_TL_VDM_CTL0_VDM_ENABLED_MASK 0x10000 ++#define PCIE_RC_TL_VDM_CTL0_VDM_IGNORETAG_MASK 0x20000 ++#define PCIE_RC_TL_VDM_CTL0_VDM_IGNOREVNDRID_MASK 0x40000 ++ ++#define PCIE_RC_TL_VDM_CTL1 0x0a0c ++#define PCIE_RC_TL_VDM_CTL1_VDM_VNDRID0_MASK 0x0000ffff ++#define PCIE_RC_TL_VDM_CTL1_VDM_VNDRID1_MASK 0xffff0000 ++ + #define PCIE_RC_DL_MDIO_ADDR 0x1100 + #define PCIE_RC_DL_MDIO_WR_DATA 0x1104 + #define PCIE_RC_DL_MDIO_RD_DATA 0x1108 + ++#define PCIE_RC_PL_PHY_CTL_15 0x184c ++#define PCIE_RC_PL_PHY_CTL_15_DIS_PLL_PD_MASK 0x400000 ++#define PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK 0xff ++ + #define PCIE_MISC_MISC_CTRL 0x4008 ++#define PCIE_MISC_MISC_CTRL_RCB_MPS_MODE_MASK 0x400 + #define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000 + #define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000 + #define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000 +@@ -71,6 +86,7 @@ + + #define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c + #define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f ++#define PCIE_MISC_RC_BAR1_CONFIG_HI 0x4030 + + #define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034 + #define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f +@@ -78,6 +94,7 @@ + + #define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c + #define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f ++#define PCIE_MISC_RC_BAR3_CONFIG_HI 0x4040 + + #define PCIE_MISC_MSI_BAR_CONFIG_LO 0x4044 + #define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048 +@@ -86,12 +103,15 @@ + #define PCIE_MISC_MSI_DATA_CONFIG_VAL_32 0xffe06540 + #define PCIE_MISC_MSI_DATA_CONFIG_VAL_8 0xfff86540 + ++#define PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT 0x405c ++ + #define PCIE_MISC_PCIE_CTRL 0x4064 + #define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1 + #define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK 0x4 + + #define PCIE_MISC_PCIE_STATUS 0x4068 + #define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK 0x80 ++#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK_2712 0x40 + #define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK 0x20 + #define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK 0x10 + #define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK 0x40 +@@ -116,14 +136,73 @@ + #define PCIE_MEM_WIN0_LIMIT_HI(win) \ + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8) + +-#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204 ++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG pcie->reg_offsets[PCIE_HARD_DEBUG] + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2 + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000 + #define PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x00800000 + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK 0x00200000 + ++#define PCIE_MISC_CTRL_1 0x40A0 ++#define PCIE_MISC_CTRL_1_OUTBOUND_TC_MASK 0xf ++#define PCIE_MISC_CTRL_1_OUTBOUND_NO_SNOOP_MASK BIT(3) ++#define PCIE_MISC_CTRL_1_OUTBOUND_RO_MASK BIT(4) ++#define PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK BIT(5) ++ ++#define PCIE_MISC_UBUS_CTRL 0x40a4 ++#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK BIT(13) ++#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK BIT(19) ++ ++#define PCIE_MISC_UBUS_TIMEOUT 0x40A8 ++ ++#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP 0x40ac ++#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_ACCESS_ENABLE_MASK BIT(0) ++#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_HI 0x40b0 ++ ++#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP 0x40b4 ++#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK BIT(0) ++ ++/* Additional RC BARs */ ++#define PCIE_MISC_RC_BAR_CONFIG_LO_SIZE_MASK 0x1f ++#define PCIE_MISC_RC_BAR4_CONFIG_LO 0x40d4 ++#define PCIE_MISC_RC_BAR4_CONFIG_HI 0x40d8 ++/* ... */ ++#define PCIE_MISC_RC_BAR10_CONFIG_LO 0x4104 ++#define PCIE_MISC_RC_BAR10_CONFIG_HI 0x4108 ++ ++#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_ENABLE 0x1 ++#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_LO_MASK 0xfffff000 ++#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_HI_MASK 0xff ++#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_LO 0x410c ++#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_HI 0x4110 ++/* ... */ ++#define PCIE_MISC_UBUS_BAR10_CONFIG_REMAP_LO 0x413c ++#define PCIE_MISC_UBUS_BAR10_CONFIG_REMAP_HI 0x4140 ++ ++/* AXI priority forwarding - automatic level-based */ ++#define PCIE_MISC_TC_QUEUE_TO_QOS_MAP(x) (0x4160 - (x) * 4) ++/* Defined in quarter-fullness */ ++#define QUEUE_THRESHOLD_34_TO_QOS_MAP_SHIFT 12 ++#define QUEUE_THRESHOLD_23_TO_QOS_MAP_SHIFT 8 ++#define QUEUE_THRESHOLD_12_TO_QOS_MAP_SHIFT 4 ++#define QUEUE_THRESHOLD_01_TO_QOS_MAP_SHIFT 0 ++#define QUEUE_THRESHOLD_MASK 0xf ++ ++/* VDM messages indexing TCs to AXI priorities */ ++/* Indexes 8-15 */ ++#define PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_HI 0x4164 ++/* Indexes 0-7 */ ++#define PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_LO 0x4168 ++#define VDM_PRIORITY_TO_QOS_MAP_SHIFT(x) (4 * (x)) ++#define VDM_PRIORITY_TO_QOS_MAP_MASK 0xf ++ ++#define PCIE_MISC_AXI_INTF_CTRL 0x416C ++#define AXI_REQFIFO_EN_QOS_PROPAGATION BIT(7) ++#define AXI_BRIDGE_LOW_LATENCY_MODE BIT(6) ++#define AXI_MASTER_MAX_OUTSTANDING_REQUESTS_MASK 0x3f + +-#define PCIE_INTR2_CPU_BASE 0x4300 ++#define PCIE_MISC_AXI_READ_ERROR_DATA 0x4170 ++ ++#define PCIE_INTR2_CPU_BASE (pcie->reg_offsets[INTR2_CPU]) + #define PCIE_MSI_INTR2_BASE 0x4500 + /* Offsets from PCIE_INTR2_CPU_BASE and PCIE_MSI_INTR2_BASE */ + #define MSI_INT_STATUS 0x0 +@@ -197,6 +276,8 @@ enum { + RGR1_SW_INIT_1, + EXT_CFG_INDEX, + EXT_CFG_DATA, ++ PCIE_HARD_DEBUG, ++ INTR2_CPU, + }; + + enum { +@@ -211,6 +292,7 @@ enum pcie_type { + BCM4908, + BCM7278, + BCM2711, ++ BCM2712, + }; + + struct pcie_cfg_data { +@@ -218,6 +300,7 @@ struct pcie_cfg_data { + const enum pcie_type type; + void (*perst_set)(struct brcm_pcie *pcie, u32 val); + void (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val); ++ bool (*rc_mode)(struct brcm_pcie *pcie); + }; + + struct subdev_regulators { +@@ -234,7 +317,7 @@ struct brcm_msi { + struct mutex lock; /* guards the alloc/free operations */ + u64 target_addr; + int irq; +- DECLARE_BITMAP(used, BRCM_INT_PCI_MSI_NR); ++ DECLARE_BITMAP(used, 64); + bool legacy; + /* Some chips have MSIs in bits [31..24] of a shared register. */ + int legacy_shift; +@@ -251,6 +334,7 @@ struct brcm_pcie { + struct device_node *np; + bool ssc; + bool l1ss; ++ bool rcb_mps_mode; + int gen; + u64 msi_target_addr; + struct brcm_msi *msi; +@@ -258,11 +342,14 @@ struct brcm_pcie { + enum pcie_type type; + struct reset_control *rescal; + struct reset_control *perst_reset; ++ struct reset_control *bridge_reset; + int num_memc; + u64 memc_size[PCIE_BRCM_MAX_MEMC]; + u32 hw_rev; ++ u32 qos_map; + void (*perst_set)(struct brcm_pcie *pcie, u32 val); + void (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val); ++ bool (*rc_mode)(struct brcm_pcie *pcie); + struct subdev_regulators *sr; + bool ep_wakeup_capable; + }; +@@ -283,8 +370,8 @@ static int brcm_pcie_encode_ibar_size(u6 + if (log2_in >= 12 && log2_in <= 15) + /* Covers 4KB to 32KB (inclusive) */ + return (log2_in - 12) + 0x1c; +- else if (log2_in >= 16 && log2_in <= 35) +- /* Covers 64KB to 32GB, (inclusive) */ ++ else if (log2_in >= 16 && log2_in <= 36) ++ /* Covers 64KB to 64GB, (inclusive) */ + return log2_in - 15; + /* Something is awry so disable */ + return 0; +@@ -381,6 +468,35 @@ static int brcm_pcie_set_ssc(struct brcm + return ssc && pll ? 0 : -EIO; + } + ++static void brcm_pcie_munge_pll(struct brcm_pcie *pcie) ++{ ++ //print "MDIO block 0x1600 written per Dannys instruction" ++ //tmp = pcie_mdio_write(phyad, &h16&, &h50b9&) ++ //tmp = pcie_mdio_write(phyad, &h17&, &hbd1a&) ++ //tmp = pcie_mdio_write(phyad, &h1b&, &h5030&) ++ //tmp = pcie_mdio_write(phyad, &h1e&, &h0007&) ++ ++ u32 tmp; ++ int ret, i; ++ u8 regs[] = { 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e }; ++ u16 data[] = { 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007 }; ++ ++ ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET, ++ 0x1600); ++ for (i = 0; i < ARRAY_SIZE(regs); i++) { ++ brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp); ++ dev_dbg(pcie->dev, "PCIE MDIO pre_refclk 0x%02x = 0x%04x\n", ++ regs[i], tmp); ++ } ++ for (i = 0; i < ARRAY_SIZE(regs); i++) { ++ brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, regs[i], data[i]); ++ brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp); ++ dev_dbg(pcie->dev, "PCIE MDIO post_refclk 0x%02x = 0x%04x\n", ++ regs[i], tmp); ++ } ++ usleep_range(100, 200); ++} ++ + /* Limits operation to a specific generation (1, 2, or 3) */ + static void brcm_pcie_set_gen(struct brcm_pcie *pcie, int gen) + { +@@ -438,6 +554,97 @@ static void brcm_pcie_set_outbound_win(s + writel(tmp, pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win)); + } + ++static void brcm_pcie_set_tc_qos(struct brcm_pcie *pcie) ++{ ++ int i; ++ u32 reg; ++ ++ if (pcie->type != BCM2712) ++ return; ++ ++ /* XXX: BCM2712C0 is broken, disable the forwarding search */ ++ reg = readl(pcie->base + PCIE_MISC_AXI_INTF_CTRL); ++ reg &= ~AXI_REQFIFO_EN_QOS_PROPAGATION; ++ writel(reg, pcie->base + PCIE_MISC_AXI_INTF_CTRL); ++ ++ /* Disable VDM reception by default - QoS map defaults to 0 */ ++ reg = readl(pcie->base + PCIE_MISC_CTRL_1); ++ reg &= ~PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK; ++ writel(reg, pcie->base + PCIE_MISC_CTRL_1); ++ ++ if (!of_property_read_u32(pcie->np, "brcm,fifo-qos-map", &pcie->qos_map)) { ++ /* ++ * Backpressure mode - bottom 4 nibbles are QoS for each ++ * quartile of FIFO level. Each TC gets the same map, because ++ * this mode is intended for nonrealtime EPs. ++ */ ++ ++ pcie->qos_map &= 0x0000ffff; ++ for (i = 0; i < 8; i++) ++ writel(pcie->qos_map, pcie->base + PCIE_MISC_TC_QUEUE_TO_QOS_MAP(i)); ++ ++ return; ++ } ++ ++ if (!of_property_read_u32(pcie->np, "brcm,vdm-qos-map", &pcie->qos_map)) { ++ ++ reg = readl(pcie->base + PCIE_MISC_CTRL_1); ++ reg |= PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK; ++ writel(reg, pcie->base + PCIE_MISC_CTRL_1); ++ ++ /* No forwarding means no point separating panic priorities from normal */ ++ writel(pcie->qos_map, pcie->base + PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_LO); ++ writel(pcie->qos_map, pcie->base + PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_HI); ++ ++ /* Match Vendor ID of 0 */ ++ writel(0, pcie->base + PCIE_RC_TL_VDM_CTL1); ++ /* Forward VDMs to priority interface - at least the rx counters work */ ++ reg = readl(pcie->base + PCIE_RC_TL_VDM_CTL0); ++ reg |= PCIE_RC_TL_VDM_CTL0_VDM_ENABLED_MASK | ++ PCIE_RC_TL_VDM_CTL0_VDM_IGNORETAG_MASK | ++ PCIE_RC_TL_VDM_CTL0_VDM_IGNOREVNDRID_MASK; ++ writel(reg, pcie->base + PCIE_RC_TL_VDM_CTL0); ++ } ++} ++ ++static void brcm_pcie_config_clkreq(struct brcm_pcie *pcie) ++{ ++ void __iomem *base = pcie->base; ++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); ++ int domain = pci_domain_nr(bridge->bus); ++ const struct pci_bus *bus = pci_find_bus(domain, 1); ++ struct pci_dev *pdev = (struct pci_dev *)bus->devices.next; ++ u32 tmp, link_cap = 0; ++ u16 link_ctl = 0; ++ int clkpm = 0; ++ int substates = 0; ++ ++ pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); ++ if ((link_cap & PCI_EXP_LNKCAP_CLKPM)) ++ clkpm = 1; ++ ++ pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &link_ctl); ++ if (!(link_ctl & PCI_EXP_LNKCTL_CLKREQ_EN)) ++ clkpm = 0; ++ ++ if (pcie->l1ss && pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS)) ++ substates = 1; ++ ++ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK; ++ tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK; ++ ++ if (substates) ++ tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK; ++ else if (clkpm) ++ tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK; ++ ++ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ ++ if (substates || clkpm) ++ dev_info(pcie->dev, "clkreq control enabled\n"); ++} ++ + static struct irq_chip brcm_msi_irq_chip = { + .name = "BRCM STB PCIe MSI", + .irq_ack = irq_chip_ack_parent, +@@ -455,7 +662,7 @@ static struct msi_domain_info brcm_msi_d + static void brcm_pcie_msi_isr(struct irq_desc *desc) + { + struct irq_chip *chip = irq_desc_get_chip(desc); +- unsigned long status; ++ unsigned long status, virq; + struct brcm_msi *msi; + struct device *dev; + u32 bit; +@@ -467,10 +674,22 @@ static void brcm_pcie_msi_isr(struct irq + status = readl(msi->intr_base + MSI_INT_STATUS); + status >>= msi->legacy_shift; + +- for_each_set_bit(bit, &status, msi->nr) { +- int ret; +- ret = generic_handle_domain_irq(msi->inner_domain, bit); +- if (ret) ++ for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR/*msi->nr*/) { ++ bool found = false; ++ ++ virq = irq_find_mapping(msi->inner_domain, bit); ++ if (virq) { ++ found = true; ++ dev_dbg(dev, "MSI -> %ld\n", virq); ++ generic_handle_irq(virq); ++ } ++ virq = irq_find_mapping(msi->inner_domain, bit + 32); ++ if (virq) { ++ found = true; ++ dev_dbg(dev, "MSI -> %ld\n", virq); ++ generic_handle_irq(virq); ++ } ++ if (!found) + dev_dbg(dev, "unexpected MSI\n"); + } + +@@ -483,7 +702,7 @@ static void brcm_msi_compose_msi_msg(str + + msg->address_lo = lower_32_bits(msi->target_addr); + msg->address_hi = upper_32_bits(msi->target_addr); +- msg->data = (0xffff & PCIE_MISC_MSI_DATA_CONFIG_VAL_32) | data->hwirq; ++ msg->data = (0xffff & PCIE_MISC_MSI_DATA_CONFIG_VAL_32) | (data->hwirq & 0x1f); + } + + static int brcm_msi_set_affinity(struct irq_data *irq_data, +@@ -495,7 +714,7 @@ static int brcm_msi_set_affinity(struct + static void brcm_msi_ack_irq(struct irq_data *data) + { + struct brcm_msi *msi = irq_data_get_irq_chip_data(data); +- const int shift_amt = data->hwirq + msi->legacy_shift; ++ const int shift_amt = (data->hwirq & 0x1f) + msi->legacy_shift; + + writel(1 << shift_amt, msi->intr_base + MSI_INT_CLR); + } +@@ -653,7 +872,7 @@ static int brcm_pcie_enable_msi(struct b + msi->legacy_shift = 24; + } else { + msi->intr_base = msi->base + PCIE_MSI_INTR2_BASE; +- msi->nr = BRCM_INT_PCI_MSI_NR; ++ msi->nr = 64; //BRCM_INT_PCI_MSI_NR; + msi->legacy_shift = 0; + } + +@@ -670,7 +889,7 @@ static int brcm_pcie_enable_msi(struct b + } + + /* The controller is capable of serving in both RC and EP roles */ +-static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie) ++static bool brcm_pcie_rc_mode_generic(struct brcm_pcie *pcie) + { + void __iomem *base = pcie->base; + u32 val = readl(base + PCIE_MISC_PCIE_STATUS); +@@ -678,6 +897,14 @@ static bool brcm_pcie_rc_mode(struct brc + return !!FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK, val); + } + ++static bool brcm_pcie_rc_mode_2712(struct brcm_pcie *pcie) ++{ ++ void __iomem *base = pcie->base; ++ u32 val = readl(base + PCIE_MISC_PCIE_STATUS); ++ ++ return !!FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK_2712, val) | 1; //XXX ++} ++ + static bool brcm_pcie_link_up(struct brcm_pcie *pcie) + { + u32 val = readl(pcie->base + PCIE_MISC_PCIE_STATUS); +@@ -749,6 +976,18 @@ static inline void brcm_pcie_bridge_sw_i + writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1(pcie)); + } + ++static inline void brcm_pcie_bridge_sw_init_set_2712(struct brcm_pcie *pcie, u32 val) ++{ ++ if (WARN_ONCE(!pcie->bridge_reset, ++ "missing bridge reset controller\n")) ++ return; ++ ++ if (val) ++ reset_control_assert(pcie->bridge_reset); ++ else ++ reset_control_deassert(pcie->bridge_reset); ++} ++ + static inline void brcm_pcie_perst_set_4908(struct brcm_pcie *pcie, u32 val) + { + if (WARN_ONCE(!pcie->perst_reset, "missing PERST# reset controller\n")) +@@ -770,6 +1009,16 @@ static inline void brcm_pcie_perst_set_7 + writel(tmp, pcie->base + PCIE_MISC_PCIE_CTRL); + } + ++static inline void brcm_pcie_perst_set_2712(struct brcm_pcie *pcie, u32 val) ++{ ++ u32 tmp; ++ ++ /* Perst bit has moved and assert value is 0 */ ++ tmp = readl(pcie->base + PCIE_MISC_PCIE_CTRL); ++ u32p_replace_bits(&tmp, !val, PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK); ++ writel(tmp, pcie->base + PCIE_MISC_PCIE_CTRL); ++} ++ + static inline void brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val) + { + u32 tmp; +@@ -796,6 +1045,8 @@ static inline int brcm_pcie_get_rc_bar2_ + size += entry->res->end - entry->res->start + 1; + if (pcie_beg < lowest_pcie_addr) + lowest_pcie_addr = pcie_beg; ++ if (pcie->type == BCM2711 || pcie->type == BCM2712) ++ break; // Only consider the first entry + } + + if (lowest_pcie_addr == ~(u64)0) { +@@ -866,6 +1117,30 @@ static inline int brcm_pcie_get_rc_bar2_ + return 0; + } + ++static int brcm_pcie_get_rc_bar_n(struct brcm_pcie *pcie, ++ int idx, ++ u64 *rc_bar_cpu, ++ u64 *rc_bar_size, ++ u64 *rc_bar_pci) ++{ ++ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); ++ struct resource_entry *entry; ++ int i = 0; ++ ++ resource_list_for_each_entry(entry, &bridge->dma_ranges) { ++ if (i == idx) { ++ *rc_bar_cpu = entry->res->start; ++ *rc_bar_size = entry->res->end - entry->res->start + 1; ++ *rc_bar_pci = entry->res->start - entry->offset; ++ return 0; ++ } ++ ++ i++; ++ } ++ ++ return -EINVAL; ++} ++ + static int brcm_pcie_setup(struct brcm_pcie *pcie) + { + u64 rc_bar2_offset, rc_bar2_size; +@@ -874,11 +1149,14 @@ static int brcm_pcie_setup(struct brcm_p + struct resource_entry *entry; + u32 tmp, burst, aspm_support; + int num_out_wins = 0; +- int ret, memc; ++ int ret, memc, count, i; + + /* Reset the bridge */ + pcie->bridge_sw_init_set(pcie, 1); +- pcie->perst_set(pcie, 1); ++ ++ /* Ensure that PERST# is asserted; some bootloaders may deassert it. */ ++ if (pcie->type == BCM2711) ++ pcie->perst_set(pcie, 1); + + usleep_range(100, 200); + +@@ -894,6 +1172,17 @@ static int brcm_pcie_setup(struct brcm_p + /* Wait for SerDes to be stable */ + usleep_range(100, 200); + ++ if (pcie->type == BCM2712) { ++ /* Allow a 54MHz (xosc) refclk source */ ++ brcm_pcie_munge_pll(pcie); ++ /* Fix for L1SS errata */ ++ tmp = readl(base + PCIE_RC_PL_PHY_CTL_15); ++ tmp &= ~PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK; ++ /* PM clock period is 18.52ns (round down) */ ++ tmp |= 0x12; ++ writel(tmp, base + PCIE_RC_PL_PHY_CTL_15); ++ } ++ + /* + * SCB_MAX_BURST_SIZE is a two bit field. For GENERIC chips it + * is encoded as 0=128, 1=256, 2=512, 3=Rsvd, for BCM7278 it +@@ -903,18 +1192,25 @@ static int brcm_pcie_setup(struct brcm_p + burst = 0x1; /* 256 bytes */ + else if (pcie->type == BCM2711) + burst = 0x0; /* 128 bytes */ ++ else if (pcie->type == BCM2712) ++ burst = 0x1; /* 128 bytes */ + else if (pcie->type == BCM7278) + burst = 0x3; /* 512 bytes */ + else + burst = 0x2; /* 512 bytes */ + +- /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */ ++ /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN, RCB_MPS_MODE */ + tmp = readl(base + PCIE_MISC_MISC_CTRL); + u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK); + u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK); + u32p_replace_bits(&tmp, burst, PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK); ++ if (pcie->rcb_mps_mode) ++ u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_RCB_MPS_MODE_MASK); ++ dev_info(pcie->dev, "setting SCB_ACCESS_EN, READ_UR_MODE, MAX_BURST_SIZE\n"); + writel(tmp, base + PCIE_MISC_MISC_CTRL); + ++ brcm_pcie_set_tc_qos(pcie); ++ + ret = brcm_pcie_get_rc_bar2_size_and_offset(pcie, &rc_bar2_size, + &rc_bar2_offset); + if (ret) +@@ -927,7 +1223,11 @@ static int brcm_pcie_setup(struct brcm_p + writel(upper_32_bits(rc_bar2_offset), + base + PCIE_MISC_RC_BAR2_CONFIG_HI); + ++ tmp = readl(base + PCIE_MISC_UBUS_BAR2_CONFIG_REMAP); ++ u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK); ++ writel(tmp, base + PCIE_MISC_UBUS_BAR2_CONFIG_REMAP); + tmp = readl(base + PCIE_MISC_MISC_CTRL); ++ + for (memc = 0; memc < pcie->num_memc; memc++) { + u32 scb_size_val = ilog2(pcie->memc_size[memc]) - 15; + +@@ -938,8 +1238,32 @@ static int brcm_pcie_setup(struct brcm_p + else if (memc == 2) + u32p_replace_bits(&tmp, scb_size_val, SCB_SIZE_MASK(2)); + } ++ + writel(tmp, base + PCIE_MISC_MISC_CTRL); + ++ if (pcie->type == BCM2712) { ++ /* Suppress AXI error responses and return 1s for read failures */ ++ tmp = readl(base + PCIE_MISC_UBUS_CTRL); ++ u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK); ++ u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK); ++ writel(tmp, base + PCIE_MISC_UBUS_CTRL); ++ writel(0xffffffff, base + PCIE_MISC_AXI_READ_ERROR_DATA); ++ ++ /* ++ * Adjust timeouts. The UBUS timeout also affects CRS ++ * completion retries, as the request will get terminated if ++ * either timeout expires, so both have to be a large value ++ * (in clocks of 750MHz). ++ * Set UBUS timeout to 250ms, then set RC config retry timeout ++ * to be ~240ms. ++ * ++ * Setting CRSVis=1 will stop the core from blocking on a CRS ++ * response, but does require the device to be well-behaved... ++ */ ++ writel(0xB2D0000, base + PCIE_MISC_UBUS_TIMEOUT); ++ writel(0xABA0000, base + PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT); ++ } ++ + /* + * We ideally want the MSI target address to be located in the 32bit + * addressable memory area. Some devices might depend on it. This is +@@ -952,7 +1276,7 @@ static int brcm_pcie_setup(struct brcm_p + else + pcie->msi_target_addr = BRCM_MSI_TARGET_ADDR_GT_4GB; + +- if (!brcm_pcie_rc_mode(pcie)) { ++ if (!pcie->rc_mode(pcie)) { + dev_err(pcie->dev, "PCIe RC controller misconfigured as Endpoint\n"); + return -EINVAL; + } +@@ -976,6 +1300,38 @@ static int brcm_pcie_setup(struct brcm_p + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK); + writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); + ++ /* program additional inbound windows (RC_BAR4..RC_BAR10) */ ++ count = (pcie->type == BCM2712) ? 7 : 0; ++ for (i = 0; i < count; i++) { ++ u64 bar_cpu, bar_size, bar_pci; ++ ++ ret = brcm_pcie_get_rc_bar_n(pcie, 1 + i, &bar_cpu, &bar_size, ++ &bar_pci); ++ if (ret) ++ break; ++ ++ tmp = lower_32_bits(bar_pci); ++ u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(bar_size), ++ PCIE_MISC_RC_BAR_CONFIG_LO_SIZE_MASK); ++ writel(tmp, base + PCIE_MISC_RC_BAR4_CONFIG_LO + i * 8); ++ writel(upper_32_bits(bar_pci), ++ base + PCIE_MISC_RC_BAR4_CONFIG_HI + i * 8); ++ ++ tmp = upper_32_bits(bar_cpu) & ++ PCIE_MISC_UBUS_BAR_CONFIG_REMAP_HI_MASK; ++ writel(tmp, ++ base + PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_HI + i * 8); ++ tmp = lower_32_bits(bar_cpu) & ++ PCIE_MISC_UBUS_BAR_CONFIG_REMAP_LO_MASK; ++ writel(tmp | PCIE_MISC_UBUS_BAR_CONFIG_REMAP_ENABLE, ++ base + PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_LO + i * 8); ++ } ++ ++ if (pcie->gen) { ++ dev_info(pcie->dev, "Forcing gen %d\n", pcie->gen); ++ brcm_pcie_set_gen(pcie, pcie->gen); ++ } ++ + /* + * For config space accesses on the RC, show the right class for + * a PCIe-PCIe bridge (the default setting is to be EP mode). +@@ -1031,7 +1387,6 @@ static int brcm_pcie_start_link(struct b + void __iomem *base = pcie->base; + u16 nlw, cls, lnksta; + bool ssc_good = false; +- u32 tmp; + int ret, i; + + /* Unassert the fundamental reset */ +@@ -1067,6 +1422,7 @@ static int brcm_pcie_start_link(struct b + dev_err(dev, "failed attempt to enter ssc mode\n"); + } + ++ + lnksta = readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKSTA); + cls = FIELD_GET(PCI_EXP_LNKSTA_CLS, lnksta); + nlw = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta); +@@ -1074,27 +1430,6 @@ static int brcm_pcie_start_link(struct b + pci_speed_string(pcie_link_speed[cls]), nlw, + ssc_good ? "(SSC)" : "(!SSC)"); + +- tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); +- if (pcie->l1ss) { +- /* +- * Enable CLKREQ# signalling include L1 Substate control of +- * the CLKREQ# signal and the external reference clock buffer. +- * meet requirement for Endpoints that require CLKREQ# +- * assertion to clock active within 400ns. +- */ +- tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK; +- tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK; +- } else { +- /* +- * Refclk from RC should be gated with CLKREQ# input when +- * ASPM L0s,L1 is enabled => setting the CLKREQ_DEBUG_ENABLE +- * field to 1. +- */ +- tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK; +- tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK; +- } +- writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); +- + return 0; + } + +@@ -1202,6 +1537,7 @@ static void brcm_pcie_enter_l23(struct b + + static int brcm_phy_cntl(struct brcm_pcie *pcie, const int start) + { ++#if 0 + static const u32 shifts[PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_NFLDS] = { + PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_PWRDN_SHIFT, + PCIE_DVT_PMU_PCIE_PHY_CTRL_DAST_RESET_SHIFT, +@@ -1234,6 +1570,9 @@ static int brcm_phy_cntl(struct brcm_pci + dev_err(pcie->dev, "failed to %s phy\n", (start ? "start" : "stop")); + + return ret; ++#else ++ return 0; ++#endif + } + + static inline int brcm_phy_start(struct brcm_pcie *pcie) +@@ -1266,6 +1605,12 @@ static void brcm_pcie_turn_off(struct br + u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK); + writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); + ++ /* ++ * Shutting down this bridge on pcie1 means accesses to rescal block ++ * will hang the chip if another RC wants to assert/deassert rescal. ++ */ ++ if (pcie->type == BCM2712) ++ return; + /* Shutdown PCIe bridge */ + pcie->bridge_sw_init_set(pcie, 1); + } +@@ -1296,9 +1641,9 @@ static int brcm_pcie_suspend_noirq(struc + if (brcm_phy_stop(pcie)) + dev_err(dev, "Could not stop phy for suspend\n"); + +- ret = reset_control_rearm(pcie->rescal); ++ ret = reset_control_assert(pcie->rescal); + if (ret) { +- dev_err(dev, "Could not rearm rescal reset\n"); ++ dev_err(dev, "Could not assert rescal reset\n"); + return ret; + } + +@@ -1393,7 +1738,7 @@ err_regulator: + if (pcie->sr) + regulator_bulk_disable(pcie->sr->num_supplies, pcie->sr->supplies); + err_reset: +- reset_control_rearm(pcie->rescal); ++ reset_control_assert(pcie->rescal); + err_disable_clk: + clk_disable_unprepare(pcie->clk); + return ret; +@@ -1405,8 +1750,8 @@ static void __brcm_pcie_remove(struct br + brcm_pcie_turn_off(pcie); + if (brcm_phy_stop(pcie)) + dev_err(pcie->dev, "Could not stop phy\n"); +- if (reset_control_rearm(pcie->rescal)) +- dev_err(pcie->dev, "Could not rearm rescal reset\n"); ++ if (reset_control_assert(pcie->rescal)) ++ dev_err(pcie->dev, "Could not assert rescal reset\n"); + clk_disable_unprepare(pcie->clk); + } + +@@ -1426,12 +1771,16 @@ static const int pcie_offsets[] = { + [RGR1_SW_INIT_1] = 0x9210, + [EXT_CFG_INDEX] = 0x9000, + [EXT_CFG_DATA] = 0x9004, ++ [PCIE_HARD_DEBUG] = 0x4204, ++ [INTR2_CPU] = 0x4300, + }; + + static const int pcie_offsets_bmips_7425[] = { + [RGR1_SW_INIT_1] = 0x8010, + [EXT_CFG_INDEX] = 0x8300, + [EXT_CFG_DATA] = 0x8304, ++ [PCIE_HARD_DEBUG] = 0x4204, ++ [INTR2_CPU] = 0x4300, + }; + + static const struct pcie_cfg_data generic_cfg = { +@@ -1439,6 +1788,7 @@ static const struct pcie_cfg_data generi + .type = GENERIC, + .perst_set = brcm_pcie_perst_set_generic, + .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic, ++ .rc_mode = brcm_pcie_rc_mode_generic, + }; + + static const struct pcie_cfg_data bcm7425_cfg = { +@@ -1446,6 +1796,7 @@ static const struct pcie_cfg_data bcm742 + .type = BCM7425, + .perst_set = brcm_pcie_perst_set_generic, + .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic, ++ .rc_mode = brcm_pcie_rc_mode_generic, + }; + + static const struct pcie_cfg_data bcm7435_cfg = { +@@ -1460,12 +1811,15 @@ static const struct pcie_cfg_data bcm490 + .type = BCM4908, + .perst_set = brcm_pcie_perst_set_4908, + .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic, ++ .rc_mode = brcm_pcie_rc_mode_generic, + }; + + static const int pcie_offset_bcm7278[] = { + [RGR1_SW_INIT_1] = 0xc010, + [EXT_CFG_INDEX] = 0x9000, + [EXT_CFG_DATA] = 0x9004, ++ [PCIE_HARD_DEBUG] = 0x4204, ++ [INTR2_CPU] = 0x4300, + }; + + static const struct pcie_cfg_data bcm7278_cfg = { +@@ -1473,6 +1827,7 @@ static const struct pcie_cfg_data bcm727 + .type = BCM7278, + .perst_set = brcm_pcie_perst_set_7278, + .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_7278, ++ .rc_mode = brcm_pcie_rc_mode_generic, + }; + + static const struct pcie_cfg_data bcm2711_cfg = { +@@ -1480,10 +1835,27 @@ static const struct pcie_cfg_data bcm271 + .type = BCM2711, + .perst_set = brcm_pcie_perst_set_generic, + .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic, ++ .rc_mode = brcm_pcie_rc_mode_generic, ++}; ++ ++static const int pcie_offsets_bcm2712[] = { ++ [EXT_CFG_INDEX] = 0x9000, ++ [EXT_CFG_DATA] = 0x9004, ++ [PCIE_HARD_DEBUG] = 0x4304, ++ [INTR2_CPU] = 0x4400, ++}; ++ ++static const struct pcie_cfg_data bcm2712_cfg = { ++ .offsets = pcie_offsets_bcm2712, ++ .type = BCM2712, ++ .perst_set = brcm_pcie_perst_set_2712, ++ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_2712, ++ .rc_mode = brcm_pcie_rc_mode_2712, + }; + + static const struct of_device_id brcm_pcie_match[] = { + { .compatible = "brcm,bcm2711-pcie", .data = &bcm2711_cfg }, ++ { .compatible = "brcm,bcm2712-pcie", .data = &bcm2712_cfg }, + { .compatible = "brcm,bcm4908-pcie", .data = &bcm4908_cfg }, + { .compatible = "brcm,bcm7211-pcie", .data = &generic_cfg }, + { .compatible = "brcm,bcm7278-pcie", .data = &bcm7278_cfg }, +@@ -1524,7 +1896,7 @@ static int brcm_pcie_probe(struct platfo + + data = of_device_get_match_data(&pdev->dev); + if (!data) { +- pr_err("failed to look up compatible string\n"); ++ dev_err(&pdev->dev, "failed to look up compatible string\n"); + return -EINVAL; + } + +@@ -1535,6 +1907,7 @@ static int brcm_pcie_probe(struct platfo + pcie->type = data->type; + pcie->perst_set = data->perst_set; + pcie->bridge_sw_init_set = data->bridge_sw_init_set; ++ pcie->rc_mode = data->rc_mode; + + pcie->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pcie->base)) +@@ -1549,6 +1922,7 @@ static int brcm_pcie_probe(struct platfo + + pcie->ssc = of_property_read_bool(np, "brcm,enable-ssc"); + pcie->l1ss = of_property_read_bool(np, "brcm,enable-l1ss"); ++ pcie->rcb_mps_mode = of_property_read_bool(np, "brcm,enable-mps-rcb"); + + ret = clk_prepare_enable(pcie->clk); + if (ret) { +@@ -1565,14 +1939,20 @@ static int brcm_pcie_probe(struct platfo + clk_disable_unprepare(pcie->clk); + return PTR_ERR(pcie->perst_reset); + } ++ pcie->bridge_reset = ++ devm_reset_control_get_optional_exclusive(&pdev->dev, "bridge"); ++ if (IS_ERR(pcie->bridge_reset)) { ++ clk_disable_unprepare(pcie->clk); ++ return PTR_ERR(pcie->bridge_reset); ++ } + +- ret = reset_control_reset(pcie->rescal); ++ ret = reset_control_deassert(pcie->rescal); + if (ret) + dev_err(&pdev->dev, "failed to deassert 'rescal'\n"); + + ret = brcm_phy_start(pcie); + if (ret) { +- reset_control_rearm(pcie->rescal); ++ reset_control_assert(pcie->rescal); + clk_disable_unprepare(pcie->clk); + return ret; + } +@@ -1595,6 +1975,33 @@ static int brcm_pcie_probe(struct platfo + dev_err(pcie->dev, "probe of internal MSI failed"); + goto fail; + } ++ } else if (pci_msi_enabled() && msi_np != pcie->np) { ++ /* Use RC_BAR1 for MIP access */ ++ u64 msi_pci_addr; ++ u64 msi_phys_addr; ++ ++ if (of_property_read_u64(msi_np, "brcm,msi-pci-addr", &msi_pci_addr)) { ++ dev_err(pcie->dev, "Unable to find MSI PCI address\n"); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ if (of_property_read_u64(msi_np, "reg", &msi_phys_addr)) { ++ dev_err(pcie->dev, "Unable to find MSI physical address\n"); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ writel(lower_32_bits(msi_pci_addr) | brcm_pcie_encode_ibar_size(0x1000), ++ pcie->base + PCIE_MISC_RC_BAR1_CONFIG_LO); ++ writel(upper_32_bits(msi_pci_addr), ++ pcie->base + PCIE_MISC_RC_BAR1_CONFIG_HI); ++ ++ writel(lower_32_bits(msi_phys_addr) | ++ PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_ACCESS_ENABLE_MASK, ++ pcie->base + PCIE_MISC_UBUS_BAR1_CONFIG_REMAP); ++ writel(upper_32_bits(msi_phys_addr), ++ pcie->base + PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_HI); + } + + bridge->ops = pcie->type == BCM7425 ? &brcm7425_pcie_ops : &brcm_pcie_ops; +@@ -1611,6 +2018,8 @@ static int brcm_pcie_probe(struct platfo + return ret; + } + ++ brcm_pcie_config_clkreq(pcie); ++ + return 0; + + fail: diff --git a/target/linux/bcm27xx/patches-6.1/950-0868-V4L2-Add-PiSP-opaque-formats-to-V4L2.patch b/target/linux/bcm27xx/patches-6.1/950-0868-V4L2-Add-PiSP-opaque-formats-to-V4L2.patch new file mode 100644 index 0000000000..3b50329ab1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0868-V4L2-Add-PiSP-opaque-formats-to-V4L2.patch @@ -0,0 +1,42 @@ +From 9a11300e46344917226b986a8740e7581d66adf3 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Mon, 7 Feb 2022 09:20:49 +0000 +Subject: [PATCH] V4L2: Add PiSP opaque formats to V4L2 + +Signed-off-by: Naushir Patuck +--- + 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 + diff --git a/target/linux/bcm27xx/patches-6.1/950-0869-V4L2-Add-PiSP-compressed-formats-to-V4L2.patch b/target/linux/bcm27xx/patches-6.1/950-0869-V4L2-Add-PiSP-compressed-formats-to-V4L2.patch new file mode 100644 index 0000000000..6836922b7c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0869-V4L2-Add-PiSP-compressed-formats-to-V4L2.patch @@ -0,0 +1,39 @@ +From 01f31f4145d49a30eb553c65ea755dde8dba1de0 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 2 Mar 2022 16:10:50 +0000 +Subject: [PATCH] V4L2: Add PiSP compressed formats to V4L2 + +Signed-off-by: Naushir Patuck +--- + 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 */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0871-dt-binding-mfd-Add-binding-for-Raspberry-Pi-RP1.patch b/target/linux/bcm27xx/patches-6.1/950-0871-dt-binding-mfd-Add-binding-for-Raspberry-Pi-RP1.patch new file mode 100644 index 0000000000..9e98dd0345 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0871-dt-binding-mfd-Add-binding-for-Raspberry-Pi-RP1.patch @@ -0,0 +1,249 @@ +From c93f469dabdbed822e5abeb5283d79fc9faa858c Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0872-mfd-Add-rp1-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0872-mfd-Add-rp1-driver.patch new file mode 100644 index 0000000000..dd252cba36 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0872-mfd-Add-rp1-driver.patch @@ -0,0 +1,442 @@ +From 7196a12b94e90225686e6c34cdf65a583214f7a5 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* 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 "); ++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 ++ ++#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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0873-dt-bindings-clock-Add-bindings-for-Raspberry-Pi-RP1.patch b/target/linux/bcm27xx/patches-6.1/950-0873-dt-bindings-clock-Add-bindings-for-Raspberry-Pi-RP1.patch new file mode 100644 index 0000000000..f94782438b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0873-dt-bindings-clock-Add-bindings-for-Raspberry-Pi-RP1.patch @@ -0,0 +1,65 @@ +From 00ff2819eb852b54fe22e7181646e40d560576dc Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0874-clk-Add-rp1-clock-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0874-clk-Add-rp1-clock-driver.patch new file mode 100644 index 0000000000..2a861d18c7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0874-clk-Add-rp1-clock-driver.patch @@ -0,0 +1,2208 @@ +From 66517cdfea750b89d86f78af55ef773cbd3e005f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 10 Oct 2022 14:25:38 +0100 +Subject: [PATCH] clk: Add rp1 clock driver + +RP1 contains various PLLs and clocks for driving the hardware +blocks, so add a driver to configure these. + +Signed-off-by: Phil Elwell +--- + drivers/clk/Kconfig | 7 + + drivers/clk/Makefile | 1 + + drivers/clk/clk-rp1.c | 2085 +++++++++++++++++++++++++++++++ + include/dt-bindings/clock/rp1.h | 69 +- + 4 files changed, 2128 insertions(+), 34 deletions(-) + create mode 100644 drivers/clk/clk-rp1.c + +--- a/drivers/clk/Kconfig ++++ b/drivers/clk/Kconfig +@@ -89,6 +89,13 @@ config COMMON_CLK_RK808 + These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each. + Clkout1 is always on, Clkout2 can off by control register. + ++config COMMON_CLK_RP1 ++ tristate "Raspberry Pi RP1-based clock support" ++ depends on PCI || COMPILE_TEST ++ depends on COMMON_CLK ++ help ++ Enable common clock framework support for Raspberry Pi RP1 ++ + 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 +@@ -58,6 +58,7 @@ obj-$(CONFIG_CLK_LS1028A_PLLDIG) += clk- + obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o + 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_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.c +@@ -0,0 +1,2085 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (C) 2023 Raspberry Pi Ltd. ++ * ++ * Clock driver for RP1 PCIe multifunction chip. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#define PLL_SYS_CS 0x08000 ++#define PLL_SYS_PWR 0x08004 ++#define PLL_SYS_FBDIV_INT 0x08008 ++#define PLL_SYS_FBDIV_FRAC 0x0800c ++#define PLL_SYS_PRIM 0x08010 ++#define PLL_SYS_SEC 0x08014 ++ ++#define PLL_AUDIO_CS 0x0c000 ++#define PLL_AUDIO_PWR 0x0c004 ++#define PLL_AUDIO_FBDIV_INT 0x0c008 ++#define PLL_AUDIO_FBDIV_FRAC 0x0c00c ++#define PLL_AUDIO_PRIM 0x0c010 ++#define PLL_AUDIO_SEC 0x0c014 ++ ++#define PLL_VIDEO_CS 0x10000 ++#define PLL_VIDEO_PWR 0x10004 ++#define PLL_VIDEO_FBDIV_INT 0x10008 ++#define PLL_VIDEO_FBDIV_FRAC 0x1000c ++#define PLL_VIDEO_PRIM 0x10010 ++#define PLL_VIDEO_SEC 0x10014 ++ ++#define CLK_SYS_CTRL 0x00014 ++#define CLK_SYS_DIV_INT 0x00018 ++#define CLK_SYS_SEL 0x00020 ++ ++#define CLK_SLOW_SYS_CTRL 0x00024 ++#define CLK_SLOW_SYS_DIV_INT 0x00028 ++#define CLK_SLOW_SYS_SEL 0x00030 ++ ++#define CLK_DMA_CTRL 0x00044 ++#define CLK_DMA_DIV_INT 0x00048 ++#define CLK_DMA_SEL 0x00050 ++ ++#define CLK_UART_CTRL 0x00054 ++#define CLK_UART_DIV_INT 0x00058 ++#define CLK_UART_SEL 0x00060 ++ ++#define CLK_ETH_CTRL 0x00064 ++#define CLK_ETH_DIV_INT 0x00068 ++#define CLK_ETH_SEL 0x00070 ++ ++#define CLK_PWM0_CTRL 0x00074 ++#define CLK_PWM0_DIV_INT 0x00078 ++#define CLK_PWM0_DIV_FRAC 0x0007c ++#define CLK_PWM0_SEL 0x00080 ++ ++#define CLK_PWM1_CTRL 0x00084 ++#define CLK_PWM1_DIV_INT 0x00088 ++#define CLK_PWM1_DIV_FRAC 0x0008c ++#define CLK_PWM1_SEL 0x00090 ++ ++#define CLK_AUDIO_IN_CTRL 0x00094 ++#define CLK_AUDIO_IN_DIV_INT 0x00098 ++#define CLK_AUDIO_IN_SEL 0x000a0 ++ ++#define CLK_AUDIO_OUT_CTRL 0x000a4 ++#define CLK_AUDIO_OUT_DIV_INT 0x000a8 ++#define CLK_AUDIO_OUT_SEL 0x000b0 ++ ++#define CLK_I2S_CTRL 0x000b4 ++#define CLK_I2S_DIV_INT 0x000b8 ++#define CLK_I2S_SEL 0x000c0 ++ ++#define CLK_MIPI0_CFG_CTRL 0x000c4 ++#define CLK_MIPI0_CFG_DIV_INT 0x000c8 ++#define CLK_MIPI0_CFG_SEL 0x000d0 ++ ++#define CLK_MIPI1_CFG_CTRL 0x000d4 ++#define CLK_MIPI1_CFG_DIV_INT 0x000d8 ++#define CLK_MIPI1_CFG_SEL 0x000e0 ++ ++#define CLK_PCIE_AUX_CTRL 0x000e4 ++#define CLK_PCIE_AUX_DIV_INT 0x000e8 ++#define CLK_PCIE_AUX_SEL 0x000f0 ++ ++#define CLK_USBH0_MICROFRAME_CTRL 0x000f4 ++#define CLK_USBH0_MICROFRAME_DIV_INT 0x000f8 ++#define CLK_USBH0_MICROFRAME_SEL 0x00100 ++ ++#define CLK_USBH1_MICROFRAME_CTRL 0x00104 ++#define CLK_USBH1_MICROFRAME_DIV_INT 0x00108 ++#define CLK_USBH1_MICROFRAME_SEL 0x00110 ++ ++#define CLK_USBH0_SUSPEND_CTRL 0x00114 ++#define CLK_USBH0_SUSPEND_DIV_INT 0x00118 ++#define CLK_USBH0_SUSPEND_SEL 0x00120 ++ ++#define CLK_USBH1_SUSPEND_CTRL 0x00124 ++#define CLK_USBH1_SUSPEND_DIV_INT 0x00128 ++#define CLK_USBH1_SUSPEND_SEL 0x00130 ++ ++#define CLK_ETH_TSU_CTRL 0x00134 ++#define CLK_ETH_TSU_DIV_INT 0x00138 ++#define CLK_ETH_TSU_SEL 0x00140 ++ ++#define CLK_ADC_CTRL 0x00144 ++#define CLK_ADC_DIV_INT 0x00148 ++#define CLK_ADC_SEL 0x00150 ++ ++#define CLK_SDIO_TIMER_CTRL 0x00154 ++#define CLK_SDIO_TIMER_DIV_INT 0x00158 ++#define CLK_SDIO_TIMER_SEL 0x00160 ++ ++#define CLK_SDIO_ALT_SRC_CTRL 0x00164 ++#define CLK_SDIO_ALT_SRC_DIV_INT 0x00168 ++#define CLK_SDIO_ALT_SRC_SEL 0x00170 ++ ++#define CLK_GP0_CTRL 0x00174 ++#define CLK_GP0_DIV_INT 0x00178 ++#define CLK_GP0_DIV_FRAC 0x0017c ++#define CLK_GP0_SEL 0x00180 ++ ++#define CLK_GP1_CTRL 0x00184 ++#define CLK_GP1_DIV_INT 0x00188 ++#define CLK_GP1_DIV_FRAC 0x0018c ++#define CLK_GP1_SEL 0x00190 ++ ++#define CLK_GP2_CTRL 0x00194 ++#define CLK_GP2_DIV_INT 0x00198 ++#define CLK_GP2_DIV_FRAC 0x0019c ++#define CLK_GP2_SEL 0x001a0 ++ ++#define CLK_GP3_CTRL 0x001a4 ++#define CLK_GP3_DIV_INT 0x001a8 ++#define CLK_GP3_DIV_FRAC 0x001ac ++#define CLK_GP3_SEL 0x001b0 ++ ++#define CLK_GP4_CTRL 0x001b4 ++#define CLK_GP4_DIV_INT 0x001b8 ++#define CLK_GP4_DIV_FRAC 0x001bc ++#define CLK_GP4_SEL 0x001c0 ++ ++#define CLK_GP5_CTRL 0x001c4 ++#define CLK_GP5_DIV_INT 0x001c8 ++#define CLK_GP5_DIV_FRAC 0x001cc ++#define CLK_GP5_SEL 0x001d0 ++ ++#define CLK_SYS_RESUS_CTRL 0x0020c ++ ++#define CLK_SLOW_SYS_RESUS_CTRL 0x00214 ++ ++#define FC0_REF_KHZ 0x0021c ++#define FC0_MIN_KHZ 0x00220 ++#define FC0_MAX_KHZ 0x00224 ++#define FC0_DELAY 0x00228 ++#define FC0_INTERVAL 0x0022c ++#define FC0_SRC 0x00230 ++#define FC0_STATUS 0x00234 ++#define FC0_RESULT 0x00238 ++#define FC_SIZE 0x20 ++#define FC_COUNT 8 ++#define FC_NUM(idx, off) ((idx) * 32 + (off)) ++ ++#define AUX_SEL 1 ++ ++#define VIDEO_CLOCKS_OFFSET 0x4000 ++#define VIDEO_CLK_VEC_CTRL (VIDEO_CLOCKS_OFFSET + 0x0000) ++#define VIDEO_CLK_VEC_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0004) ++#define VIDEO_CLK_VEC_SEL (VIDEO_CLOCKS_OFFSET + 0x000c) ++#define VIDEO_CLK_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0010) ++#define VIDEO_CLK_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0014) ++#define VIDEO_CLK_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x001c) ++#define VIDEO_CLK_MIPI0_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0020) ++#define VIDEO_CLK_MIPI0_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0024) ++#define VIDEO_CLK_MIPI0_DPI_DIV_FRAC (VIDEO_CLOCKS_OFFSET + 0x0028) ++#define VIDEO_CLK_MIPI0_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x002c) ++#define VIDEO_CLK_MIPI1_DPI_CTRL (VIDEO_CLOCKS_OFFSET + 0x0030) ++#define VIDEO_CLK_MIPI1_DPI_DIV_INT (VIDEO_CLOCKS_OFFSET + 0x0034) ++#define VIDEO_CLK_MIPI1_DPI_DIV_FRAC (VIDEO_CLOCKS_OFFSET + 0x0038) ++#define VIDEO_CLK_MIPI1_DPI_SEL (VIDEO_CLOCKS_OFFSET + 0x003c) ++ ++#define DIV_INT_8BIT_MAX 0x000000ffu /* max divide for most clocks */ ++#define DIV_INT_16BIT_MAX 0x0000ffffu /* max divide for GPx, PWM */ ++#define DIV_INT_24BIT_MAX 0x00ffffffu /* max divide for CLK_SYS */ ++ ++#define FC0_STATUS_DONE BIT(4) ++#define FC0_STATUS_RUNNING BIT(8) ++#define FC0_RESULT_FRAC_SHIFT 5 ++ ++#define PLL_PRIM_DIV1_SHIFT 16 ++#define PLL_PRIM_DIV1_MASK 0x00070000 ++#define PLL_PRIM_DIV2_SHIFT 12 ++#define PLL_PRIM_DIV2_MASK 0x00007000 ++ ++#define PLL_SEC_DIV_SHIFT 8 ++#define PLL_SEC_DIV_WIDTH 5 ++#define PLL_SEC_DIV_MASK 0x00001f00 ++ ++#define PLL_CS_LOCK BIT(31) ++#define PLL_CS_REFDIV_SHIFT 0 ++ ++#define PLL_PWR_PD BIT(0) ++#define PLL_PWR_DACPD BIT(1) ++#define PLL_PWR_DSMPD BIT(2) ++#define PLL_PWR_POSTDIVPD BIT(3) ++#define PLL_PWR_4PHASEPD BIT(4) ++#define PLL_PWR_VCOPD BIT(5) ++#define PLL_PWR_MASK 0x0000003f ++ ++#define PLL_SEC_RST BIT(16) ++#define PLL_SEC_IMPL BIT(31) ++ ++/* PLL phase output for both PRI and SEC */ ++#define PLL_PH_EN BIT(4) ++#define PLL_PH_PHASE_SHIFT 0 ++ ++#define RP1_PLL_PHASE_0 0 ++#define RP1_PLL_PHASE_90 1 ++#define RP1_PLL_PHASE_180 2 ++#define RP1_PLL_PHASE_270 3 ++ ++/* Clock fields for all clocks */ ++#define CLK_CTRL_ENABLE BIT(11) ++#define CLK_CTRL_AUXSRC_MASK 0x000003e0 ++#define CLK_CTRL_AUXSRC_SHIFT 5 ++#define CLK_CTRL_SRC_SHIFT 0 ++#define CLK_DIV_FRAC_BITS 16 ++ ++#define KHz 1000 ++#define MHz (KHz * KHz) ++#define LOCK_TIMEOUT_NS 100000000 ++#define FC_TIMEOUT_NS 100000000 ++ ++#define MAX_CLK_PARENTS 8 ++ ++#define MEASURE_CLOCK_RATE ++const char * const fc0_ref_clk_name = "clk_slow_sys"; ++ ++#define ABS_DIFF(a, b) ((a) > (b) ? (a) - (b) : (b) - (a)) ++#define DIV_U64_NEAREST(a, b) div_u64(((a) + ((b) >> 1)), (b)) ++ ++/* ++ * Names of the reference clock for the pll cores. This name must match ++ * the DT reference clock-output-name. ++ */ ++static const char *const ref_clock = "xosc"; ++ ++/* ++ * Secondary PLL channel output divider table. ++ * Divider values range from 8 to 19. ++ * Invalid values default to 19 ++ */ ++static const struct clk_div_table pll_sec_div_table[] = { ++ { 0x00, 19 }, ++ { 0x01, 19 }, ++ { 0x02, 19 }, ++ { 0x03, 19 }, ++ { 0x04, 19 }, ++ { 0x05, 19 }, ++ { 0x06, 19 }, ++ { 0x07, 19 }, ++ { 0x08, 8 }, ++ { 0x09, 9 }, ++ { 0x0a, 10 }, ++ { 0x0b, 11 }, ++ { 0x0c, 12 }, ++ { 0x0d, 13 }, ++ { 0x0e, 14 }, ++ { 0x0f, 15 }, ++ { 0x10, 16 }, ++ { 0x11, 17 }, ++ { 0x12, 18 }, ++ { 0x13, 19 }, ++ { 0x14, 19 }, ++ { 0x15, 19 }, ++ { 0x16, 19 }, ++ { 0x17, 19 }, ++ { 0x18, 19 }, ++ { 0x19, 19 }, ++ { 0x1a, 19 }, ++ { 0x1b, 19 }, ++ { 0x1c, 19 }, ++ { 0x1d, 19 }, ++ { 0x1e, 19 }, ++ { 0x1f, 19 }, ++ { 0 } ++}; ++ ++struct rp1_clockman { ++ struct device *dev; ++ void __iomem *regs; ++ spinlock_t regs_lock; /* spinlock for all clocks */ ++ ++ /* Must be last */ ++ struct clk_hw_onecell_data onecell; ++}; ++ ++struct rp1_pll_core_data { ++ const char *name; ++ u32 cs_reg; ++ u32 pwr_reg; ++ u32 fbdiv_int_reg; ++ u32 fbdiv_frac_reg; ++ unsigned long flags; ++ u32 fc0_src; ++}; ++ ++struct rp1_pll_data { ++ const char *name; ++ const char *source_pll; ++ u32 ctrl_reg; ++ unsigned long flags; ++ u32 fc0_src; ++}; ++ ++struct rp1_pll_ph_data { ++ const char *name; ++ const char *source_pll; ++ unsigned int phase; ++ unsigned int fixed_divider; ++ u32 ph_reg; ++ unsigned long flags; ++ u32 fc0_src; ++}; ++ ++struct rp1_pll_divider_data { ++ const char *name; ++ const char *source_pll; ++ u32 sec_reg; ++ unsigned long flags; ++ u32 fc0_src; ++}; ++ ++struct rp1_clock_data { ++ const char *name; ++ const char *const parents[MAX_CLK_PARENTS]; ++ int num_std_parents; ++ int num_aux_parents; ++ unsigned long flags; ++ u32 clk_src_mask; ++ u32 ctrl_reg; ++ u32 div_int_reg; ++ u32 div_frac_reg; ++ u32 sel_reg; ++ u32 div_int_max; ++ u32 fc0_src; ++}; ++ ++struct rp1_pll_core { ++ struct clk_hw hw; ++ struct rp1_clockman *clockman; ++ const struct rp1_pll_core_data *data; ++ unsigned long cached_rate; ++}; ++ ++struct rp1_pll { ++ struct clk_hw hw; ++ struct clk_divider div; ++ struct rp1_clockman *clockman; ++ const struct rp1_pll_data *data; ++ unsigned long cached_rate; ++}; ++ ++struct rp1_pll_ph { ++ struct clk_hw hw; ++ struct rp1_clockman *clockman; ++ const struct rp1_pll_ph_data *data; ++}; ++ ++struct rp1_clock { ++ struct clk_hw hw; ++ struct rp1_clockman *clockman; ++ const struct rp1_clock_data *data; ++ unsigned long cached_rate; ++}; ++ ++static void rp1_debugfs_regset(struct rp1_clockman *clockman, u32 base, ++ const struct debugfs_reg32 *regs, ++ size_t nregs, struct dentry *dentry) ++{ ++ struct debugfs_regset32 *regset; ++ ++ regset = devm_kzalloc(clockman->dev, sizeof(*regset), GFP_KERNEL); ++ if (!regset) ++ return; ++ ++ regset->regs = regs; ++ regset->nregs = nregs; ++ regset->base = clockman->regs + base; ++ ++ debugfs_create_regset32("regdump", 0444, dentry, regset); ++} ++ ++static inline u32 set_register_field(u32 reg, u32 val, u32 mask, u32 shift) ++{ ++ reg &= ~mask; ++ reg |= (val << shift) & mask; ++ return reg; ++} ++ ++static inline ++void clockman_write(struct rp1_clockman *clockman, u32 reg, u32 val) ++{ ++ writel(val, clockman->regs + reg); ++} ++ ++static inline u32 clockman_read(struct rp1_clockman *clockman, u32 reg) ++{ ++ return readl(clockman->regs + reg); ++} ++ ++#ifdef MEASURE_CLOCK_RATE ++static unsigned long clockman_measure_clock(struct rp1_clockman *clockman, ++ const char *clk_name, ++ unsigned int fc0_src) ++{ ++ struct clk *ref_clk = __clk_lookup(fc0_ref_clk_name); ++ unsigned long result; ++ ktime_t timeout; ++ unsigned int fc_idx, fc_offset, fc_src; ++ ++ fc_idx = fc0_src / 32; ++ fc_src = fc0_src % 32; ++ ++ /* fc_src == 0 is invalid. */ ++ if (!fc_src || fc_idx >= FC_COUNT) ++ return 0; ++ ++ fc_offset = fc_idx * FC_SIZE; ++ ++ /* Ensure the frequency counter is idle. */ ++ timeout = ktime_add_ns(ktime_get(), FC_TIMEOUT_NS); ++ while (clockman_read(clockman, fc_offset + FC0_STATUS) & FC0_STATUS_RUNNING) { ++ if (ktime_after(ktime_get(), timeout)) { ++ dev_err(clockman->dev, "%s: FC0 busy timeout\n", ++ clk_name); ++ return 0; ++ } ++ cpu_relax(); ++ } ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, fc_offset + FC0_REF_KHZ, ++ clk_get_rate(ref_clk) / KHz); ++ clockman_write(clockman, fc_offset + FC0_MIN_KHZ, 0); ++ clockman_write(clockman, fc_offset + FC0_MAX_KHZ, 0x1ffffff); ++ clockman_write(clockman, fc_offset + FC0_INTERVAL, 8); ++ clockman_write(clockman, fc_offset + FC0_DELAY, 7); ++ clockman_write(clockman, fc_offset + FC0_SRC, fc_src); ++ spin_unlock(&clockman->regs_lock); ++ ++ /* Ensure the frequency counter is idle. */ ++ timeout = ktime_add_ns(ktime_get(), FC_TIMEOUT_NS); ++ while (!(clockman_read(clockman, fc_offset + FC0_STATUS) & FC0_STATUS_DONE)) { ++ if (ktime_after(ktime_get(), timeout)) { ++ dev_err(clockman->dev, "%s: FC0 wait timeout\n", ++ clk_name); ++ return 0; ++ } ++ cpu_relax(); ++ } ++ ++ result = clockman_read(clockman, fc_offset + FC0_RESULT); ++ ++ /* Disable FC0 */ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, fc_offset + FC0_SRC, 0); ++ spin_unlock(&clockman->regs_lock); ++ ++ return result; ++} ++#endif ++ ++static int rp1_pll_core_is_on(struct clk_hw *hw) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ u32 pwr = clockman_read(clockman, data->pwr_reg); ++ ++ return (pwr & PLL_PWR_PD) || (pwr & PLL_PWR_POSTDIVPD); ++} ++ ++static int rp1_pll_core_on(struct clk_hw *hw) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ u32 fbdiv_frac; ++ ktime_t timeout; ++ ++ spin_lock(&clockman->regs_lock); ++ ++ if (!(clockman_read(clockman, data->cs_reg) & PLL_CS_LOCK)) { ++ /* Reset to a known state. */ ++ clockman_write(clockman, data->pwr_reg, PLL_PWR_MASK); ++ clockman_write(clockman, data->fbdiv_int_reg, 20); ++ clockman_write(clockman, data->fbdiv_frac_reg, 0); ++ clockman_write(clockman, data->cs_reg, 1 << PLL_CS_REFDIV_SHIFT); ++ } ++ ++ /* Come out of reset. */ ++ fbdiv_frac = clockman_read(clockman, data->fbdiv_frac_reg); ++ clockman_write(clockman, data->pwr_reg, fbdiv_frac ? 0 : PLL_PWR_DSMPD); ++ spin_unlock(&clockman->regs_lock); ++ ++ /* Wait for the PLL to lock. */ ++ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS); ++ while (!(clockman_read(clockman, data->cs_reg) & PLL_CS_LOCK)) { ++ if (ktime_after(ktime_get(), timeout)) { ++ dev_err(clockman->dev, "%s: can't lock PLL\n", ++ clk_hw_get_name(hw)); ++ return -ETIMEDOUT; ++ } ++ cpu_relax(); ++ } ++ ++ return 0; ++} ++ ++static void rp1_pll_core_off(struct clk_hw *hw) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->pwr_reg, 0); ++ spin_unlock(&clockman->regs_lock); ++} ++ ++static inline unsigned long get_pll_core_divider(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate, ++ u32 *div_int, u32 *div_frac) ++{ ++ unsigned long calc_rate; ++ u32 fbdiv_int, fbdiv_frac; ++ u64 div_fp64; /* 32.32 fixed point fraction. */ ++ ++ /* Factor of reference clock to VCO frequency. */ ++ div_fp64 = (u64)(rate) << 32; ++ div_fp64 = DIV_U64_NEAREST(div_fp64, parent_rate); ++ ++ /* Round the fractional component at 24 bits. */ ++ div_fp64 += 1 << (32 - 24 - 1); ++ ++ fbdiv_int = div_fp64 >> 32; ++ fbdiv_frac = (div_fp64 >> (32 - 24)) & 0xffffff; ++ ++ calc_rate = ++ ((u64)parent_rate * (((u64)fbdiv_int << 24) + fbdiv_frac) + (1 << 23)) >> 24; ++ ++ *div_int = fbdiv_int; ++ *div_frac = fbdiv_frac; ++ ++ return calc_rate; ++} ++ ++static int rp1_pll_core_set_rate(struct clk_hw *hw, ++ unsigned long rate, unsigned long parent_rate) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ unsigned long calc_rate; ++ u32 fbdiv_int, fbdiv_frac; ++ ++ // todo: is this needed?? ++ //rp1_pll_off(hw); ++ ++ /* Disable dividers to start with. */ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->fbdiv_int_reg, 0); ++ clockman_write(clockman, data->fbdiv_frac_reg, 0); ++ spin_unlock(&clockman->regs_lock); ++ ++ calc_rate = get_pll_core_divider(hw, rate, parent_rate, ++ &fbdiv_int, &fbdiv_frac); ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->pwr_reg, fbdiv_frac ? 0 : PLL_PWR_DSMPD); ++ clockman_write(clockman, data->fbdiv_int_reg, fbdiv_int); ++ clockman_write(clockman, data->fbdiv_frac_reg, fbdiv_frac); ++ spin_unlock(&clockman->regs_lock); ++ ++ /* Check that reference frequency is no greater than VCO / 16. */ ++ BUG_ON(parent_rate > (rate / 16)); ++ ++ pll_core->cached_rate = calc_rate; ++ ++ spin_lock(&clockman->regs_lock); ++ /* Don't need to divide ref unless parent_rate > (output freq / 16) */ ++ clockman_write(clockman, data->cs_reg, ++ clockman_read(clockman, data->cs_reg) | ++ (1 << PLL_CS_REFDIV_SHIFT)); ++ spin_unlock(&clockman->regs_lock); ++ ++ return 0; ++} ++ ++static unsigned long rp1_pll_core_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ u32 fbdiv_int, fbdiv_frac; ++ unsigned long calc_rate; ++ ++ fbdiv_int = clockman_read(clockman, data->fbdiv_int_reg); ++ fbdiv_frac = clockman_read(clockman, data->fbdiv_frac_reg); ++ calc_rate = ++ ((u64)parent_rate * (((u64)fbdiv_int << 24) + fbdiv_frac) + (1 << 23)) >> 24; ++ ++ return calc_rate; ++} ++ ++static long rp1_pll_core_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ u32 fbdiv_int, fbdiv_frac; ++ long calc_rate; ++ ++ calc_rate = get_pll_core_divider(hw, rate, *parent_rate, ++ &fbdiv_int, &fbdiv_frac); ++ return calc_rate; ++} ++ ++static void rp1_pll_core_debug_init(struct clk_hw *hw, struct dentry *dentry) ++{ ++ struct rp1_pll_core *pll_core = container_of(hw, struct rp1_pll_core, hw); ++ struct rp1_clockman *clockman = pll_core->clockman; ++ const struct rp1_pll_core_data *data = pll_core->data; ++ struct debugfs_reg32 *regs; ++ ++ regs = devm_kcalloc(clockman->dev, 4, sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return; ++ ++ regs[0].name = "cs"; ++ regs[0].offset = data->cs_reg; ++ regs[1].name = "pwr"; ++ regs[1].offset = data->pwr_reg; ++ regs[2].name = "fbdiv_int"; ++ regs[2].offset = data->fbdiv_int_reg; ++ regs[3].name = "fbdiv_frac"; ++ regs[3].offset = data->fbdiv_frac_reg; ++ ++ rp1_debugfs_regset(clockman, 0, regs, 4, dentry); ++} ++ ++static void get_pll_prim_dividers(unsigned long rate, unsigned long parent_rate, ++ u32 *divider1, u32 *divider2) ++{ ++ unsigned int div1, div2; ++ unsigned int best_div1 = 7, best_div2 = 7; ++ unsigned long best_rate_diff = ++ ABS_DIFF(DIV_ROUND_CLOSEST(parent_rate, best_div1 * best_div2), rate); ++ long rate_diff, calc_rate; ++ ++ for (div1 = 1; div1 <= 7; div1++) { ++ for (div2 = 1; div2 <= div1; div2++) { ++ calc_rate = DIV_ROUND_CLOSEST(parent_rate, div1 * div2); ++ rate_diff = ABS_DIFF(calc_rate, rate); ++ ++ if (calc_rate == rate) { ++ best_div1 = div1; ++ best_div2 = div2; ++ goto done; ++ } else if (rate_diff < best_rate_diff) { ++ best_div1 = div1; ++ best_div2 = div2; ++ best_rate_diff = rate_diff; ++ } ++ } ++ } ++ ++done: ++ *divider1 = best_div1; ++ *divider2 = best_div2; ++} ++ ++static int rp1_pll_set_rate(struct clk_hw *hw, ++ unsigned long rate, unsigned long parent_rate) ++{ ++ struct rp1_pll *pll = container_of(hw, struct rp1_pll, hw); ++ struct rp1_clockman *clockman = pll->clockman; ++ const struct rp1_pll_data *data = pll->data; ++ u32 prim, prim_div1, prim_div2; ++ ++ get_pll_prim_dividers(rate, parent_rate, &prim_div1, &prim_div2); ++ ++ spin_lock(&clockman->regs_lock); ++ prim = clockman_read(clockman, data->ctrl_reg); ++ prim = set_register_field(prim, prim_div1, PLL_PRIM_DIV1_MASK, ++ PLL_PRIM_DIV1_SHIFT); ++ prim = set_register_field(prim, prim_div2, PLL_PRIM_DIV2_MASK, ++ PLL_PRIM_DIV2_SHIFT); ++ clockman_write(clockman, data->ctrl_reg, prim); ++ spin_unlock(&clockman->regs_lock); ++ ++#ifdef MEASURE_CLOCK_RATE ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static unsigned long rp1_pll_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rp1_pll *pll = container_of(hw, struct rp1_pll, hw); ++ struct rp1_clockman *clockman = pll->clockman; ++ const struct rp1_pll_data *data = pll->data; ++ u32 prim, prim_div1, prim_div2; ++ ++ prim = clockman_read(clockman, data->ctrl_reg); ++ prim_div1 = (prim & PLL_PRIM_DIV1_MASK) >> PLL_PRIM_DIV1_SHIFT; ++ prim_div2 = (prim & PLL_PRIM_DIV2_MASK) >> PLL_PRIM_DIV2_SHIFT; ++ ++ if (!prim_div1 || !prim_div2) { ++ dev_err(clockman->dev, "%s: (%s) zero divider value\n", ++ __func__, data->name); ++ return 0; ++ } ++ ++ return DIV_ROUND_CLOSEST(parent_rate, prim_div1 * prim_div2); ++} ++ ++static long rp1_pll_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ u32 div1, div2; ++ ++ get_pll_prim_dividers(rate, *parent_rate, &div1, &div2); ++ ++ return DIV_ROUND_CLOSEST(*parent_rate, div1 * div2); ++} ++ ++static void rp1_pll_debug_init(struct clk_hw *hw, ++ struct dentry *dentry) ++{ ++ struct rp1_pll *pll = container_of(hw, struct rp1_pll, hw); ++ struct rp1_clockman *clockman = pll->clockman; ++ const struct rp1_pll_data *data = pll->data; ++ struct debugfs_reg32 *regs; ++ ++ regs = devm_kcalloc(clockman->dev, 1, sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return; ++ ++ regs[0].name = "prim"; ++ regs[0].offset = data->ctrl_reg; ++ ++ rp1_debugfs_regset(clockman, 0, regs, 1, dentry); ++} ++ ++static int rp1_pll_ph_is_on(struct clk_hw *hw) ++{ ++ struct rp1_pll_ph *pll = container_of(hw, struct rp1_pll_ph, hw); ++ struct rp1_clockman *clockman = pll->clockman; ++ const struct rp1_pll_ph_data *data = pll->data; ++ ++ return !!(clockman_read(clockman, data->ph_reg) & PLL_PH_EN); ++} ++ ++static int rp1_pll_ph_on(struct clk_hw *hw) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ struct rp1_clockman *clockman = pll_ph->clockman; ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ u32 ph_reg; ++ ++ /* todo: ensure pri/sec is enabled! */ ++ spin_lock(&clockman->regs_lock); ++ ph_reg = clockman_read(clockman, data->ph_reg); ++ ph_reg |= data->phase << PLL_PH_PHASE_SHIFT; ++ ph_reg |= PLL_PH_EN; ++ clockman_write(clockman, data->ph_reg, ph_reg); ++ spin_unlock(&clockman->regs_lock); ++ ++#ifdef MEASURE_CLOCK_RATE ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static void rp1_pll_ph_off(struct clk_hw *hw) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ struct rp1_clockman *clockman = pll_ph->clockman; ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->ph_reg, ++ clockman_read(clockman, data->ph_reg) & ~PLL_PH_EN); ++ spin_unlock(&clockman->regs_lock); ++} ++ ++static int rp1_pll_ph_set_rate(struct clk_hw *hw, ++ unsigned long rate, unsigned long parent_rate) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ struct rp1_clockman *clockman = pll_ph->clockman; ++ ++ /* Nothing really to do here! */ ++ WARN_ON(data->fixed_divider != 1 && data->fixed_divider != 2); ++ WARN_ON(rate != parent_rate / data->fixed_divider); ++ ++#ifdef MEASURE_CLOCK_RATE ++ if (rp1_pll_ph_is_on(hw)) ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static unsigned long rp1_pll_ph_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ ++ return parent_rate / data->fixed_divider; ++} ++ ++static long rp1_pll_ph_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ ++ return *parent_rate / data->fixed_divider; ++} ++ ++static void rp1_pll_ph_debug_init(struct clk_hw *hw, ++ struct dentry *dentry) ++{ ++ struct rp1_pll_ph *pll_ph = container_of(hw, struct rp1_pll_ph, hw); ++ const struct rp1_pll_ph_data *data = pll_ph->data; ++ struct rp1_clockman *clockman = pll_ph->clockman; ++ struct debugfs_reg32 *regs; ++ ++ regs = devm_kcalloc(clockman->dev, 1, sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return; ++ ++ regs[0].name = "ph_reg"; ++ regs[0].offset = data->ph_reg; ++ ++ rp1_debugfs_regset(clockman, 0, regs, 1, dentry); ++} ++ ++static int rp1_pll_divider_is_on(struct clk_hw *hw) ++{ ++ struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); ++ struct rp1_clockman *clockman = divider->clockman; ++ const struct rp1_pll_data *data = divider->data; ++ ++ return !(clockman_read(clockman, data->ctrl_reg) & PLL_SEC_RST); ++} ++ ++static int rp1_pll_divider_on(struct clk_hw *hw) ++{ ++ struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); ++ struct rp1_clockman *clockman = divider->clockman; ++ const struct rp1_pll_data *data = divider->data; ++ ++ spin_lock(&clockman->regs_lock); ++ /* Check the implementation bit is set! */ ++ WARN_ON(!(clockman_read(clockman, data->ctrl_reg) & PLL_SEC_IMPL)); ++ clockman_write(clockman, data->ctrl_reg, ++ clockman_read(clockman, data->ctrl_reg) & ~PLL_SEC_RST); ++ spin_unlock(&clockman->regs_lock); ++ ++#ifdef MEASURE_CLOCK_RATE ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static void rp1_pll_divider_off(struct clk_hw *hw) ++{ ++ struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); ++ struct rp1_clockman *clockman = divider->clockman; ++ const struct rp1_pll_data *data = divider->data; ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->ctrl_reg, PLL_SEC_RST); ++ spin_unlock(&clockman->regs_lock); ++} ++ ++static int rp1_pll_divider_set_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); ++ struct rp1_clockman *clockman = divider->clockman; ++ const struct rp1_pll_data *data = divider->data; ++ u32 div, sec; ++ ++ div = DIV_ROUND_UP_ULL(parent_rate, rate); ++ div = clamp(div, 8u, 19u); ++ ++ spin_lock(&clockman->regs_lock); ++ sec = clockman_read(clockman, data->ctrl_reg); ++ sec = set_register_field(sec, div, PLL_SEC_DIV_MASK, PLL_SEC_DIV_SHIFT); ++ ++ /* Must keep the divider in reset to change the value. */ ++ sec |= PLL_SEC_RST; ++ clockman_write(clockman, data->ctrl_reg, sec); ++ ++ // todo: must sleep 10 pll vco cycles ++ sec &= ~PLL_SEC_RST; ++ clockman_write(clockman, data->ctrl_reg, sec); ++ spin_unlock(&clockman->regs_lock); ++ ++#ifdef MEASURE_CLOCK_RATE ++ if (rp1_pll_divider_is_on(hw)) ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static unsigned long rp1_pll_divider_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ return clk_divider_ops.recalc_rate(hw, parent_rate); ++} ++ ++static long rp1_pll_divider_round_rate(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ return clk_divider_ops.round_rate(hw, rate, parent_rate); ++} ++ ++static void rp1_pll_divider_debug_init(struct clk_hw *hw, struct dentry *dentry) ++{ ++ struct rp1_pll *divider = container_of(hw, struct rp1_pll, div.hw); ++ struct rp1_clockman *clockman = divider->clockman; ++ const struct rp1_pll_data *data = divider->data; ++ struct debugfs_reg32 *regs; ++ ++ regs = devm_kcalloc(clockman->dev, 1, sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return; ++ ++ regs[0].name = "sec"; ++ regs[0].offset = data->ctrl_reg; ++ ++ rp1_debugfs_regset(clockman, 0, regs, 1, dentry); ++} ++ ++static int rp1_clock_is_on(struct clk_hw *hw) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ ++ return !!(clockman_read(clockman, data->ctrl_reg) & CLK_CTRL_ENABLE); ++} ++ ++static unsigned long rp1_clock_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ u64 calc_rate; ++ u64 div; ++ ++ u32 frac; ++ ++ div = clockman_read(clockman, data->div_int_reg); ++ frac = (data->div_frac_reg != 0) ? ++ clockman_read(clockman, data->div_frac_reg) : 0; ++ ++ /* If the integer portion of the divider is 0, treat it as 2^16 */ ++ if (!div) ++ div = 1 << 16; ++ ++ div = (div << CLK_DIV_FRAC_BITS) | (frac >> (32 - CLK_DIV_FRAC_BITS)); ++ ++ calc_rate = (u64)parent_rate << CLK_DIV_FRAC_BITS; ++ calc_rate = div64_u64(calc_rate, div); ++ ++ return calc_rate; ++} ++ ++static int rp1_clock_on(struct clk_hw *hw) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->ctrl_reg, ++ clockman_read(clockman, data->ctrl_reg) | CLK_CTRL_ENABLE); ++ spin_unlock(&clockman->regs_lock); ++ ++#ifdef MEASURE_CLOCK_RATE ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static void rp1_clock_off(struct clk_hw *hw) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ ++ spin_lock(&clockman->regs_lock); ++ clockman_write(clockman, data->ctrl_reg, ++ clockman_read(clockman, data->ctrl_reg) & ~CLK_CTRL_ENABLE); ++ spin_unlock(&clockman->regs_lock); ++} ++ ++static u32 rp1_clock_choose_div(unsigned long rate, unsigned long parent_rate, ++ const struct rp1_clock_data *data) ++{ ++ u64 div; ++ ++ /* ++ * Due to earlier rounding, calculated parent_rate may differ from ++ * expected value. Don't fail on a small discrepancy near unity divide. ++ */ ++ if (!rate || rate > parent_rate + (parent_rate >> CLK_DIV_FRAC_BITS)) ++ return 0; ++ ++ /* ++ * Always express div in fixed-point format for fractional division; ++ * If no fractional divider is present, the fraction part will be zero. ++ */ ++ if (data->div_frac_reg) { ++ div = (u64)parent_rate << CLK_DIV_FRAC_BITS; ++ div = DIV_U64_NEAREST(div, rate); ++ } else { ++ div = DIV_U64_NEAREST(parent_rate, rate); ++ div <<= CLK_DIV_FRAC_BITS; ++ } ++ ++ div = clamp(div, ++ 1ull << CLK_DIV_FRAC_BITS, ++ (u64)data->div_int_max << CLK_DIV_FRAC_BITS); ++ ++ return div; ++} ++ ++static u8 rp1_clock_get_parent(struct clk_hw *hw) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ u32 sel, ctrl; ++ u8 parent; ++ ++ /* Sel is one-hot, so find the first bit set */ ++ sel = clockman_read(clockman, data->sel_reg); ++ parent = ffs(sel) - 1; ++ ++ /* sel == 0 implies the parent clock is not enabled yet. */ ++ if (!sel) { ++ /* Read the clock src from the CTRL register instead */ ++ ctrl = clockman_read(clockman, data->ctrl_reg); ++ parent = (ctrl & data->clk_src_mask) >> CLK_CTRL_SRC_SHIFT; ++ } ++ ++ if (parent >= data->num_std_parents) ++ parent = AUX_SEL; ++ ++ if (parent == AUX_SEL) { ++ /* ++ * Clock parent is an auxiliary source, so get the parent from ++ * the AUXSRC register field. ++ */ ++ ctrl = clockman_read(clockman, data->ctrl_reg); ++ parent = (ctrl & CLK_CTRL_AUXSRC_MASK) >> CLK_CTRL_AUXSRC_SHIFT; ++ parent += data->num_std_parents; ++ } ++ ++ return parent; ++} ++ ++static int rp1_clock_set_parent(struct clk_hw *hw, u8 index) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ u32 ctrl, sel; ++ ++ spin_lock(&clockman->regs_lock); ++ ctrl = clockman_read(clockman, data->ctrl_reg); ++ ++ if (index >= data->num_std_parents) { ++ /* This is an aux source request */ ++ if (index >= data->num_std_parents + data->num_aux_parents) ++ return -EINVAL; ++ ++ /* Select parent from aux list */ ++ ctrl = set_register_field(ctrl, index - data->num_std_parents, ++ CLK_CTRL_AUXSRC_MASK, ++ CLK_CTRL_AUXSRC_SHIFT); ++ /* Set src to aux list */ ++ ctrl = set_register_field(ctrl, AUX_SEL, data->clk_src_mask, ++ CLK_CTRL_SRC_SHIFT); ++ } else { ++ ctrl = set_register_field(ctrl, index, data->clk_src_mask, ++ CLK_CTRL_SRC_SHIFT); ++ } ++ ++ clockman_write(clockman, data->ctrl_reg, ctrl); ++ spin_unlock(&clockman->regs_lock); ++ ++ sel = rp1_clock_get_parent(hw); ++ WARN(sel != index, "(%s): Parent index req %u returned back %u\n", ++ data->name, index, sel); ++ ++ return 0; ++} ++ ++static int rp1_clock_set_rate_and_parent(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long parent_rate, ++ u8 parent) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ u32 div = rp1_clock_choose_div(rate, parent_rate, data); ++ ++ WARN(rate > 4000000000ll, "rate is -ve (%d)\n", (int)rate); ++ ++ if (WARN(!div, ++ "clk divider calculated as 0! (%s, rate %ld, parent rate %ld)\n", ++ data->name, rate, parent_rate)) ++ div = 1 << CLK_DIV_FRAC_BITS; ++ ++ spin_lock(&clockman->regs_lock); ++ ++ clockman_write(clockman, data->div_int_reg, div >> CLK_DIV_FRAC_BITS); ++ if (data->div_frac_reg) ++ clockman_write(clockman, data->div_frac_reg, div << (32 - CLK_DIV_FRAC_BITS)); ++ ++ spin_unlock(&clockman->regs_lock); ++ ++ if (parent != 0xff) ++ rp1_clock_set_parent(hw, parent); ++ ++#ifdef MEASURE_CLOCK_RATE ++ if (rp1_clock_is_on(hw)) ++ clockman_measure_clock(clockman, data->name, data->fc0_src); ++#endif ++ return 0; ++} ++ ++static int rp1_clock_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ return rp1_clock_set_rate_and_parent(hw, rate, parent_rate, 0xff); ++} ++ ++static void rp1_clock_choose_div_and_prate(struct clk_hw *hw, ++ int parent_idx, ++ unsigned long rate, ++ unsigned long *prate, ++ unsigned long *calc_rate) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ const struct rp1_clock_data *data = clock->data; ++ struct clk_hw *parent; ++ u32 div; ++ u64 tmp; ++ ++ parent = clk_hw_get_parent_by_index(hw, parent_idx); ++ *prate = clk_hw_get_rate(parent); ++ div = rp1_clock_choose_div(rate, *prate, data); ++ ++ if (!div) { ++ *calc_rate = 0; ++ return; ++ } ++ ++ /* Recalculate to account for rounding errors */ ++ tmp = (u64)*prate << CLK_DIV_FRAC_BITS; ++ tmp = div_u64(tmp, div); ++ *calc_rate = tmp; ++} ++ ++static int rp1_clock_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ struct clk_hw *parent, *best_parent = NULL; ++ unsigned long best_rate = 0; ++ unsigned long best_prate = 0; ++ unsigned long best_rate_diff = ULONG_MAX; ++ unsigned long prate, calc_rate; ++ size_t i; ++ ++ /* ++ * If the NO_REPARENT flag is set, try to use existing parent. ++ */ ++ if ((clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT)) { ++ i = rp1_clock_get_parent(hw); ++ parent = clk_hw_get_parent_by_index(hw, i); ++ if (parent) { ++ rp1_clock_choose_div_and_prate(hw, i, req->rate, &prate, ++ &calc_rate); ++ if (calc_rate > 0) { ++ req->best_parent_hw = parent; ++ req->best_parent_rate = prate; ++ req->rate = calc_rate; ++ return 0; ++ } ++ } ++ } ++ ++ /* ++ * Select parent clock that results in the closest rate (lower or ++ * higher) ++ */ ++ for (i = 0; i < clk_hw_get_num_parents(hw); i++) { ++ parent = clk_hw_get_parent_by_index(hw, i); ++ if (!parent) ++ continue; ++ ++ rp1_clock_choose_div_and_prate(hw, i, req->rate, &prate, ++ &calc_rate); ++ ++ if (ABS_DIFF(calc_rate, req->rate) < best_rate_diff) { ++ best_parent = parent; ++ best_prate = prate; ++ best_rate = calc_rate; ++ best_rate_diff = ABS_DIFF(calc_rate, req->rate); ++ ++ if (best_rate_diff == 0) ++ break; ++ } ++ } ++ ++ if (best_rate == 0) ++ return -EINVAL; ++ ++ req->best_parent_hw = best_parent; ++ req->best_parent_rate = best_prate; ++ req->rate = best_rate; ++ ++ return 0; ++} ++ ++static void rp1_clk_debug_init(struct clk_hw *hw, struct dentry *dentry) ++{ ++ struct rp1_clock *clock = container_of(hw, struct rp1_clock, hw); ++ struct rp1_clockman *clockman = clock->clockman; ++ const struct rp1_clock_data *data = clock->data; ++ struct debugfs_reg32 *regs; ++ int i; ++ ++ regs = devm_kcalloc(clockman->dev, 4, sizeof(*regs), GFP_KERNEL); ++ if (!regs) ++ return; ++ ++ i = 0; ++ regs[i].name = "ctrl"; ++ regs[i++].offset = data->ctrl_reg; ++ regs[i].name = "div_int"; ++ regs[i++].offset = data->div_int_reg; ++ regs[i].name = "div_frac"; ++ regs[i++].offset = data->div_frac_reg; ++ regs[i].name = "sel"; ++ regs[i++].offset = data->sel_reg; ++ ++ rp1_debugfs_regset(clockman, 0, regs, i, dentry); ++} ++ ++static const struct clk_ops rp1_pll_core_ops = { ++ .is_prepared = rp1_pll_core_is_on, ++ .prepare = rp1_pll_core_on, ++ .unprepare = rp1_pll_core_off, ++ .set_rate = rp1_pll_core_set_rate, ++ .recalc_rate = rp1_pll_core_recalc_rate, ++ .round_rate = rp1_pll_core_round_rate, ++ .debug_init = rp1_pll_core_debug_init, ++}; ++ ++static const struct clk_ops rp1_pll_ops = { ++ .set_rate = rp1_pll_set_rate, ++ .recalc_rate = rp1_pll_recalc_rate, ++ .round_rate = rp1_pll_round_rate, ++ .debug_init = rp1_pll_debug_init, ++}; ++ ++static const struct clk_ops rp1_pll_ph_ops = { ++ .is_prepared = rp1_pll_ph_is_on, ++ .prepare = rp1_pll_ph_on, ++ .unprepare = rp1_pll_ph_off, ++ .set_rate = rp1_pll_ph_set_rate, ++ .recalc_rate = rp1_pll_ph_recalc_rate, ++ .round_rate = rp1_pll_ph_round_rate, ++ .debug_init = rp1_pll_ph_debug_init, ++}; ++ ++static const struct clk_ops rp1_pll_divider_ops = { ++ .is_prepared = rp1_pll_divider_is_on, ++ .prepare = rp1_pll_divider_on, ++ .unprepare = rp1_pll_divider_off, ++ .set_rate = rp1_pll_divider_set_rate, ++ .recalc_rate = rp1_pll_divider_recalc_rate, ++ .round_rate = rp1_pll_divider_round_rate, ++ .debug_init = rp1_pll_divider_debug_init, ++}; ++ ++static const struct clk_ops rp1_clk_ops = { ++ .is_prepared = rp1_clock_is_on, ++ .prepare = rp1_clock_on, ++ .unprepare = rp1_clock_off, ++ .recalc_rate = rp1_clock_recalc_rate, ++ .get_parent = rp1_clock_get_parent, ++ .set_parent = rp1_clock_set_parent, ++ .set_rate_and_parent = rp1_clock_set_rate_and_parent, ++ .set_rate = rp1_clock_set_rate, ++ .determine_rate = rp1_clock_determine_rate, ++ .debug_init = rp1_clk_debug_init, ++}; ++ ++static bool rp1_clk_is_claimed(const char *name); ++ ++static struct clk_hw *rp1_register_pll_core(struct rp1_clockman *clockman, ++ const void *data) ++{ ++ const struct rp1_pll_core_data *pll_core_data = data; ++ struct rp1_pll_core *pll_core; ++ struct clk_init_data init; ++ int ret; ++ ++ memset(&init, 0, sizeof(init)); ++ ++ /* All of the PLL cores derive from the external oscillator. */ ++ init.parent_names = &ref_clock; ++ init.num_parents = 1; ++ init.name = pll_core_data->name; ++ init.ops = &rp1_pll_core_ops; ++ init.flags = pll_core_data->flags | CLK_IGNORE_UNUSED | CLK_IS_CRITICAL; ++ ++ pll_core = kzalloc(sizeof(*pll_core), GFP_KERNEL); ++ if (!pll_core) ++ return NULL; ++ ++ pll_core->clockman = clockman; ++ pll_core->data = pll_core_data; ++ pll_core->hw.init = &init; ++ ++ ret = devm_clk_hw_register(clockman->dev, &pll_core->hw); ++ if (ret) { ++ kfree(pll_core); ++ return NULL; ++ } ++ ++ return &pll_core->hw; ++} ++ ++static struct clk_hw *rp1_register_pll(struct rp1_clockman *clockman, ++ const void *data) ++{ ++ const struct rp1_pll_data *pll_data = data; ++ struct rp1_pll *pll; ++ struct clk_init_data init; ++ int ret; ++ ++ memset(&init, 0, sizeof(init)); ++ ++ init.parent_names = &pll_data->source_pll; ++ init.num_parents = 1; ++ init.name = pll_data->name; ++ init.ops = &rp1_pll_ops; ++ init.flags = pll_data->flags | CLK_IGNORE_UNUSED | CLK_IS_CRITICAL; ++ ++ pll = kzalloc(sizeof(*pll), GFP_KERNEL); ++ if (!pll) ++ return NULL; ++ ++ pll->clockman = clockman; ++ pll->data = pll_data; ++ pll->hw.init = &init; ++ ++ ret = devm_clk_hw_register(clockman->dev, &pll->hw); ++ if (ret) { ++ kfree(pll); ++ return NULL; ++ } ++ ++ return &pll->hw; ++} ++ ++static struct clk_hw *rp1_register_pll_ph(struct rp1_clockman *clockman, ++ const void *data) ++{ ++ const struct rp1_pll_ph_data *ph_data = data; ++ struct rp1_pll_ph *ph; ++ struct clk_init_data init; ++ int ret; ++ ++ memset(&init, 0, sizeof(init)); ++ ++ /* All of the PLLs derive from the external oscillator. */ ++ init.parent_names = &ph_data->source_pll; ++ init.num_parents = 1; ++ init.name = ph_data->name; ++ init.ops = &rp1_pll_ph_ops; ++ init.flags = ph_data->flags | CLK_IGNORE_UNUSED; ++ ++ ph = kzalloc(sizeof(*ph), GFP_KERNEL); ++ if (!ph) ++ return NULL; ++ ++ ph->clockman = clockman; ++ ph->data = ph_data; ++ ph->hw.init = &init; ++ ++ ret = devm_clk_hw_register(clockman->dev, &ph->hw); ++ if (ret) { ++ kfree(ph); ++ return NULL; ++ } ++ ++ return &ph->hw; ++} ++ ++static struct clk_hw *rp1_register_pll_divider(struct rp1_clockman *clockman, ++ const void *data) ++{ ++ const struct rp1_pll_data *divider_data = data; ++ struct rp1_pll *divider; ++ struct clk_init_data init; ++ int ret; ++ ++ memset(&init, 0, sizeof(init)); ++ ++ init.parent_names = ÷r_data->source_pll; ++ init.num_parents = 1; ++ init.name = divider_data->name; ++ init.ops = &rp1_pll_divider_ops; ++ init.flags = divider_data->flags | CLK_IGNORE_UNUSED; ++ ++ divider = devm_kzalloc(clockman->dev, sizeof(*divider), GFP_KERNEL); ++ if (!divider) ++ return NULL; ++ ++ divider->div.reg = clockman->regs + divider_data->ctrl_reg; ++ divider->div.shift = PLL_SEC_DIV_SHIFT; ++ divider->div.width = PLL_SEC_DIV_WIDTH; ++ divider->div.flags = CLK_DIVIDER_ROUND_CLOSEST; ++ divider->div.lock = &clockman->regs_lock; ++ divider->div.hw.init = &init; ++ divider->div.table = pll_sec_div_table; ++ ++ if (!rp1_clk_is_claimed(divider_data->source_pll)) ++ init.flags |= CLK_IS_CRITICAL; ++ if (!rp1_clk_is_claimed(divider_data->name)) ++ divider->div.flags |= CLK_IS_CRITICAL; ++ ++ divider->clockman = clockman; ++ divider->data = divider_data; ++ ++ ret = devm_clk_hw_register(clockman->dev, ÷r->div.hw); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ return ÷r->div.hw; ++} ++ ++static struct clk_hw *rp1_register_clock(struct rp1_clockman *clockman, ++ const void *data) ++{ ++ const struct rp1_clock_data *clock_data = data; ++ struct rp1_clock *clock; ++ struct clk_init_data init; ++ int ret; ++ ++ BUG_ON(MAX_CLK_PARENTS < ++ clock_data->num_std_parents + clock_data->num_aux_parents); ++ /* There must be a gap for the AUX selector */ ++ BUG_ON((clock_data->num_std_parents > AUX_SEL) && ++ strcmp("-", clock_data->parents[AUX_SEL])); ++ ++ memset(&init, 0, sizeof(init)); ++ init.parent_names = clock_data->parents; ++ init.num_parents = ++ clock_data->num_std_parents + clock_data->num_aux_parents; ++ init.name = clock_data->name; ++ init.flags = clock_data->flags | CLK_IGNORE_UNUSED; ++ init.ops = &rp1_clk_ops; ++ ++ clock = devm_kzalloc(clockman->dev, sizeof(*clock), GFP_KERNEL); ++ if (!clock) ++ return NULL; ++ ++ clock->clockman = clockman; ++ clock->data = clock_data; ++ clock->hw.init = &init; ++ ++ ret = devm_clk_hw_register(clockman->dev, &clock->hw); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ return &clock->hw; ++} ++ ++struct rp1_clk_desc { ++ struct clk_hw *(*clk_register)(struct rp1_clockman *clockman, ++ const void *data); ++ const void *data; ++}; ++ ++/* Assignment helper macros for different clock types. */ ++#define _REGISTER(f, ...) { .clk_register = f, .data = __VA_ARGS__ } ++ ++#define REGISTER_PLL_CORE(...) _REGISTER(&rp1_register_pll_core, \ ++ &(struct rp1_pll_core_data) \ ++ {__VA_ARGS__}) ++ ++#define REGISTER_PLL(...) _REGISTER(&rp1_register_pll, \ ++ &(struct rp1_pll_data) \ ++ {__VA_ARGS__}) ++ ++#define REGISTER_PLL_PH(...) _REGISTER(&rp1_register_pll_ph, \ ++ &(struct rp1_pll_ph_data) \ ++ {__VA_ARGS__}) ++ ++#define REGISTER_PLL_DIV(...) _REGISTER(&rp1_register_pll_divider, \ ++ &(struct rp1_pll_data) \ ++ {__VA_ARGS__}) ++ ++#define REGISTER_CLK(...) _REGISTER(&rp1_register_clock, \ ++ &(struct rp1_clock_data) \ ++ {__VA_ARGS__}) ++ ++static const struct rp1_clk_desc clk_desc_array[] = { ++ [RP1_PLL_SYS_CORE] = REGISTER_PLL_CORE( ++ .name = "pll_sys_core", ++ .cs_reg = PLL_SYS_CS, ++ .pwr_reg = PLL_SYS_PWR, ++ .fbdiv_int_reg = PLL_SYS_FBDIV_INT, ++ .fbdiv_frac_reg = PLL_SYS_FBDIV_FRAC, ++ ), ++ ++ [RP1_PLL_AUDIO_CORE] = REGISTER_PLL_CORE( ++ .name = "pll_audio_core", ++ .cs_reg = PLL_AUDIO_CS, ++ .pwr_reg = PLL_AUDIO_PWR, ++ .fbdiv_int_reg = PLL_AUDIO_FBDIV_INT, ++ .fbdiv_frac_reg = PLL_AUDIO_FBDIV_FRAC, ++ ), ++ ++ [RP1_PLL_VIDEO_CORE] = REGISTER_PLL_CORE( ++ .name = "pll_video_core", ++ .cs_reg = PLL_VIDEO_CS, ++ .pwr_reg = PLL_VIDEO_PWR, ++ .fbdiv_int_reg = PLL_VIDEO_FBDIV_INT, ++ .fbdiv_frac_reg = PLL_VIDEO_FBDIV_FRAC, ++ ), ++ ++ [RP1_PLL_SYS] = REGISTER_PLL( ++ .name = "pll_sys", ++ .source_pll = "pll_sys_core", ++ .ctrl_reg = PLL_SYS_PRIM, ++ .fc0_src = FC_NUM(0, 2), ++ ), ++ ++ [RP1_PLL_AUDIO] = REGISTER_PLL( ++ .name = "pll_audio", ++ .source_pll = "pll_audio_core", ++ .ctrl_reg = PLL_AUDIO_PRIM, ++ .fc0_src = FC_NUM(4, 2), ++ ), ++ ++ [RP1_PLL_VIDEO] = REGISTER_PLL( ++ .name = "pll_video", ++ .source_pll = "pll_video_core", ++ .ctrl_reg = PLL_VIDEO_PRIM, ++ .fc0_src = FC_NUM(3, 2), ++ ), ++ ++ [RP1_PLL_SYS_PRI_PH] = REGISTER_PLL_PH( ++ .name = "pll_sys_pri_ph", ++ .source_pll = "pll_sys", ++ .ph_reg = PLL_SYS_PRIM, ++ .fixed_divider = 2, ++ .phase = RP1_PLL_PHASE_0, ++ .fc0_src = FC_NUM(1, 2), ++ ), ++ ++ [RP1_PLL_AUDIO_PRI_PH] = REGISTER_PLL_PH( ++ .name = "pll_audio_pri_ph", ++ .source_pll = "pll_audio", ++ .ph_reg = PLL_AUDIO_PRIM, ++ .fixed_divider = 2, ++ .phase = RP1_PLL_PHASE_0, ++ .fc0_src = FC_NUM(5, 1), ++ ), ++ ++ [RP1_PLL_SYS_SEC] = REGISTER_PLL_DIV( ++ .name = "pll_sys_sec", ++ .source_pll = "pll_sys_core", ++ .ctrl_reg = PLL_SYS_SEC, ++ .fc0_src = FC_NUM(2, 2), ++ ), ++ ++ [RP1_PLL_AUDIO_SEC] = REGISTER_PLL_DIV( ++ .name = "pll_audio_sec", ++ .source_pll = "pll_audio_core", ++ .ctrl_reg = PLL_AUDIO_SEC, ++ .fc0_src = FC_NUM(6, 2), ++ ), ++ ++ [RP1_PLL_VIDEO_SEC] = REGISTER_PLL_DIV( ++ .name = "pll_video_sec", ++ .source_pll = "pll_video_core", ++ .ctrl_reg = PLL_VIDEO_SEC, ++ .fc0_src = FC_NUM(5, 3), ++ ), ++ ++ [RP1_CLK_SYS] = REGISTER_CLK( ++ .name = "clk_sys", ++ .parents = {"xosc", "-", "pll_sys"}, ++ .num_std_parents = 3, ++ .num_aux_parents = 0, ++ .ctrl_reg = CLK_SYS_CTRL, ++ .div_int_reg = CLK_SYS_DIV_INT, ++ .sel_reg = CLK_SYS_SEL, ++ .div_int_max = DIV_INT_24BIT_MAX, ++ .fc0_src = FC_NUM(0, 4), ++ .clk_src_mask = 0x3, ++ ), ++ ++ [RP1_CLK_SLOW_SYS] = REGISTER_CLK( ++ .name = "clk_slow_sys", ++ .parents = {"xosc"}, ++ .num_std_parents = 1, ++ .num_aux_parents = 0, ++ .ctrl_reg = CLK_SLOW_SYS_CTRL, ++ .div_int_reg = CLK_SLOW_SYS_DIV_INT, ++ .sel_reg = CLK_SLOW_SYS_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(1, 4), ++ .clk_src_mask = 0x1, ++ ), ++ ++ [RP1_CLK_UART] = REGISTER_CLK( ++ .name = "clk_uart", ++ .parents = {"pll_sys_pri_ph", ++ "pll_video", ++ "xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 3, ++ .ctrl_reg = CLK_UART_CTRL, ++ .div_int_reg = CLK_UART_DIV_INT, ++ .sel_reg = CLK_UART_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(6, 7), ++ ), ++ ++ [RP1_CLK_ETH] = REGISTER_CLK( ++ .name = "clk_eth", ++ .parents = {"-"}, ++ .num_std_parents = 1, ++ .num_aux_parents = 0, ++ .ctrl_reg = CLK_ETH_CTRL, ++ .div_int_reg = CLK_ETH_DIV_INT, ++ .sel_reg = CLK_ETH_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(4, 6), ++ ), ++ ++ [RP1_CLK_PWM0] = REGISTER_CLK( ++ .name = "clk_pwm0", ++ .parents = {"pll_audio_pri_ph", ++ "pll_video_sec", ++ "xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 3, ++ .ctrl_reg = CLK_PWM0_CTRL, ++ .div_int_reg = CLK_PWM0_DIV_INT, ++ .div_frac_reg = CLK_PWM0_DIV_FRAC, ++ .sel_reg = CLK_PWM0_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(0, 5), ++ ), ++ ++ [RP1_CLK_PWM1] = REGISTER_CLK( ++ .name = "clk_pwm1", ++ .parents = {"pll_audio_pri_ph", ++ "pll_video_sec", ++ "xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 3, ++ .ctrl_reg = CLK_PWM1_CTRL, ++ .div_int_reg = CLK_PWM1_DIV_INT, ++ .div_frac_reg = CLK_PWM1_DIV_FRAC, ++ .sel_reg = CLK_PWM1_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(1, 5), ++ ), ++ ++ [RP1_CLK_AUDIO_IN] = REGISTER_CLK( ++ .name = "clk_audio_in", ++ .parents = {"-"}, ++ .num_std_parents = 1, ++ .num_aux_parents = 0, ++ .ctrl_reg = CLK_AUDIO_IN_CTRL, ++ .div_int_reg = CLK_AUDIO_IN_DIV_INT, ++ .sel_reg = CLK_AUDIO_IN_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(2, 5), ++ ), ++ ++ [RP1_CLK_AUDIO_OUT] = REGISTER_CLK( ++ .name = "clk_audio_out", ++ .parents = {"-"}, ++ .num_std_parents = 1, ++ .num_aux_parents = 0, ++ .ctrl_reg = CLK_AUDIO_OUT_CTRL, ++ .div_int_reg = CLK_AUDIO_OUT_DIV_INT, ++ .sel_reg = CLK_AUDIO_OUT_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(3, 5), ++ ), ++ ++ [RP1_CLK_I2S] = REGISTER_CLK( ++ .name = "clk_i2s", ++ .parents = {"xosc", ++ "pll_audio", ++ "pll_audio_sec"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 3, ++ .ctrl_reg = CLK_I2S_CTRL, ++ .div_int_reg = CLK_I2S_DIV_INT, ++ .sel_reg = CLK_I2S_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(4, 4), ++ ), ++ ++ [RP1_CLK_MIPI0_CFG] = REGISTER_CLK( ++ .name = "clk_mipi0_cfg", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_MIPI0_CFG_CTRL, ++ .div_int_reg = CLK_MIPI0_CFG_DIV_INT, ++ .sel_reg = CLK_MIPI0_CFG_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(4, 5), ++ ), ++ ++ [RP1_CLK_MIPI1_CFG] = REGISTER_CLK( ++ .name = "clk_mipi1_cfg", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_MIPI1_CFG_CTRL, ++ .div_int_reg = CLK_MIPI1_CFG_DIV_INT, ++ .sel_reg = CLK_MIPI1_CFG_SEL, ++ .clk_src_mask = 1, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(5, 6), ++ ), ++ ++ [RP1_CLK_ETH_TSU] = REGISTER_CLK( ++ .name = "clk_eth_tsu", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_ETH_TSU_CTRL, ++ .div_int_reg = CLK_ETH_TSU_DIV_INT, ++ .sel_reg = CLK_ETH_TSU_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(5, 7), ++ ), ++ ++ [RP1_CLK_ADC] = REGISTER_CLK( ++ .name = "clk_adc", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_ADC_CTRL, ++ .div_int_reg = CLK_ADC_DIV_INT, ++ .sel_reg = CLK_ADC_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(5, 5), ++ ), ++ ++ [RP1_CLK_SDIO_TIMER] = REGISTER_CLK( ++ .name = "clk_sdio_timer", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_SDIO_TIMER_CTRL, ++ .div_int_reg = CLK_SDIO_TIMER_DIV_INT, ++ .sel_reg = CLK_SDIO_TIMER_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(3, 4), ++ ), ++ ++ [RP1_CLK_SDIO_ALT_SRC] = REGISTER_CLK( ++ .name = "clk_sdio_alt_src", ++ .parents = {"pll_sys"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_SDIO_ALT_SRC_CTRL, ++ .div_int_reg = CLK_SDIO_ALT_SRC_DIV_INT, ++ .sel_reg = CLK_SDIO_ALT_SRC_SEL, ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(5, 4), ++ ), ++ ++ [RP1_CLK_GP0] = REGISTER_CLK( ++ .name = "clk_gp0", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP0_CTRL, ++ .div_int_reg = CLK_GP0_DIV_INT, ++ .div_frac_reg = CLK_GP0_DIV_FRAC, ++ .sel_reg = CLK_GP0_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(0, 1), ++ ), ++ ++ [RP1_CLK_GP1] = REGISTER_CLK( ++ .name = "clk_gp1", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP1_CTRL, ++ .div_int_reg = CLK_GP1_DIV_INT, ++ .div_frac_reg = CLK_GP1_DIV_FRAC, ++ .sel_reg = CLK_GP1_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(1, 1), ++ ), ++ ++ [RP1_CLK_GP2] = REGISTER_CLK( ++ .name = "clk_gp2", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP2_CTRL, ++ .div_int_reg = CLK_GP2_DIV_INT, ++ .div_frac_reg = CLK_GP2_DIV_FRAC, ++ .sel_reg = CLK_GP2_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(2, 1), ++ ), ++ ++ [RP1_CLK_GP3] = REGISTER_CLK( ++ .name = "clk_gp3", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP3_CTRL, ++ .div_int_reg = CLK_GP3_DIV_INT, ++ .div_frac_reg = CLK_GP3_DIV_FRAC, ++ .sel_reg = CLK_GP3_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(3, 1), ++ ), ++ ++ [RP1_CLK_GP4] = REGISTER_CLK( ++ .name = "clk_gp4", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP4_CTRL, ++ .div_int_reg = CLK_GP4_DIV_INT, ++ .div_frac_reg = CLK_GP4_DIV_FRAC, ++ .sel_reg = CLK_GP4_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(4, 1), ++ ), ++ ++ [RP1_CLK_GP5] = REGISTER_CLK( ++ .name = "clk_gp5", ++ .parents = {"xosc"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 1, ++ .ctrl_reg = CLK_GP5_CTRL, ++ .div_int_reg = CLK_GP5_DIV_INT, ++ .div_frac_reg = CLK_GP5_DIV_FRAC, ++ .sel_reg = CLK_GP5_SEL, ++ .div_int_max = DIV_INT_16BIT_MAX, ++ .fc0_src = FC_NUM(5, 1), ++ ), ++ ++ [RP1_CLK_VEC] = REGISTER_CLK( ++ .name = "clk_vec", ++ .parents = {"pll_sys_pri_ph", ++ "pll_video_sec", ++ "pll_video", ++ "clk_gp0", ++ "clk_gp1", ++ "clk_gp2", ++ "clk_gp3", ++ "clk_gp4"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 8, /* XXX in fact there are more than 8 */ ++ .ctrl_reg = VIDEO_CLK_VEC_CTRL, ++ .div_int_reg = VIDEO_CLK_VEC_DIV_INT, ++ .sel_reg = VIDEO_CLK_VEC_SEL, ++ .flags = CLK_SET_RATE_NO_REPARENT, /* Let VEC driver set parent */ ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(0, 6), ++ ), ++ ++ [RP1_CLK_DPI] = REGISTER_CLK( ++ .name = "clk_dpi", ++ .parents = {"pll_sys", ++ "pll_video_sec", ++ "pll_video", ++ "clk_gp0", ++ "clk_gp1", ++ "clk_gp2", ++ "clk_gp3", ++ "clk_gp4"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 8, /* XXX in fact there are more than 8 */ ++ .ctrl_reg = VIDEO_CLK_DPI_CTRL, ++ .div_int_reg = VIDEO_CLK_DPI_DIV_INT, ++ .sel_reg = VIDEO_CLK_DPI_SEL, ++ .flags = CLK_SET_RATE_NO_REPARENT, /* Let DPI driver set parent */ ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(1, 6), ++ ), ++ ++ [RP1_CLK_MIPI0_DPI] = REGISTER_CLK( ++ .name = "clk_mipi0_dpi", ++ .parents = {"pll_sys", ++ "pll_video_sec", ++ "pll_video", ++ "clksrc_mipi0_dsi_byteclk", ++ "clk_gp0", ++ "clk_gp1", ++ "clk_gp2", ++ "clk_gp3"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 8, /* XXX in fact there are more than 8 */ ++ .ctrl_reg = VIDEO_CLK_MIPI0_DPI_CTRL, ++ .div_int_reg = VIDEO_CLK_MIPI0_DPI_DIV_INT, ++ .div_frac_reg = VIDEO_CLK_MIPI0_DPI_DIV_FRAC, ++ .sel_reg = VIDEO_CLK_MIPI0_DPI_SEL, ++ .flags = CLK_SET_RATE_NO_REPARENT, /* Let DSI driver set parent */ ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(2, 6), ++ ), ++ ++ [RP1_CLK_MIPI1_DPI] = REGISTER_CLK( ++ .name = "clk_mipi1_dpi", ++ .parents = {"pll_sys", ++ "pll_video_sec", ++ "pll_video", ++ "clksrc_mipi1_dsi_byteclk", ++ "clk_gp0", ++ "clk_gp1", ++ "clk_gp2", ++ "clk_gp3"}, ++ .num_std_parents = 0, ++ .num_aux_parents = 8, /* XXX in fact there are more than 8 */ ++ .ctrl_reg = VIDEO_CLK_MIPI1_DPI_CTRL, ++ .div_int_reg = VIDEO_CLK_MIPI1_DPI_DIV_INT, ++ .div_frac_reg = VIDEO_CLK_MIPI1_DPI_DIV_FRAC, ++ .sel_reg = VIDEO_CLK_MIPI1_DPI_SEL, ++ .flags = CLK_SET_RATE_NO_REPARENT, /* Let DSI driver set parent */ ++ .div_int_max = DIV_INT_8BIT_MAX, ++ .fc0_src = FC_NUM(3, 6), ++ ), ++}; ++ ++static bool rp1_clk_claimed[ARRAY_SIZE(clk_desc_array)]; ++ ++static bool rp1_clk_is_claimed(const char *name) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(clk_desc_array); i++) { ++ if (clk_desc_array[i].data) { ++ const char *clk_name = *(const char **)(clk_desc_array[i].data); ++ ++ if (!strcmp(name, clk_name)) ++ return rp1_clk_claimed[i]; ++ } ++ } ++ ++ return false; ++} ++ ++static int rp1_clk_probe(struct platform_device *pdev) ++{ ++ const struct rp1_clk_desc *desc; ++ struct device *dev = &pdev->dev; ++ struct rp1_clockman *clockman; ++ struct resource *res; ++ struct clk_hw **hws; ++ const size_t asize = ARRAY_SIZE(clk_desc_array); ++ u32 chip_id, platform; ++ unsigned int i; ++ u32 clk_id; ++ int ret; ++ ++ clockman = devm_kzalloc(dev, struct_size(clockman, onecell.hws, asize), ++ GFP_KERNEL); ++ if (!clockman) ++ return -ENOMEM; ++ ++ rp1_get_platform(&chip_id, &platform); ++ ++ spin_lock_init(&clockman->regs_lock); ++ clockman->dev = dev; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ clockman->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(clockman->regs)) ++ return PTR_ERR(clockman->regs); ++ ++ memset(rp1_clk_claimed, 0, sizeof(rp1_clk_claimed)); ++ for (i = 0; ++ !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks", ++ i, &clk_id); ++ i++) ++ rp1_clk_claimed[clk_id] = true; ++ ++ platform_set_drvdata(pdev, clockman); ++ ++ clockman->onecell.num = asize; ++ hws = clockman->onecell.hws; ++ ++ for (i = 0; i < asize; i++) { ++ desc = &clk_desc_array[i]; ++ if (desc->clk_register && desc->data) ++ hws[i] = desc->clk_register(clockman, desc->data); ++ } ++ ++ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, ++ &clockman->onecell); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static const struct of_device_id rp1_clk_of_match[] = { ++ { .compatible = "raspberrypi,rp1-clocks" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, rp1_clk_of_match); ++ ++static struct platform_driver rp1_clk_driver = { ++ .driver = { ++ .name = "rp1-clk", ++ .of_match_table = rp1_clk_of_match, ++ }, ++ .probe = rp1_clk_probe, ++}; ++ ++static int __init __rp1_clk_driver_init(void) ++{ ++ return platform_driver_register(&rp1_clk_driver); ++} ++postcore_initcall(__rp1_clk_driver_init); ++ ++MODULE_AUTHOR("Naushir Patuck "); ++MODULE_DESCRIPTION("RP1 clock driver"); ++MODULE_LICENSE("GPL"); +--- a/include/dt-bindings/clock/rp1.h ++++ b/include/dt-bindings/clock/rp1.h +@@ -13,39 +13,40 @@ + + #define RP1_PLL_SYS_PRI_PH 6 + #define RP1_PLL_SYS_SEC_PH 7 ++#define RP1_PLL_AUDIO_PRI_PH 8 + +-#define RP1_PLL_SYS_SEC 8 +-#define RP1_PLL_AUDIO_SEC 9 +-#define RP1_PLL_VIDEO_SEC 10 ++#define RP1_PLL_SYS_SEC 9 ++#define RP1_PLL_AUDIO_SEC 10 ++#define RP1_PLL_VIDEO_SEC 11 + +-#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 ++#define RP1_CLK_SYS 12 ++#define RP1_CLK_SLOW_SYS 13 ++#define RP1_CLK_DMA 14 ++#define RP1_CLK_UART 15 ++#define RP1_CLK_ETH 16 ++#define RP1_CLK_PWM0 17 ++#define RP1_CLK_PWM1 18 ++#define RP1_CLK_AUDIO_IN 19 ++#define RP1_CLK_AUDIO_OUT 20 ++#define RP1_CLK_I2S 21 ++#define RP1_CLK_MIPI0_CFG 22 ++#define RP1_CLK_MIPI1_CFG 23 ++#define RP1_CLK_PCIE_AUX 24 ++#define RP1_CLK_USBH0_MICROFRAME 25 ++#define RP1_CLK_USBH1_MICROFRAME 26 ++#define RP1_CLK_USBH0_SUSPEND 27 ++#define RP1_CLK_USBH1_SUSPEND 28 ++#define RP1_CLK_ETH_TSU 29 ++#define RP1_CLK_ADC 30 ++#define RP1_CLK_SDIO_TIMER 31 ++#define RP1_CLK_SDIO_ALT_SRC 32 ++#define RP1_CLK_GP0 33 ++#define RP1_CLK_GP1 34 ++#define RP1_CLK_GP2 35 ++#define RP1_CLK_GP3 36 ++#define RP1_CLK_GP4 37 ++#define RP1_CLK_GP5 38 ++#define RP1_CLK_VEC 39 ++#define RP1_CLK_DPI 40 ++#define RP1_CLK_MIPI0_DPI 41 ++#define RP1_CLK_MIPI1_DPI 42 diff --git a/target/linux/bcm27xx/patches-6.1/950-0875-dt-bindings-pinctrl-Add-bindings-for-Raspberry-Pi-RP.patch b/target/linux/bcm27xx/patches-6.1/950-0875-dt-bindings-pinctrl-Add-bindings-for-Raspberry-Pi-RP.patch new file mode 100644 index 0000000000..d0180a65ba --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0875-dt-bindings-pinctrl-Add-bindings-for-Raspberry-Pi-RP.patch @@ -0,0 +1,60 @@ +From 19b934ce3763c9465c5c80302f7c142d30b75869 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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__ */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0876-pinctrl-Add-rp1-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0876-pinctrl-Add-rp1-driver.patch new file mode 100644 index 0000000000..c824cddb51 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0876-pinctrl-Add-rp1-driver.patch @@ -0,0 +1,1666 @@ +From 4d4cc5be473a7767052122a87393a83d10f9ed41 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 10 Oct 2022 14:21:11 +0100 +Subject: [PATCH] pinctrl: Add rp1 driver + +RP1 exposes GPIOs. Add a pinctrl driver to allow control of those. + +Signed-off-by: Phil Elwell +--- + drivers/pinctrl/Kconfig | 7 + + drivers/pinctrl/Makefile | 1 + + drivers/pinctrl/pinctrl-rp1.c | 1571 +++++++++++++++++++++++++++++ + include/dt-bindings/pinctrl/rp1.h | 46 - + 4 files changed, 1579 insertions(+), 46 deletions(-) + create mode 100644 drivers/pinctrl/pinctrl-rp1.c + delete mode 100644 include/dt-bindings/pinctrl/rp1.h + +--- a/drivers/pinctrl/Kconfig ++++ b/drivers/pinctrl/Kconfig +@@ -512,6 +512,13 @@ config PINCTRL_ZYNQMP + This driver can also be built as a module. If so, the module + will be called pinctrl-zynqmp. + ++config PINCTRL_RP1 ++ bool "Pinctrl driver for RP1" ++ select PINMUX ++ select PINCONF ++ select GENERIC_PINCONF ++ select GPIOLIB_IRQCHIP ++ + source "drivers/pinctrl/actions/Kconfig" + source "drivers/pinctrl/aspeed/Kconfig" + source "drivers/pinctrl/bcm/Kconfig" +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -42,6 +42,7 @@ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-p + obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o + obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o + obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o ++obj-$(CONFIG_PINCTRL_RP1) += pinctrl-rp1.o + obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o + obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o + obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o +--- /dev/null ++++ b/drivers/pinctrl/pinctrl-rp1.c +@@ -0,0 +1,1571 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Driver for Raspberry Pi RP1 GPIO unit (pinctrl + GPIO) ++ * ++ * Copyright (C) 2023 Raspberry Pi Ltd. ++ * ++ * This driver is inspired by: ++ * pinctrl-bcm2835.c, please see original file for copyright information ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "core.h" ++#include "pinconf.h" ++#include "pinctrl-utils.h" ++ ++#define MODULE_NAME "pinctrl-rp1" ++#define RP1_NUM_GPIOS 54 ++#define RP1_NUM_BANKS 3 ++ ++#define RP1_RW_OFFSET 0x0000 ++#define RP1_XOR_OFFSET 0x1000 ++#define RP1_SET_OFFSET 0x2000 ++#define RP1_CLR_OFFSET 0x3000 ++ ++#define RP1_GPIO_STATUS 0x0000 ++#define RP1_GPIO_CTRL 0x0004 ++ ++#define RP1_GPIO_PCIE_INTE 0x011c ++#define RP1_GPIO_PCIE_INTS 0x0124 ++ ++#define RP1_GPIO_EVENTS_SHIFT_RAW 20 ++#define RP1_GPIO_STATUS_FALLING BIT(20) ++#define RP1_GPIO_STATUS_RISING BIT(21) ++#define RP1_GPIO_STATUS_LOW BIT(22) ++#define RP1_GPIO_STATUS_HIGH BIT(23) ++ ++#define RP1_GPIO_EVENTS_SHIFT_FILTERED 24 ++#define RP1_GPIO_STATUS_F_FALLING BIT(24) ++#define RP1_GPIO_STATUS_F_RISING BIT(25) ++#define RP1_GPIO_STATUS_F_LOW BIT(26) ++#define RP1_GPIO_STATUS_F_HIGH BIT(27) ++ ++#define RP1_GPIO_CTRL_FUNCSEL_LSB 0 ++#define RP1_GPIO_CTRL_FUNCSEL_MASK 0x0000001f ++#define RP1_GPIO_CTRL_OUTOVER_LSB 12 ++#define RP1_GPIO_CTRL_OUTOVER_MASK 0x00003000 ++#define RP1_GPIO_CTRL_OEOVER_LSB 14 ++#define RP1_GPIO_CTRL_OEOVER_MASK 0x0000c000 ++#define RP1_GPIO_CTRL_INOVER_LSB 16 ++#define RP1_GPIO_CTRL_INOVER_MASK 0x00030000 ++#define RP1_GPIO_CTRL_IRQEN_FALLING BIT(20) ++#define RP1_GPIO_CTRL_IRQEN_RISING BIT(21) ++#define RP1_GPIO_CTRL_IRQEN_LOW BIT(22) ++#define RP1_GPIO_CTRL_IRQEN_HIGH BIT(23) ++#define RP1_GPIO_CTRL_IRQEN_F_FALLING BIT(24) ++#define RP1_GPIO_CTRL_IRQEN_F_RISING BIT(25) ++#define RP1_GPIO_CTRL_IRQEN_F_LOW BIT(26) ++#define RP1_GPIO_CTRL_IRQEN_F_HIGH BIT(27) ++#define RP1_GPIO_CTRL_IRQRESET BIT(28) ++#define RP1_GPIO_CTRL_IRQOVER_LSB 30 ++#define RP1_GPIO_CTRL_IRQOVER_MASK 0xc0000000 ++ ++#define RP1_INT_EDGE_FALLING BIT(0) ++#define RP1_INT_EDGE_RISING BIT(1) ++#define RP1_INT_LEVEL_LOW BIT(2) ++#define RP1_INT_LEVEL_HIGH BIT(3) ++#define RP1_INT_MASK 0xf ++ ++#define RP1_INT_EDGE_BOTH (RP1_INT_EDGE_FALLING | \ ++ RP1_INT_EDGE_RISING) ++#define RP1_PUD_OFF 0 ++#define RP1_PUD_DOWN 1 ++#define RP1_PUD_UP 2 ++ ++#define RP1_FSEL_COUNT 9 ++ ++#define RP1_FSEL_ALT0 0x00 ++#define RP1_FSEL_GPIO 0x05 ++#define RP1_FSEL_NONE 0x09 ++#define RP1_FSEL_NONE_HW 0x1f ++ ++#define RP1_DIR_OUTPUT 0 ++#define RP1_DIR_INPUT 1 ++ ++#define RP1_OUTOVER_PERI 0 ++#define RP1_OUTOVER_INVPERI 1 ++#define RP1_OUTOVER_LOW 2 ++#define RP1_OUTOVER_HIGH 3 ++ ++#define RP1_OEOVER_PERI 0 ++#define RP1_OEOVER_INVPERI 1 ++#define RP1_OEOVER_DISABLE 2 ++#define RP1_OEOVER_ENABLE 3 ++ ++#define RP1_INOVER_PERI 0 ++#define RP1_INOVER_INVPERI 1 ++#define RP1_INOVER_LOW 2 ++#define RP1_INOVER_HIGH 3 ++ ++#define RP1_RIO_OUT 0x00 ++#define RP1_RIO_OE 0x04 ++#define RP1_RIO_IN 0x08 ++ ++#define RP1_PAD_SLEWFAST_MASK 0x00000001 ++#define RP1_PAD_SLEWFAST_LSB 0 ++#define RP1_PAD_SCHMITT_MASK 0x00000002 ++#define RP1_PAD_SCHMITT_LSB 1 ++#define RP1_PAD_PULL_MASK 0x0000000c ++#define RP1_PAD_PULL_LSB 2 ++#define RP1_PAD_DRIVE_MASK 0x00000030 ++#define RP1_PAD_DRIVE_LSB 4 ++#define RP1_PAD_IN_ENABLE_MASK 0x00000040 ++#define RP1_PAD_IN_ENABLE_LSB 6 ++#define RP1_PAD_OUT_DISABLE_MASK 0x00000080 ++#define RP1_PAD_OUT_DISABLE_LSB 7 ++ ++#define RP1_PAD_DRIVE_2MA 0x00000000 ++#define RP1_PAD_DRIVE_4MA 0x00000010 ++#define RP1_PAD_DRIVE_8MA 0x00000020 ++#define RP1_PAD_DRIVE_12MA 0x00000030 ++ ++#define FLD_GET(r, f) (((r) & (f ## _MASK)) >> (f ## _LSB)) ++#define FLD_SET(r, f, v) r = (((r) & ~(f ## _MASK)) | ((v) << (f ## _LSB))) ++ ++#define FUNC(f) \ ++ [func_##f] = #f ++#define RP1_MAX_FSEL 8 ++#define PIN(i, f0, f1, f2, f3, f4, f5, f6, f7, f8) \ ++ [i] = { \ ++ .funcs = { \ ++ func_##f0, \ ++ func_##f1, \ ++ func_##f2, \ ++ func_##f3, \ ++ func_##f4, \ ++ func_##f5, \ ++ func_##f6, \ ++ func_##f7, \ ++ func_##f8, \ ++ }, \ ++ } ++ ++#define LEGACY_MAP(n, f0, f1, f2, f3, f4, f5) \ ++ [n] = { \ ++ func_gpio, \ ++ func_gpio, \ ++ func_##f5, \ ++ func_##f4, \ ++ func_##f0, \ ++ func_##f1, \ ++ func_##f2, \ ++ func_##f3, \ ++ } ++ ++struct rp1_iobank_desc { ++ int min_gpio; ++ int num_gpios; ++ int gpio_offset; ++ int inte_offset; ++ int ints_offset; ++ int rio_offset; ++ int pads_offset; ++}; ++ ++struct rp1_pin_info { ++ u8 num; ++ u8 bank; ++ u8 offset; ++ u8 fsel; ++ u8 irq_type; ++ ++ void __iomem *gpio; ++ void __iomem *rio; ++ void __iomem *inte; ++ void __iomem *ints; ++ void __iomem *pad; ++}; ++ ++enum funcs { ++ func_alt0, ++ func_alt1, ++ func_alt2, ++ func_alt3, ++ func_alt4, ++ func_gpio, ++ func_alt6, ++ func_alt7, ++ func_alt8, ++ func_none, ++ func_aaud, ++ func_dcd0, ++ func_dpi, ++ func_dsi0_te_ext, ++ func_dsi1_te_ext, ++ func_dsr0, ++ func_dtr0, ++ func_gpclk0, ++ func_gpclk1, ++ func_gpclk2, ++ func_gpclk3, ++ func_gpclk4, ++ func_gpclk5, ++ func_i2c0, ++ func_i2c1, ++ func_i2c2, ++ func_i2c3, ++ func_i2c4, ++ func_i2c5, ++ func_i2c6, ++ func_i2s0, ++ func_i2s1, ++ func_i2s2, ++ func_ir, ++ func_mic, ++ func_pcie_clkreq_n, ++ func_pio, ++ func_proc_rio, ++ func_pwm0, ++ func_pwm1, ++ func_ri0, ++ func_sd0, ++ func_sd1, ++ func_spi0, ++ func_spi1, ++ func_spi2, ++ func_spi3, ++ func_spi4, ++ func_spi5, ++ func_spi6, ++ func_spi7, ++ func_spi8, ++ func_uart0, ++ func_uart1, ++ func_uart2, ++ func_uart3, ++ func_uart4, ++ func_uart5, ++ func_vbus0, ++ func_vbus1, ++ func_vbus2, ++ func_vbus3, ++ func__, ++ func_count = func__, ++ func_invalid = func__, ++}; ++ ++struct rp1_pin_funcs { ++ u8 funcs[RP1_FSEL_COUNT]; ++}; ++ ++struct rp1_pinctrl { ++ struct device *dev; ++ void __iomem *gpio_base; ++ void __iomem *rio_base; ++ void __iomem *pads_base; ++ int irq[RP1_NUM_BANKS]; ++ struct rp1_pin_info pins[RP1_NUM_GPIOS]; ++ ++ struct pinctrl_dev *pctl_dev; ++ struct gpio_chip gpio_chip; ++ struct pinctrl_gpio_range gpio_range; ++ ++ raw_spinlock_t irq_lock[RP1_NUM_BANKS]; ++}; ++ ++const struct rp1_iobank_desc rp1_iobanks[RP1_NUM_BANKS] = { ++ /* gpio inte ints rio pads */ ++ { 0, 28, 0x0000, 0x011c, 0x0124, 0x0000, 0x0004 }, ++ { 28, 6, 0x4000, 0x411c, 0x4124, 0x4000, 0x4004 }, ++ { 34, 20, 0x8000, 0x811c, 0x8124, 0x8000, 0x8004 }, ++}; ++ ++/* pins are just named GPIO0..GPIO53 */ ++#define RP1_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a) ++static struct pinctrl_pin_desc rp1_gpio_pins[] = { ++ RP1_GPIO_PIN(0), ++ RP1_GPIO_PIN(1), ++ RP1_GPIO_PIN(2), ++ RP1_GPIO_PIN(3), ++ RP1_GPIO_PIN(4), ++ RP1_GPIO_PIN(5), ++ RP1_GPIO_PIN(6), ++ RP1_GPIO_PIN(7), ++ RP1_GPIO_PIN(8), ++ RP1_GPIO_PIN(9), ++ RP1_GPIO_PIN(10), ++ RP1_GPIO_PIN(11), ++ RP1_GPIO_PIN(12), ++ RP1_GPIO_PIN(13), ++ RP1_GPIO_PIN(14), ++ RP1_GPIO_PIN(15), ++ RP1_GPIO_PIN(16), ++ RP1_GPIO_PIN(17), ++ RP1_GPIO_PIN(18), ++ RP1_GPIO_PIN(19), ++ RP1_GPIO_PIN(20), ++ RP1_GPIO_PIN(21), ++ RP1_GPIO_PIN(22), ++ RP1_GPIO_PIN(23), ++ RP1_GPIO_PIN(24), ++ RP1_GPIO_PIN(25), ++ RP1_GPIO_PIN(26), ++ RP1_GPIO_PIN(27), ++ RP1_GPIO_PIN(28), ++ RP1_GPIO_PIN(29), ++ RP1_GPIO_PIN(30), ++ RP1_GPIO_PIN(31), ++ RP1_GPIO_PIN(32), ++ RP1_GPIO_PIN(33), ++ RP1_GPIO_PIN(34), ++ RP1_GPIO_PIN(35), ++ RP1_GPIO_PIN(36), ++ RP1_GPIO_PIN(37), ++ RP1_GPIO_PIN(38), ++ RP1_GPIO_PIN(39), ++ RP1_GPIO_PIN(40), ++ RP1_GPIO_PIN(41), ++ RP1_GPIO_PIN(42), ++ RP1_GPIO_PIN(43), ++ RP1_GPIO_PIN(44), ++ RP1_GPIO_PIN(45), ++ RP1_GPIO_PIN(46), ++ RP1_GPIO_PIN(47), ++ RP1_GPIO_PIN(48), ++ RP1_GPIO_PIN(49), ++ RP1_GPIO_PIN(50), ++ RP1_GPIO_PIN(51), ++ RP1_GPIO_PIN(52), ++ RP1_GPIO_PIN(53), ++}; ++ ++/* one pin per group */ ++static const char * const rp1_gpio_groups[] = { ++ "gpio0", ++ "gpio1", ++ "gpio2", ++ "gpio3", ++ "gpio4", ++ "gpio5", ++ "gpio6", ++ "gpio7", ++ "gpio8", ++ "gpio9", ++ "gpio10", ++ "gpio11", ++ "gpio12", ++ "gpio13", ++ "gpio14", ++ "gpio15", ++ "gpio16", ++ "gpio17", ++ "gpio18", ++ "gpio19", ++ "gpio20", ++ "gpio21", ++ "gpio22", ++ "gpio23", ++ "gpio24", ++ "gpio25", ++ "gpio26", ++ "gpio27", ++ "gpio28", ++ "gpio29", ++ "gpio30", ++ "gpio31", ++ "gpio32", ++ "gpio33", ++ "gpio34", ++ "gpio35", ++ "gpio36", ++ "gpio37", ++ "gpio38", ++ "gpio39", ++ "gpio40", ++ "gpio41", ++ "gpio42", ++ "gpio43", ++ "gpio44", ++ "gpio45", ++ "gpio46", ++ "gpio47", ++ "gpio48", ++ "gpio49", ++ "gpio50", ++ "gpio51", ++ "gpio52", ++ "gpio53", ++}; ++ ++static const char * const rp1_func_names[] = { ++ FUNC(alt0), ++ FUNC(alt1), ++ FUNC(alt2), ++ FUNC(alt3), ++ FUNC(alt4), ++ FUNC(gpio), ++ FUNC(alt6), ++ FUNC(alt7), ++ FUNC(alt8), ++ FUNC(none), ++ FUNC(aaud), ++ FUNC(dcd0), ++ FUNC(dpi), ++ FUNC(dsi0_te_ext), ++ FUNC(dsi1_te_ext), ++ FUNC(dsr0), ++ FUNC(dtr0), ++ FUNC(gpclk0), ++ FUNC(gpclk1), ++ FUNC(gpclk2), ++ FUNC(gpclk3), ++ FUNC(gpclk4), ++ FUNC(gpclk5), ++ FUNC(i2c0), ++ FUNC(i2c1), ++ FUNC(i2c2), ++ FUNC(i2c3), ++ FUNC(i2c4), ++ FUNC(i2c5), ++ FUNC(i2c6), ++ FUNC(i2s0), ++ FUNC(i2s1), ++ FUNC(i2s2), ++ FUNC(ir), ++ FUNC(mic), ++ FUNC(pcie_clkreq_n), ++ FUNC(pio), ++ FUNC(proc_rio), ++ FUNC(pwm0), ++ FUNC(pwm1), ++ FUNC(ri0), ++ FUNC(sd0), ++ FUNC(sd1), ++ FUNC(spi0), ++ FUNC(spi1), ++ FUNC(spi2), ++ FUNC(spi3), ++ FUNC(spi4), ++ FUNC(spi5), ++ FUNC(spi6), ++ FUNC(spi7), ++ FUNC(spi8), ++ FUNC(uart0), ++ FUNC(uart1), ++ FUNC(uart2), ++ FUNC(uart3), ++ FUNC(uart4), ++ FUNC(uart5), ++ FUNC(vbus0), ++ FUNC(vbus1), ++ FUNC(vbus2), ++ FUNC(vbus3), ++ [func_invalid] = "?" ++}; ++ ++static const struct rp1_pin_funcs rp1_gpio_pin_funcs[] = { ++ PIN(0, spi0, dpi, uart1, i2c0, _, gpio, proc_rio, pio, spi2), ++ PIN(1, spi0, dpi, uart1, i2c0, _, gpio, proc_rio, pio, spi2), ++ PIN(2, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2), ++ PIN(3, spi0, dpi, uart1, i2c1, ir, gpio, proc_rio, pio, spi2), ++ PIN(4, gpclk0, dpi, uart2, i2c2, ri0, gpio, proc_rio, pio, spi3), ++ PIN(5, gpclk1, dpi, uart2, i2c2, dtr0, gpio, proc_rio, pio, spi3), ++ PIN(6, gpclk2, dpi, uart2, i2c3, dcd0, gpio, proc_rio, pio, spi3), ++ PIN(7, spi0, dpi, uart2, i2c3, dsr0, gpio, proc_rio, pio, spi3), ++ PIN(8, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4), ++ PIN(9, spi0, dpi, uart3, i2c0, _, gpio, proc_rio, pio, spi4), ++ PIN(10, spi0, dpi, uart3, i2c1, _, gpio, proc_rio, pio, spi4), ++ PIN(11, spi0, dpi, uart3, i2c1, _, gpio, proc_rio, pio, spi4), ++ PIN(12, pwm0, dpi, uart4, i2c2, aaud, gpio, proc_rio, pio, spi5), ++ PIN(13, pwm0, dpi, uart4, i2c2, aaud, gpio, proc_rio, pio, spi5), ++ PIN(14, pwm0, dpi, uart4, i2c3, uart0, gpio, proc_rio, pio, spi5), ++ PIN(15, pwm0, dpi, uart4, i2c3, uart0, gpio, proc_rio, pio, spi5), ++ PIN(16, spi1, dpi, dsi0_te_ext, _, uart0, gpio, proc_rio, pio, _), ++ PIN(17, spi1, dpi, dsi1_te_ext, _, uart0, gpio, proc_rio, pio, _), ++ PIN(18, spi1, dpi, i2s0, pwm0, i2s1, gpio, proc_rio, pio, gpclk1), ++ PIN(19, spi1, dpi, i2s0, pwm0, i2s1, gpio, proc_rio, pio, _), ++ PIN(20, spi1, dpi, i2s0, gpclk0, i2s1, gpio, proc_rio, pio, _), ++ PIN(21, spi1, dpi, i2s0, gpclk1, i2s1, gpio, proc_rio, pio, _), ++ PIN(22, sd0, dpi, i2s0, i2c3, i2s1, gpio, proc_rio, pio, _), ++ PIN(23, sd0, dpi, i2s0, i2c3, i2s1, gpio, proc_rio, pio, _), ++ PIN(24, sd0, dpi, i2s0, _, i2s1, gpio, proc_rio, pio, spi2), ++ PIN(25, sd0, dpi, i2s0, mic, i2s1, gpio, proc_rio, pio, spi3), ++ PIN(26, sd0, dpi, i2s0, mic, i2s1, gpio, proc_rio, pio, spi5), ++ PIN(27, sd0, dpi, i2s0, mic, i2s1, gpio, proc_rio, pio, spi1), ++ PIN(28, sd1, i2c4, i2s2, spi6, vbus0, gpio, proc_rio, _, _), ++ PIN(29, sd1, i2c4, i2s2, spi6, vbus0, gpio, proc_rio, _, _), ++ PIN(30, sd1, i2c5, i2s2, spi6, uart5, gpio, proc_rio, _, _), ++ PIN(31, sd1, i2c5, i2s2, spi6, uart5, gpio, proc_rio, _, _), ++ PIN(32, sd1, gpclk3, i2s2, spi6, uart5, gpio, proc_rio, _, _), ++ PIN(33, sd1, gpclk4, i2s2, spi6, uart5, gpio, proc_rio, _, _), ++ PIN(34, pwm1, gpclk3, vbus0, i2c4, mic, gpio, proc_rio, _, _), ++ PIN(35, spi8, pwm1, vbus0, i2c4, mic, gpio, proc_rio, _, _), ++ PIN(36, spi8, uart5, pcie_clkreq_n, i2c5, mic, gpio, proc_rio, _, _), ++ PIN(37, spi8, uart5, mic, i2c5, pcie_clkreq_n, gpio, proc_rio, _, _), ++ PIN(38, spi8, uart5, mic, i2c6, aaud, gpio, proc_rio, dsi0_te_ext, _), ++ PIN(39, spi8, uart5, mic, i2c6, aaud, gpio, proc_rio, dsi1_te_ext, _), ++ PIN(40, pwm1, uart5, i2c4, spi6, aaud, gpio, proc_rio, _, _), ++ PIN(41, pwm1, uart5, i2c4, spi6, aaud, gpio, proc_rio, _, _), ++ PIN(42, gpclk5, uart5, vbus1, spi6, i2s2, gpio, proc_rio, _, _), ++ PIN(43, gpclk4, uart5, vbus1, spi6, i2s2, gpio, proc_rio, _, _), ++ PIN(44, gpclk5, i2c5, pwm1, spi6, i2s2, gpio, proc_rio, _, _), ++ PIN(45, pwm1, i2c5, spi7, spi6, i2s2, gpio, proc_rio, _, _), ++ PIN(46, gpclk3, i2c4, spi7, mic, i2s2, gpio, proc_rio, dsi0_te_ext, _), ++ PIN(47, gpclk5, i2c4, spi7, mic, i2s2, gpio, proc_rio, dsi1_te_ext, _), ++ PIN(48, pwm1, pcie_clkreq_n, spi7, mic, uart5, gpio, proc_rio, _, _), ++ PIN(49, spi8, spi7, i2c5, aaud, uart5, gpio, proc_rio, _, _), ++ PIN(50, spi8, spi7, i2c5, aaud, vbus2, gpio, proc_rio, _, _), ++ PIN(51, spi8, spi7, i2c6, aaud, vbus2, gpio, proc_rio, _, _), ++ PIN(52, spi8, _, i2c6, aaud, vbus3, gpio, proc_rio, _, _), ++ PIN(53, spi8, spi7, _, pcie_clkreq_n, vbus3, gpio, proc_rio, _, _), ++}; ++ ++static const u8 legacy_fsel_map[][8] = { ++ LEGACY_MAP(0, i2c0, _, dpi, spi2, uart1, _), ++ LEGACY_MAP(1, i2c0, _, dpi, spi2, uart1, _), ++ LEGACY_MAP(2, i2c1, _, dpi, spi2, uart1, _), ++ LEGACY_MAP(3, i2c1, _, dpi, spi2, uart1, _), ++ LEGACY_MAP(4, gpclk0, _, dpi, spi3, uart2, i2c2), ++ LEGACY_MAP(5, gpclk1, _, dpi, spi3, uart2, i2c2), ++ LEGACY_MAP(6, gpclk2, _, dpi, spi3, uart2, i2c3), ++ LEGACY_MAP(7, spi0, _, dpi, spi3, uart2, i2c3), ++ LEGACY_MAP(8, spi0, _, dpi, _, uart3, i2c0), ++ LEGACY_MAP(9, spi0, _, dpi, _, uart3, i2c0), ++ LEGACY_MAP(10, spi0, _, dpi, _, uart3, i2c1), ++ LEGACY_MAP(11, spi0, _, dpi, _, uart3, i2c1), ++ LEGACY_MAP(12, pwm0, _, dpi, spi5, uart4, i2c2), ++ LEGACY_MAP(13, pwm0, _, dpi, spi5, uart4, i2c2), ++ LEGACY_MAP(14, uart0, _, dpi, spi5, uart4, _), ++ LEGACY_MAP(15, uart0, _, dpi, spi5, uart4, _), ++ LEGACY_MAP(16, _, _, dpi, uart0, spi1, _), ++ LEGACY_MAP(17, _, _, dpi, uart0, spi1, _), ++ LEGACY_MAP(18, i2s0, _, dpi, _, spi1, pwm0), ++ LEGACY_MAP(19, i2s0, _, dpi, _, spi1, pwm0), ++ LEGACY_MAP(20, i2s0, _, dpi, _, spi1, gpclk0), ++ LEGACY_MAP(21, i2s0, _, dpi, _, spi1, gpclk1), ++ LEGACY_MAP(22, sd0, _, dpi, _, _, i2c3), ++ LEGACY_MAP(23, sd0, _, dpi, _, _, i2c3), ++ LEGACY_MAP(24, sd0, _, dpi, _, _, spi2), ++ LEGACY_MAP(25, sd0, _, dpi, _, _, spi3), ++ LEGACY_MAP(26, sd0, _, dpi, _, _, spi5), ++ LEGACY_MAP(27, sd0, _, dpi, _, _, _), ++}; ++ ++static const char * const irq_type_names[] = { ++ [IRQ_TYPE_NONE] = "none", ++ [IRQ_TYPE_EDGE_RISING] = "edge-rising", ++ [IRQ_TYPE_EDGE_FALLING] = "edge-falling", ++ [IRQ_TYPE_EDGE_BOTH] = "edge-both", ++ [IRQ_TYPE_LEVEL_HIGH] = "level-high", ++ [IRQ_TYPE_LEVEL_LOW] = "level-low", ++}; ++ ++static int rp1_pinconf_set(struct pinctrl_dev *pctldev, ++ unsigned int offset, unsigned long *configs, ++ unsigned int num_configs); ++ ++static struct rp1_pin_info *rp1_get_pin(struct gpio_chip *chip, ++ unsigned int offset) ++{ ++ struct rp1_pinctrl *pc = gpiochip_get_data(chip); ++ ++ if (pc && offset < RP1_NUM_GPIOS) ++ return &pc->pins[offset]; ++ return NULL; ++} ++ ++static struct rp1_pin_info *rp1_get_pin_pctl(struct pinctrl_dev *pctldev, ++ unsigned int offset) ++{ ++ struct rp1_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ ++ if (pc && offset < RP1_NUM_GPIOS) ++ return &pc->pins[offset]; ++ return NULL; ++} ++ ++static void rp1_pad_update(struct rp1_pin_info *pin, u32 clr, u32 set) ++{ ++ u32 padctrl = readl(pin->pad); ++ ++ padctrl &= ~clr; ++ padctrl |= set; ++ ++ writel(padctrl, pin->pad); ++} ++ ++static void rp1_input_enable(struct rp1_pin_info *pin, int value) ++{ ++ rp1_pad_update(pin, RP1_PAD_IN_ENABLE_MASK, ++ value ? RP1_PAD_IN_ENABLE_MASK : 0); ++} ++ ++static void rp1_output_enable(struct rp1_pin_info *pin, int value) ++{ ++ rp1_pad_update(pin, RP1_PAD_OUT_DISABLE_MASK, ++ value ? 0 : RP1_PAD_OUT_DISABLE_MASK); ++} ++ ++static u32 rp1_get_fsel(struct rp1_pin_info *pin) ++{ ++ u32 ctrl = readl(pin->gpio + RP1_GPIO_CTRL); ++ u32 oeover = FLD_GET(ctrl, RP1_GPIO_CTRL_OEOVER); ++ u32 fsel = FLD_GET(ctrl, RP1_GPIO_CTRL_FUNCSEL); ++ ++ if (oeover != RP1_OEOVER_PERI || fsel >= RP1_FSEL_COUNT) ++ fsel = RP1_FSEL_NONE; ++ ++ return fsel; ++} ++ ++static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel) ++{ ++ u32 ctrl = readl(pin->gpio + RP1_GPIO_CTRL); ++ ++ if (fsel >= RP1_FSEL_COUNT) ++ fsel = RP1_FSEL_NONE_HW; ++ ++ rp1_input_enable(pin, 1); ++ rp1_output_enable(pin, 1); ++ ++ if (fsel == RP1_FSEL_NONE) { ++ FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_DISABLE); ++ } else { ++ FLD_SET(ctrl, RP1_GPIO_CTRL_OUTOVER, RP1_OUTOVER_PERI); ++ FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_PERI); ++ } ++ FLD_SET(ctrl, RP1_GPIO_CTRL_FUNCSEL, fsel); ++ writel(ctrl, pin->gpio + RP1_GPIO_CTRL); ++} ++ ++static int rp1_get_dir(struct rp1_pin_info *pin) ++{ ++ return !(readl(pin->rio + RP1_RIO_OE) & (1 << pin->offset)) ? ++ RP1_DIR_INPUT : RP1_DIR_OUTPUT; ++} ++ ++static void rp1_set_dir(struct rp1_pin_info *pin, bool is_input) ++{ ++ int offset = is_input ? RP1_CLR_OFFSET : RP1_SET_OFFSET; ++ ++ writel(1 << pin->offset, pin->rio + RP1_RIO_OE + offset); ++} ++ ++static int rp1_get_value(struct rp1_pin_info *pin) ++{ ++ return !!(readl(pin->rio + RP1_RIO_IN) & (1 << pin->offset)); ++} ++ ++static void rp1_set_value(struct rp1_pin_info *pin, int value) ++{ ++ /* Assume the pin is already an output */ ++ writel(1 << pin->offset, ++ pin->rio + RP1_RIO_OUT + (value ? RP1_SET_OFFSET : RP1_CLR_OFFSET)); ++} ++ ++static int rp1_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin(chip, offset); ++ int ret; ++ ++ if (!pin) ++ return -EINVAL; ++ ret = rp1_get_value(pin); ++ return ret; ++} ++ ++static void rp1_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin(chip, offset); ++ ++ if (pin) ++ rp1_set_value(pin, value); ++} ++ ++static int rp1_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin(chip, offset); ++ u32 fsel; ++ ++ if (!pin) ++ return -EINVAL; ++ fsel = rp1_get_fsel(pin); ++ if (fsel != RP1_FSEL_GPIO) ++ return -EINVAL; ++ return (rp1_get_dir(pin) == RP1_DIR_OUTPUT) ? ++ GPIO_LINE_DIRECTION_OUT : ++ GPIO_LINE_DIRECTION_IN; ++} ++ ++static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin(chip, offset); ++ ++ if (!pin) ++ return -EINVAL; ++ rp1_set_dir(pin, RP1_DIR_INPUT); ++ rp1_set_fsel(pin, RP1_FSEL_GPIO); ++ return 0; ++} ++ ++static int rp1_gpio_direction_output(struct gpio_chip *chip, unsigned offset, ++ int value) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin(chip, offset); ++ ++ if (!pin) ++ return -EINVAL; ++ rp1_set_value(pin, value); ++ rp1_set_dir(pin, RP1_DIR_OUTPUT); ++ rp1_set_fsel(pin, RP1_FSEL_GPIO); ++ return 0; ++} ++ ++static int rp1_gpio_set_config(struct gpio_chip *gc, unsigned offset, ++ unsigned long config) ++{ ++ struct rp1_pinctrl *pc = gpiochip_get_data(gc); ++ unsigned long configs[] = { config }; ++ ++ return rp1_pinconf_set(pc->pctl_dev, offset, configs, ++ ARRAY_SIZE(configs)); ++} ++ ++static const struct gpio_chip rp1_gpio_chip = { ++ .label = MODULE_NAME, ++ .owner = THIS_MODULE, ++ .request = gpiochip_generic_request, ++ .free = gpiochip_generic_free, ++ .direction_input = rp1_gpio_direction_input, ++ .direction_output = rp1_gpio_direction_output, ++ .get_direction = rp1_gpio_get_direction, ++ .get = rp1_gpio_get, ++ .set = rp1_gpio_set, ++ .base = -1, ++ .set_config = rp1_gpio_set_config, ++ .ngpio = RP1_NUM_GPIOS, ++ .can_sleep = false, ++}; ++ ++static void rp1_gpio_irq_handler(struct irq_desc *desc) ++{ ++ struct gpio_chip *chip = irq_desc_get_handler_data(desc); ++ struct rp1_pinctrl *pc = gpiochip_get_data(chip); ++ struct irq_chip *host_chip = irq_desc_get_chip(desc); ++ const struct rp1_iobank_desc *bank; ++ int irq = irq_desc_get_irq(desc); ++ unsigned long ints; ++ int b; ++ ++ if (pc->irq[0] == irq) ++ bank = &rp1_iobanks[0]; ++ else if (pc->irq[1] == irq) ++ bank = &rp1_iobanks[1]; ++ else ++ bank = &rp1_iobanks[2]; ++ ++ chained_irq_enter(host_chip, desc); ++ ++ ints = readl(pc->gpio_base + bank->ints_offset); ++ for_each_set_bit(b, &ints, 32) { ++ struct rp1_pin_info *pin = rp1_get_pin(chip, b); ++ ++ writel(RP1_GPIO_CTRL_IRQRESET, ++ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); ++ generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irq.domain, ++ bank->gpio_offset + b)); ++ } ++ ++ chained_irq_exit(host_chip, desc); ++} ++ ++static void rp1_gpio_irq_config(struct rp1_pin_info *pin, bool enable) ++{ ++ writel(1 << pin->offset, ++ pin->inte + (enable ? RP1_SET_OFFSET : RP1_CLR_OFFSET)); ++ if (!enable) ++ /* Clear any latched events */ ++ writel(RP1_GPIO_CTRL_IRQRESET, ++ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); ++} ++ ++static void rp1_gpio_irq_enable(struct irq_data *data) ++{ ++ struct gpio_chip *chip = irq_data_get_irq_chip_data(data); ++ unsigned gpio = irqd_to_hwirq(data); ++ struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); ++ ++ rp1_gpio_irq_config(pin, true); ++} ++ ++static void rp1_gpio_irq_disable(struct irq_data *data) ++{ ++ struct gpio_chip *chip = irq_data_get_irq_chip_data(data); ++ unsigned gpio = irqd_to_hwirq(data); ++ struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); ++ ++ rp1_gpio_irq_config(pin, false); ++} ++ ++static int rp1_irq_set_type(struct rp1_pin_info *pin, unsigned int type) ++{ ++ u32 irq_flags; ++ ++ switch (type) { ++ case IRQ_TYPE_NONE: ++ irq_flags = 0; ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ irq_flags = RP1_INT_EDGE_RISING; ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ irq_flags = RP1_INT_EDGE_FALLING; ++ break; ++ case IRQ_TYPE_EDGE_BOTH: ++ irq_flags = RP1_INT_EDGE_RISING | RP1_INT_EDGE_FALLING; ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ irq_flags = RP1_INT_LEVEL_HIGH; ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ irq_flags = RP1_INT_LEVEL_LOW; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ /* Clear them all */ ++ writel(RP1_INT_MASK << RP1_GPIO_EVENTS_SHIFT_RAW, ++ pin->gpio + RP1_CLR_OFFSET + RP1_GPIO_CTRL); ++ /* Set those that are needed */ ++ writel(irq_flags << RP1_GPIO_EVENTS_SHIFT_RAW, ++ pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); ++ pin->irq_type = type; ++ ++ return 0; ++} ++ ++static int rp1_gpio_irq_set_type(struct irq_data *data, unsigned int type) ++{ ++ struct gpio_chip *chip = irq_data_get_irq_chip_data(data); ++ struct rp1_pinctrl *pc = gpiochip_get_data(chip); ++ unsigned gpio = irqd_to_hwirq(data); ++ struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); ++ int bank = pin->bank; ++ unsigned long flags; ++ int ret; ++ ++ raw_spin_lock_irqsave(&pc->irq_lock[bank], flags); ++ ++ ret = rp1_irq_set_type(pin, type); ++ if (!ret) { ++ if (type & IRQ_TYPE_EDGE_BOTH) ++ irq_set_handler_locked(data, handle_edge_irq); ++ else ++ irq_set_handler_locked(data, handle_level_irq); ++ } ++ ++ raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags); ++ ++ return ret; ++} ++ ++static void rp1_gpio_irq_ack(struct irq_data *data) ++{ ++ struct gpio_chip *chip = irq_data_get_irq_chip_data(data); ++ unsigned gpio = irqd_to_hwirq(data); ++ struct rp1_pin_info *pin = rp1_get_pin(chip, gpio); ++ ++ /* Clear any latched events */ ++ writel(RP1_GPIO_CTRL_IRQRESET, pin->gpio + RP1_SET_OFFSET + RP1_GPIO_CTRL); ++} ++ ++static struct irq_chip rp1_gpio_irq_chip = { ++ .name = MODULE_NAME, ++ .irq_enable = rp1_gpio_irq_enable, ++ .irq_disable = rp1_gpio_irq_disable, ++ .irq_set_type = rp1_gpio_irq_set_type, ++ .irq_ack = rp1_gpio_irq_ack, ++ .irq_mask = rp1_gpio_irq_disable, ++ .irq_unmask = rp1_gpio_irq_enable, ++ .flags = IRQCHIP_IMMUTABLE, ++}; ++ ++static int rp1_pctl_get_groups_count(struct pinctrl_dev *pctldev) ++{ ++ return ARRAY_SIZE(rp1_gpio_groups); ++} ++ ++static const char *rp1_pctl_get_group_name(struct pinctrl_dev *pctldev, ++ unsigned selector) ++{ ++ return rp1_gpio_groups[selector]; ++} ++ ++static enum funcs rp1_get_fsel_func(unsigned pin, unsigned fsel) ++{ ++ if (pin < RP1_NUM_GPIOS) { ++ if (fsel < RP1_FSEL_COUNT) ++ return rp1_gpio_pin_funcs[pin].funcs[fsel]; ++ else if (fsel == RP1_FSEL_NONE) ++ return func_none; ++ } ++ return func_invalid; ++} ++ ++static int rp1_pctl_get_group_pins(struct pinctrl_dev *pctldev, ++ unsigned selector, ++ const unsigned **pins, ++ unsigned *num_pins) ++{ ++ *pins = &rp1_gpio_pins[selector].number; ++ *num_pins = 1; ++ ++ return 0; ++} ++ ++static void rp1_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, ++ struct seq_file *s, ++ unsigned offset) ++{ ++ struct rp1_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ struct gpio_chip *chip = &pc->gpio_chip; ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); ++ u32 fsel = rp1_get_fsel(pin); ++ enum funcs func = rp1_get_fsel_func(offset, fsel); ++ int value = rp1_get_value(pin); ++ int irq = irq_find_mapping(chip->irq.domain, offset); ++ ++ seq_printf(s, "function %s (%s) in %s; irq %d (%s)", ++ rp1_func_names[fsel], rp1_func_names[func], ++ value ? "hi" : "lo", ++ irq, irq_type_names[pin->irq_type]); ++} ++ ++static void rp1_pctl_dt_free_map(struct pinctrl_dev *pctldev, ++ struct pinctrl_map *maps, unsigned num_maps) ++{ ++ int i; ++ ++ for (i = 0; i < num_maps; i++) ++ if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN) ++ kfree(maps[i].data.configs.configs); ++ ++ kfree(maps); ++} ++ ++static int rp1_pctl_legacy_map_func(struct rp1_pinctrl *pc, ++ struct device_node *np, u32 pin, u32 fnum, ++ struct pinctrl_map *maps, ++ unsigned int *num_maps) ++{ ++ struct pinctrl_map *map = &maps[*num_maps]; ++ enum funcs func; ++ ++ if (fnum >= ARRAY_SIZE(legacy_fsel_map[0])) { ++ dev_err(pc->dev, "%pOF: invalid brcm,function %d\n", np, fnum); ++ return -EINVAL; ++ } ++ ++ func = legacy_fsel_map[pin][fnum]; ++ if (func == func_invalid) { ++ dev_err(pc->dev, "%pOF: brcm,function %d not supported on pin %d\n", ++ np, fnum, pin); ++ } ++ ++ map->type = PIN_MAP_TYPE_MUX_GROUP; ++ map->data.mux.group = rp1_gpio_groups[pin]; ++ map->data.mux.function = rp1_func_names[func]; ++ (*num_maps)++; ++ ++ return 0; ++} ++ ++static int rp1_pctl_legacy_map_pull(struct rp1_pinctrl *pc, ++ struct device_node *np, u32 pin, u32 pull, ++ struct pinctrl_map *maps, ++ unsigned int *num_maps) ++{ ++ struct pinctrl_map *map = &maps[*num_maps]; ++ enum pin_config_param param; ++ unsigned long *configs; ++ ++ switch (pull) { ++ case RP1_PUD_OFF: ++ param = PIN_CONFIG_BIAS_DISABLE; ++ break; ++ case RP1_PUD_DOWN: ++ param = PIN_CONFIG_BIAS_PULL_DOWN; ++ break; ++ case RP1_PUD_UP: ++ param = PIN_CONFIG_BIAS_PULL_UP; ++ break; ++ default: ++ dev_err(pc->dev, "%pOF: invalid brcm,pull %d\n", np, pull); ++ return -EINVAL; ++ } ++ ++ configs = kzalloc(sizeof(*configs), GFP_KERNEL); ++ if (!configs) ++ return -ENOMEM; ++ ++ configs[0] = pinconf_to_config_packed(param, 0); ++ map->type = PIN_MAP_TYPE_CONFIGS_PIN; ++ map->data.configs.group_or_pin = rp1_gpio_pins[pin].name; ++ map->data.configs.configs = configs; ++ map->data.configs.num_configs = 1; ++ (*num_maps)++; ++ ++ return 0; ++} ++ ++static int rp1_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, ++ struct device_node *np, ++ struct pinctrl_map **map, ++ unsigned int *num_maps) ++{ ++ struct rp1_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); ++ struct property *pins, *funcs, *pulls; ++ int num_pins, num_funcs, num_pulls, maps_per_pin; ++ struct pinctrl_map *maps; ++ unsigned long *configs = NULL; ++ const char *function = NULL; ++ unsigned int reserved_maps; ++ int num_configs = 0; ++ int i, err; ++ u32 pin, func, pull; ++ ++ /* Check for legacy pin declaration */ ++ pins = of_find_property(np, "brcm,pins", NULL); ++ ++ if (!pins) /* Assume generic bindings in this node */ ++ return pinconf_generic_dt_node_to_map_all(pctldev, np, map, num_maps); ++ ++ funcs = of_find_property(np, "brcm,function", NULL); ++ if (!funcs) ++ of_property_read_string(np, "function", &function); ++ ++ pulls = of_find_property(np, "brcm,pull", NULL); ++ if (!pulls) ++ pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs); ++ ++ if (!function && !funcs && !num_configs && !pulls) { ++ dev_err(pc->dev, ++ "%pOF: no function, brcm,function, brcm,pull, etc.\n", ++ np); ++ return -EINVAL; ++ } ++ ++ num_pins = pins->length / 4; ++ num_funcs = funcs ? (funcs->length / 4) : 0; ++ num_pulls = pulls ? (pulls->length / 4) : 0; ++ ++ if (num_funcs > 1 && num_funcs != num_pins) { ++ dev_err(pc->dev, ++ "%pOF: brcm,function must have 1 or %d entries\n", ++ np, num_pins); ++ return -EINVAL; ++ } ++ ++ if (num_pulls > 1 && num_pulls != num_pins) { ++ dev_err(pc->dev, ++ "%pOF: brcm,pull must have 1 or %d entries\n", ++ np, num_pins); ++ return -EINVAL; ++ } ++ ++ maps_per_pin = 0; ++ if (function || num_funcs) ++ maps_per_pin++; ++ if (num_configs || num_pulls) ++ maps_per_pin++; ++ reserved_maps = num_pins * maps_per_pin; ++ maps = kcalloc(reserved_maps, sizeof(*maps), GFP_KERNEL); ++ if (!maps) ++ return -ENOMEM; ++ ++ *num_maps = 0; ++ ++ for (i = 0; i < num_pins; i++) { ++ err = of_property_read_u32_index(np, "brcm,pins", i, &pin); ++ if (err) ++ goto out; ++ if (pin >= ARRAY_SIZE(legacy_fsel_map)) { ++ dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n", ++ np, pin); ++ err = -EINVAL; ++ goto out; ++ } ++ ++ if (num_funcs) { ++ err = of_property_read_u32_index(np, "brcm,function", ++ (num_funcs > 1) ? i : 0, ++ &func); ++ if (err) ++ goto out; ++ err = rp1_pctl_legacy_map_func(pc, np, pin, func, ++ maps, num_maps); ++ } else if (function) { ++ err = pinctrl_utils_add_map_mux(pctldev, &maps, ++ &reserved_maps, num_maps, ++ rp1_gpio_groups[pin], ++ function); ++ } ++ ++ if (err) ++ goto out; ++ ++ if (num_pulls) { ++ err = of_property_read_u32_index(np, "brcm,pull", ++ (num_pulls > 1) ? i : 0, ++ &pull); ++ if (err) ++ goto out; ++ err = rp1_pctl_legacy_map_pull(pc, np, pin, pull, ++ maps, num_maps); ++ } else if (num_configs) { ++ err = pinctrl_utils_add_map_configs(pctldev, &maps, ++ &reserved_maps, num_maps, ++ rp1_gpio_groups[pin], ++ configs, num_configs, ++ PIN_MAP_TYPE_CONFIGS_PIN); ++ } ++ ++ if (err) ++ goto out; ++ } ++ ++ *map = maps; ++ ++ return 0; ++ ++out: ++ rp1_pctl_dt_free_map(pctldev, maps, reserved_maps); ++ return err; ++} ++ ++static const struct pinctrl_ops rp1_pctl_ops = { ++ .get_groups_count = rp1_pctl_get_groups_count, ++ .get_group_name = rp1_pctl_get_group_name, ++ .get_group_pins = rp1_pctl_get_group_pins, ++ .pin_dbg_show = rp1_pctl_pin_dbg_show, ++ .dt_node_to_map = rp1_pctl_dt_node_to_map, ++ .dt_free_map = rp1_pctl_dt_free_map, ++}; ++ ++static int rp1_pmx_free(struct pinctrl_dev *pctldev, unsigned offset) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); ++ u32 fsel = rp1_get_fsel(pin); ++ ++ /* Return non-GPIOs to GPIO_IN */ ++ if (fsel != RP1_FSEL_GPIO) { ++ rp1_set_dir(pin, RP1_DIR_INPUT); ++ rp1_set_fsel(pin, RP1_FSEL_GPIO); ++ } ++ ++ return 0; ++} ++ ++static int rp1_pmx_get_functions_count(struct pinctrl_dev *pctldev) ++{ ++ return func_count; ++} ++ ++static const char *rp1_pmx_get_function_name(struct pinctrl_dev *pctldev, ++ unsigned selector) ++{ ++ return (selector < func_count) ? rp1_func_names[selector] : NULL; ++} ++ ++static int rp1_pmx_get_function_groups(struct pinctrl_dev *pctldev, ++ unsigned selector, ++ const char * const **groups, ++ unsigned * const num_groups) ++{ ++ /* every pin can do every function */ ++ *groups = rp1_gpio_groups; ++ *num_groups = ARRAY_SIZE(rp1_gpio_groups); ++ ++ return 0; ++} ++ ++static int rp1_pmx_set(struct pinctrl_dev *pctldev, unsigned func_selector, ++ unsigned group_selector) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, group_selector); ++ const u8 *pin_funcs; ++ int fsel; ++ ++ /* func_selector is an enum funcs, so needs translation */ ++ ++ if (func_selector >= RP1_FSEL_COUNT) { ++ /* Convert to an fsel number */ ++ pin_funcs = rp1_gpio_pin_funcs[pin->num].funcs; ++ for (fsel = 0; fsel < RP1_FSEL_COUNT; fsel++) { ++ if (pin_funcs[fsel] == func_selector) ++ break; ++ } ++ } else { ++ fsel = (int)func_selector; ++ } ++ ++ if (fsel >= RP1_FSEL_COUNT && fsel != RP1_FSEL_NONE) ++ return -EINVAL; ++ ++ rp1_set_fsel(pin, fsel); ++ ++ return 0; ++} ++ ++static void rp1_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned offset) ++{ ++ (void)rp1_pmx_free(pctldev, offset); ++} ++ ++static int rp1_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, ++ struct pinctrl_gpio_range *range, ++ unsigned offset, ++ bool input) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); ++ ++ rp1_set_dir(pin, input); ++ rp1_set_fsel(pin, RP1_FSEL_GPIO); ++ ++ return 0; ++} ++ ++static const struct pinmux_ops rp1_pmx_ops = { ++ .free = rp1_pmx_free, ++ .get_functions_count = rp1_pmx_get_functions_count, ++ .get_function_name = rp1_pmx_get_function_name, ++ .get_function_groups = rp1_pmx_get_function_groups, ++ .set_mux = rp1_pmx_set, ++ .gpio_disable_free = rp1_pmx_gpio_disable_free, ++ .gpio_set_direction = rp1_pmx_gpio_set_direction, ++}; ++ ++static void rp1_pull_config_set(struct rp1_pin_info *pin, unsigned int arg) ++{ ++ u32 padctrl = readl(pin->pad); ++ ++ FLD_SET(padctrl, RP1_PAD_PULL, arg & 0x3); ++ ++ writel(padctrl, pin->pad); ++} ++ ++/* Generic pinconf methods */ ++ ++static int rp1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int offset, ++ unsigned long *configs, unsigned int num_configs) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); ++ u32 param, arg; ++ int i; ++ ++ if (!pin) ++ return -EINVAL; ++ ++ for (i = 0; i < num_configs; i++) { ++ param = pinconf_to_config_param(configs[i]); ++ arg = pinconf_to_config_argument(configs[i]); ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ rp1_pull_config_set(pin, RP1_PUD_OFF); ++ break; ++ ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ rp1_pull_config_set(pin, RP1_PUD_DOWN); ++ break; ++ ++ case PIN_CONFIG_BIAS_PULL_UP: ++ rp1_pull_config_set(pin, RP1_PUD_UP); ++ break; ++ ++ case PIN_CONFIG_INPUT_ENABLE: ++ rp1_input_enable(pin, arg); ++ break; ++ ++ case PIN_CONFIG_OUTPUT_ENABLE: ++ rp1_output_enable(pin, arg); ++ break; ++ ++ case PIN_CONFIG_OUTPUT: ++ rp1_set_value(pin, arg); ++ rp1_set_dir(pin, RP1_DIR_OUTPUT); ++ rp1_set_fsel(pin, RP1_FSEL_GPIO); ++ break; ++ ++ case PIN_CONFIG_INPUT_SCHMITT_ENABLE: ++ rp1_pad_update(pin, RP1_PAD_SCHMITT_MASK, ++ arg ? RP1_PAD_SCHMITT_MASK : 0); ++ break; ++ ++ case PIN_CONFIG_SLEW_RATE: ++ rp1_pad_update(pin, RP1_PAD_SLEWFAST_MASK, ++ arg ? RP1_PAD_SLEWFAST_MASK : 0); ++ break; ++ ++ case PIN_CONFIG_DRIVE_STRENGTH: ++ switch (arg) { ++ case 2: ++ arg = RP1_PAD_DRIVE_2MA; ++ break; ++ case 4: ++ arg = RP1_PAD_DRIVE_4MA; ++ break; ++ case 8: ++ arg = RP1_PAD_DRIVE_8MA; ++ break; ++ case 12: ++ arg = RP1_PAD_DRIVE_12MA; ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ rp1_pad_update(pin, RP1_PAD_DRIVE_MASK, arg); ++ break; ++ ++ default: ++ return -ENOTSUPP; ++ ++ } /* switch param type */ ++ } /* for each config */ ++ ++ return 0; ++} ++ ++static int rp1_pinconf_get(struct pinctrl_dev *pctldev, unsigned offset, ++ unsigned long *config) ++{ ++ struct rp1_pin_info *pin = rp1_get_pin_pctl(pctldev, offset); ++ enum pin_config_param param = pinconf_to_config_param(*config); ++ u32 padctrl; ++ u32 arg; ++ ++ if (!pin) ++ return -EINVAL; ++ ++ padctrl = readl(pin->pad); ++ ++ switch (param) { ++ case PIN_CONFIG_INPUT_ENABLE: ++ arg = !!(padctrl & RP1_PAD_IN_ENABLE_MASK); ++ break; ++ case PIN_CONFIG_OUTPUT_ENABLE: ++ arg = !(padctrl & RP1_PAD_OUT_DISABLE_MASK); ++ break; ++ case PIN_CONFIG_INPUT_SCHMITT_ENABLE: ++ arg = !!(padctrl & RP1_PAD_SCHMITT_MASK); ++ break; ++ case PIN_CONFIG_SLEW_RATE: ++ arg = !!(padctrl & RP1_PAD_SLEWFAST_MASK); ++ break; ++ case PIN_CONFIG_DRIVE_STRENGTH: ++ switch (padctrl & RP1_PAD_DRIVE_MASK) { ++ case RP1_PAD_DRIVE_2MA: ++ arg = 2; ++ break; ++ case RP1_PAD_DRIVE_4MA: ++ arg = 4; ++ break; ++ case RP1_PAD_DRIVE_8MA: ++ arg = 8; ++ break; ++ case RP1_PAD_DRIVE_12MA: ++ arg = 12; ++ break; ++ } ++ break; ++ case PIN_CONFIG_BIAS_DISABLE: ++ arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_OFF << RP1_PAD_PULL_LSB)); ++ break; ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_DOWN << RP1_PAD_PULL_LSB)); ++ break; ++ ++ case PIN_CONFIG_BIAS_PULL_UP: ++ arg = ((padctrl & RP1_PAD_PULL_MASK) == (RP1_PUD_UP << RP1_PAD_PULL_LSB)); ++ break; ++ default: ++ return -ENOTSUPP; ++ } ++ ++ *config = pinconf_to_config_packed(param, arg); ++ ++ return 0; ++} ++ ++static const struct pinconf_ops rp1_pinconf_ops = { ++ .is_generic = true, ++ .pin_config_get = rp1_pinconf_get, ++ .pin_config_set = rp1_pinconf_set, ++}; ++ ++static struct pinctrl_desc rp1_pinctrl_desc = { ++ .name = MODULE_NAME, ++ .pins = rp1_gpio_pins, ++ .npins = ARRAY_SIZE(rp1_gpio_pins), ++ .pctlops = &rp1_pctl_ops, ++ .pmxops = &rp1_pmx_ops, ++ .confops = &rp1_pinconf_ops, ++ .owner = THIS_MODULE, ++}; ++ ++static struct pinctrl_gpio_range rp1_pinctrl_gpio_range = { ++ .name = MODULE_NAME, ++ .npins = RP1_NUM_GPIOS, ++}; ++ ++static const struct of_device_id rp1_pinctrl_match[] = { ++ { ++ .compatible = "raspberrypi,rp1-gpio", ++ .data = &rp1_pinconf_ops, ++ }, ++ {} ++}; ++ ++static inline void __iomem *devm_auto_iomap(struct platform_device *pdev, ++ unsigned int index) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ ++ if (np) ++ return devm_of_iomap(dev, np, (int)index, NULL); ++ else ++ return devm_platform_ioremap_resource(pdev, index); ++} ++ ++static int rp1_pinctrl_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct rp1_pinctrl *pc; ++ struct gpio_irq_chip *girq; ++ int err, i; ++ ++ BUILD_BUG_ON(ARRAY_SIZE(rp1_gpio_pins) != RP1_NUM_GPIOS); ++ BUILD_BUG_ON(ARRAY_SIZE(rp1_gpio_groups) != RP1_NUM_GPIOS); ++ ++ pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); ++ if (!pc) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, pc); ++ pc->dev = dev; ++ ++ pc->gpio_base = devm_auto_iomap(pdev, 0); ++ if (IS_ERR(pc->gpio_base)) { ++ dev_err(dev, "could not get GPIO IO memory\n"); ++ return PTR_ERR(pc->gpio_base); ++ } ++ ++ pc->rio_base = devm_auto_iomap(pdev, 1); ++ if (IS_ERR(pc->rio_base)) { ++ dev_err(dev, "could not get RIO IO memory\n"); ++ return PTR_ERR(pc->rio_base); ++ } ++ ++ pc->pads_base = devm_auto_iomap(pdev, 2); ++ if (IS_ERR(pc->pads_base)) { ++ dev_err(dev, "could not get PADS IO memory\n"); ++ return PTR_ERR(pc->pads_base); ++ } ++ ++ pc->gpio_chip = rp1_gpio_chip; ++ pc->gpio_chip.parent = dev; ++ ++ for (i = 0; i < RP1_NUM_BANKS; i++) { ++ const struct rp1_iobank_desc *bank = &rp1_iobanks[i]; ++ int j; ++ ++ for (j = 0; j < bank->num_gpios; j++) { ++ struct rp1_pin_info *pin = ++ &pc->pins[bank->min_gpio + j]; ++ ++ pin->num = bank->min_gpio + j; ++ pin->bank = i; ++ pin->offset = j; ++ ++ pin->gpio = pc->gpio_base + bank->gpio_offset + ++ j * sizeof(u32) * 2; ++ pin->inte = pc->gpio_base + bank->inte_offset; ++ pin->ints = pc->gpio_base + bank->ints_offset; ++ pin->rio = pc->rio_base + bank->rio_offset; ++ pin->pad = pc->pads_base + bank->pads_offset + ++ j * sizeof(u32); ++ } ++ ++ raw_spin_lock_init(&pc->irq_lock[i]); ++ } ++ ++ pc->pctl_dev = devm_pinctrl_register(dev, &rp1_pinctrl_desc, pc); ++ if (IS_ERR(pc->pctl_dev)) ++ return PTR_ERR(pc->pctl_dev); ++ ++ girq = &pc->gpio_chip.irq; ++ girq->chip = &rp1_gpio_irq_chip; ++ girq->parent_handler = rp1_gpio_irq_handler; ++ girq->num_parents = RP1_NUM_BANKS; ++ girq->parents = pc->irq; ++ ++ /* ++ * Use the same handler for all groups: this is necessary ++ * since we use one gpiochip to cover all lines - the ++ * irq handler then needs to figure out which group and ++ * bank that was firing the IRQ and look up the per-group ++ * and bank data. ++ */ ++ for (i = 0; i < RP1_NUM_BANKS; i++) { ++ pc->irq[i] = irq_of_parse_and_map(np, i); ++ if (!pc->irq[i]) { ++ girq->num_parents = i; ++ break; ++ } ++ } ++ ++ girq->default_type = IRQ_TYPE_NONE; ++ girq->handler = handle_level_irq; ++ ++ err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc); ++ if (err) { ++ dev_err(dev, "could not add GPIO chip\n"); ++ return err; ++ } ++ ++ pc->gpio_range = rp1_pinctrl_gpio_range; ++ pc->gpio_range.base = pc->gpio_chip.base; ++ pc->gpio_range.gc = &pc->gpio_chip; ++ pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); ++ ++ return 0; ++} ++ ++static struct platform_driver rp1_pinctrl_driver = { ++ .probe = rp1_pinctrl_probe, ++ .driver = { ++ .name = MODULE_NAME, ++ .of_match_table = rp1_pinctrl_match, ++ .suppress_bind_attrs = true, ++ }, ++}; ++builtin_platform_driver(rp1_pinctrl_driver); +--- a/include/dt-bindings/pinctrl/rp1.h ++++ /dev/null +@@ -1,46 +0,0 @@ +-/* 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__ */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0877-serial-pl011-rp1-uart-support.patch b/target/linux/bcm27xx/patches-6.1/950-0877-serial-pl011-rp1-uart-support.patch new file mode 100644 index 0000000000..b0b9897e89 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0877-serial-pl011-rp1-uart-support.patch @@ -0,0 +1,129 @@ +From f88da9e21d8eff58eeb9280ae96bf9593121d8eb Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 12 Oct 2022 13:24:51 +0100 +Subject: [PATCH] serial: pl011: rp1 uart support + +Signed-off-by: Phil Elwell +--- + 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); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-0878-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch b/target/linux/bcm27xx/patches-6.1/950-0878-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch new file mode 100644 index 0000000000..6bc21a6a57 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0878-mmc-sdhci-of-dwcmshc-define-sdio-timeout-clocks.patch @@ -0,0 +1,83 @@ +From 4a5ac516ca0a820e7c006ae408872009e37e114b Mon Sep 17 00:00:00 2001 +From: Liam Fraser +Date: Thu, 14 Mar 2019 16:01:26 +0000 +Subject: [PATCH] mmc: sdhci-of-dwcmshc: define sdio timeout clocks + +Signed-off-by: Liam Fraser +--- + 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; diff --git a/target/linux/bcm27xx/patches-6.1/950-0879-mmc-sdhci-of-dwcmshc-rp1-sdio-changes.patch b/target/linux/bcm27xx/patches-6.1/950-0879-mmc-sdhci-of-dwcmshc-rp1-sdio-changes.patch new file mode 100644 index 0000000000..12d614fd94 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0879-mmc-sdhci-of-dwcmshc-rp1-sdio-changes.patch @@ -0,0 +1,83 @@ +From 14a43b3fd43bf9b230f93d1eba276d40aac969ba Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 12 Oct 2022 14:07:32 +0100 +Subject: [PATCH] mmc: sdhci-of-dwcmshc: rp1 sdio changes + +Signed-off-by: Phil Elwell +--- + 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; diff --git a/target/linux/bcm27xx/patches-6.1/950-0880-clk-rp1-Add-sdio-clk-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0880-clk-rp1-Add-sdio-clk-driver.patch new file mode 100644 index 0000000000..7db5202ae4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0880-clk-rp1-Add-sdio-clk-driver.patch @@ -0,0 +1,641 @@ +From b427cc1a83404f48b12dec2efbef076b38df6218 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 12 Oct 2022 14:20:07 +0100 +Subject: [PATCH] clk: rp1: Add sdio-clk driver + +Signed-off-by: Phil Elwell +--- + 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 ++#include ++#include ++#include ++#include ++ ++// 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 "); ++MODULE_DESCRIPTION("RP1 SDIO clock driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0881-i2c-designware-Add-SMBUS-quick-command-support.patch b/target/linux/bcm27xx/patches-6.1/950-0881-i2c-designware-Add-SMBUS-quick-command-support.patch new file mode 100644 index 0000000000..ea3b315501 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0881-i2c-designware-Add-SMBUS-quick-command-support.patch @@ -0,0 +1,76 @@ +From 50adadfaf324ed5cbb59ce2b85eda59de4e3801a Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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; diff --git a/target/linux/bcm27xx/patches-6.1/950-0882-dmaengine-dw-axi-dmac-Fixes-for-RP1.patch b/target/linux/bcm27xx/patches-6.1/950-0882-dmaengine-dw-axi-dmac-Fixes-for-RP1.patch new file mode 100644 index 0000000000..fff6cfdeb4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0882-dmaengine-dw-axi-dmac-Fixes-for-RP1.patch @@ -0,0 +1,355 @@ +From 0a1cd70189daec3baf4b4a233dd8e25ffbb9d512 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + .../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 + #include + #include ++#include + #include + #include + #include +@@ -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; diff --git a/target/linux/bcm27xx/patches-6.1/950-0883-spi-dw-Handle-combined-tx-and-rx-messages.patch b/target/linux/bcm27xx/patches-6.1/950-0883-spi-dw-Handle-combined-tx-and-rx-messages.patch new file mode 100644 index 0000000000..68eca7961f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0883-spi-dw-Handle-combined-tx-and-rx-messages.patch @@ -0,0 +1,64 @@ +From 8a9c0607ce0daa91c48faefd70ea73bda54ed0ae Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 29 Nov 2022 10:09:54 +0000 +Subject: [PATCH] spi: dw: Handle combined tx and rx messages + +Signed-off-by: Phil Elwell +--- + 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 + #include + #include ++#include + + #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)) diff --git a/target/linux/bcm27xx/patches-6.1/950-0884-pwm-Add-support-for-RP1-PWM.patch b/target/linux/bcm27xx/patches-6.1/950-0884-pwm-Add-support-for-RP1-PWM.patch new file mode 100644 index 0000000000..241d6c49db --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0884-pwm-Add-support-for-RP1-PWM.patch @@ -0,0 +1,292 @@ +From 824f18efc8ad59e2783570ae2df83e2cd16b9f04 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + .../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 ++ ++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 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 +Date: Tue, 14 Feb 2023 14:58:33 +0000 +Subject: [PATCH] drm: Add RP1 DSI driver + +Add support for the RP1 DSI hardware. + +Signed-off-by: Nick Hollinghurst +--- + drivers/gpu/drm/Kconfig | 2 + + drivers/gpu/drm/Makefile | 1 + + drivers/gpu/drm/rp1/Kconfig | 5 + + drivers/gpu/drm/rp1/Makefile | 4 + + drivers/gpu/drm/rp1/rp1-dsi/Kconfig | 15 + + drivers/gpu/drm/rp1/rp1-dsi/Makefile | 5 + + drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c | 537 ++++++++ + drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h | 94 ++ + drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dma.c | 443 ++++++ + drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c | 1504 +++++++++++++++++++++ + 10 files changed, 2610 insertions(+) + create mode 100644 drivers/gpu/drm/rp1/Kconfig + create mode 100644 drivers/gpu/drm/rp1/Makefile + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/Kconfig + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/Makefile + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dma.c + create mode 100644 drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c + +--- a/drivers/gpu/drm/Kconfig ++++ b/drivers/gpu/drm/Kconfig +@@ -384,6 +384,8 @@ source "drivers/gpu/drm/v3d/Kconfig" + + source "drivers/gpu/drm/vc4/Kconfig" + ++source "drivers/gpu/drm/rp1/Kconfig" ++ + source "drivers/gpu/drm/etnaviv/Kconfig" + + source "drivers/gpu/drm/hisilicon/Kconfig" +--- a/drivers/gpu/drm/Makefile ++++ b/drivers/gpu/drm/Makefile +@@ -148,3 +148,4 @@ obj-y += gud/ + obj-$(CONFIG_DRM_HYPERV) += hyperv/ + obj-y += solomon/ + obj-$(CONFIG_DRM_SPRD) += sprd/ ++obj-y += rp1/ +--- /dev/null ++++ b/drivers/gpu/drm/rp1/Kconfig +@@ -0,0 +1,5 @@ ++source "drivers/gpu/drm/rp1/rp1-dsi/Kconfig" ++ ++source "drivers/gpu/drm/rp1/rp1-dpi/Kconfig" ++ ++source "drivers/gpu/drm/rp1/rp1-vec/Kconfig" +--- /dev/null ++++ b/drivers/gpu/drm/rp1/Makefile +@@ -0,0 +1,4 @@ ++obj-$(CONFIG_DRM_RP1_DSI) += rp1-dsi/ ++obj-$(CONFIG_DRM_RP1_DPI) += rp1-dpi/ ++obj-$(CONFIG_DRM_RP1_VEC) += rp1-vec/ ++ +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/Kconfig +@@ -0,0 +1,15 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config DRM_RP1_DSI ++ tristate "DRM Support for RP1 DSI" ++ depends on DRM ++ select MFD_RP1 ++ select DRM_GEM_DMA_HELPER ++ select DRM_KMS_HELPER ++ select DRM_MIPI_DSI ++ select DRM_VRAM_HELPER ++ select DRM_TTM ++ select DRM_TTM_HELPER ++ select GENERIC_PHY ++ select GENERIC_PHY_MIPI_DPHY ++ help ++ Choose this option to enable DSI display on RP1 +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/Makefile +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++drm-rp1-dsi-y := rp1_dsi.o rp1_dsi_dma.o rp1_dsi_dsi.o ++ ++obj-$(CONFIG_DRM_RP1_DSI) += drm-rp1-dsi.o +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c +@@ -0,0 +1,537 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_dsi.h" ++ ++static inline struct rp1_dsi * ++bridge_to_rp1_dsi(struct drm_bridge *bridge) ++{ ++ return container_of(bridge, struct rp1_dsi, bridge); ++} ++ ++static void rp1_dsi_bridge_pre_enable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) ++{ ++ struct rp1_dsi *dsi = bridge_to_rp1_dsi(bridge); ++ ++ rp1dsi_dsi_setup(dsi, &dsi->pipe.crtc.state->adjusted_mode); ++} ++ ++static void rp1_dsi_bridge_enable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) ++{ ++} ++ ++static void rp1_dsi_bridge_disable(struct drm_bridge *bridge, ++ struct drm_bridge_state *state) ++{ ++} ++ ++static void rp1_dsi_bridge_post_disable(struct drm_bridge *bridge, ++ struct drm_bridge_state *state) ++{ ++ struct rp1_dsi *dsi = bridge_to_rp1_dsi(bridge); ++ ++ if (dsi->dsi_running) { ++ rp1dsi_dsi_stop(dsi); ++ dsi->dsi_running = false; ++ } ++} ++ ++static int rp1_dsi_bridge_attach(struct drm_bridge *bridge, ++ enum drm_bridge_attach_flags flags) ++{ ++ struct rp1_dsi *dsi = bridge_to_rp1_dsi(bridge); ++ ++ /* Attach the panel or bridge to the dsi bridge */ ++ return drm_bridge_attach(bridge->encoder, dsi->out_bridge, ++ &dsi->bridge, flags); ++ return 0; ++} ++ ++static const struct drm_bridge_funcs rp1_dsi_bridge_funcs = { ++ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, ++ .atomic_reset = drm_atomic_helper_bridge_reset, ++ .atomic_pre_enable = rp1_dsi_bridge_pre_enable, ++ .atomic_enable = rp1_dsi_bridge_enable, ++ .atomic_disable = rp1_dsi_bridge_disable, ++ .atomic_post_disable = rp1_dsi_bridge_post_disable, ++ .attach = rp1_dsi_bridge_attach, ++}; ++ ++static void rp1dsi_pipe_update(struct drm_simple_display_pipe *pipe, ++ struct drm_plane_state *old_state) ++{ ++ struct drm_pending_vblank_event *event; ++ unsigned long flags; ++ struct drm_framebuffer *fb = pipe->plane.state->fb; ++ struct rp1_dsi *dsi = pipe->crtc.dev->dev_private; ++ struct drm_gem_object *gem = fb ? drm_gem_fb_get_obj(fb, 0) : NULL; ++ struct drm_gem_dma_object *dma_obj = gem ? to_drm_gem_dma_obj(gem) : NULL; ++ bool can_update = fb && dma_obj && dsi && dsi->pipe_enabled; ++ ++ /* (Re-)start DSI,DMA where required; and update FB address */ ++ if (can_update) { ++ if (!dsi->dma_running || fb->format->format != dsi->cur_fmt) { ++ if (dsi->dma_running && fb->format->format != dsi->cur_fmt) { ++ rp1dsi_dma_stop(dsi); ++ dsi->dma_running = false; ++ } ++ if (!dsi->dma_running) { ++ rp1dsi_dma_setup(dsi, ++ fb->format->format, dsi->display_format, ++ &pipe->crtc.state->adjusted_mode); ++ dsi->dma_running = true; ++ } ++ dsi->cur_fmt = fb->format->format; ++ drm_crtc_vblank_on(&pipe->crtc); ++ } ++ rp1dsi_dma_update(dsi, dma_obj->dma_addr, fb->offsets[0], fb->pitches[0]); ++ } ++ ++ /* Arm VBLANK event (or call it immediately in some error cases) */ ++ spin_lock_irqsave(&pipe->crtc.dev->event_lock, flags); ++ event = pipe->crtc.state->event; ++ if (event) { ++ pipe->crtc.state->event = NULL; ++ if (can_update && drm_crtc_vblank_get(&pipe->crtc) == 0) ++ drm_crtc_arm_vblank_event(&pipe->crtc, event); ++ else ++ drm_crtc_send_vblank_event(&pipe->crtc, event); ++ } ++ spin_unlock_irqrestore(&pipe->crtc.dev->event_lock, flags); ++} ++ ++static inline struct rp1_dsi * ++encoder_to_rp1_dsi(struct drm_encoder *encoder) ++{ ++ struct drm_simple_display_pipe *pipe = ++ container_of(encoder, struct drm_simple_display_pipe, encoder); ++ return container_of(pipe, struct rp1_dsi, pipe); ++} ++ ++static void rp1dsi_encoder_enable(struct drm_encoder *encoder) ++{ ++ struct rp1_dsi *dsi = encoder_to_rp1_dsi(encoder); ++ ++ /* Put DSI into video mode before starting video */ ++ rp1dsi_dsi_set_cmdmode(dsi, 0); ++ ++ /* Start DMA -> DPI */ ++ dsi->pipe_enabled = true; ++ dsi->cur_fmt = 0xdeadbeef; ++ rp1dsi_pipe_update(&dsi->pipe, 0); ++} ++ ++static void rp1dsi_encoder_disable(struct drm_encoder *encoder) ++{ ++ struct rp1_dsi *dsi = encoder_to_rp1_dsi(encoder); ++ ++ drm_crtc_vblank_off(&dsi->pipe.crtc); ++ if (dsi->dma_running) { ++ rp1dsi_dma_stop(dsi); ++ dsi->dma_running = false; ++ } ++ dsi->pipe_enabled = false; ++ ++ /* Return to command mode after stopping video */ ++ rp1dsi_dsi_set_cmdmode(dsi, 1); ++} ++ ++static const struct drm_encoder_helper_funcs rp1_dsi_encoder_funcs = { ++ .enable = rp1dsi_encoder_enable, ++ .disable = rp1dsi_encoder_disable, ++}; ++ ++static void rp1dsi_pipe_enable(struct drm_simple_display_pipe *pipe, ++ struct drm_crtc_state *crtc_state, ++ struct drm_plane_state *plane_state) ++{ ++} ++ ++static void rp1dsi_pipe_disable(struct drm_simple_display_pipe *pipe) ++{ ++} ++ ++static int rp1dsi_pipe_enable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_dsi *dsi = pipe->crtc.dev->dev_private; ++ ++ if (dsi) ++ rp1dsi_dma_vblank_ctrl(dsi, 1); ++ ++ return 0; ++} ++ ++static void rp1dsi_pipe_disable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_dsi *dsi = pipe->crtc.dev->dev_private; ++ ++ if (dsi) ++ rp1dsi_dma_vblank_ctrl(dsi, 0); ++} ++ ++static const struct drm_simple_display_pipe_funcs rp1dsi_pipe_funcs = { ++ .enable = rp1dsi_pipe_enable, ++ .update = rp1dsi_pipe_update, ++ .disable = rp1dsi_pipe_disable, ++ .prepare_fb = drm_gem_simple_display_pipe_prepare_fb, ++ .enable_vblank = rp1dsi_pipe_enable_vblank, ++ .disable_vblank = rp1dsi_pipe_disable_vblank, ++}; ++ ++static const struct drm_mode_config_funcs rp1dsi_mode_funcs = { ++ .fb_create = drm_gem_fb_create, ++ .atomic_check = drm_atomic_helper_check, ++ .atomic_commit = drm_atomic_helper_commit, ++}; ++ ++static const u32 rp1dsi_formats[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_RGB888, ++ DRM_FORMAT_BGR888, ++ DRM_FORMAT_RGB565 ++}; ++ ++static void rp1dsi_stopall(struct drm_device *drm) ++{ ++ if (drm->dev_private) { ++ struct rp1_dsi *dsi = drm->dev_private; ++ ++ if (dsi->dma_running || rp1dsi_dma_busy(dsi)) { ++ rp1dsi_dma_stop(dsi); ++ dsi->dma_running = false; ++ } ++ if (dsi->dsi_running) { ++ rp1dsi_dsi_stop(dsi); ++ dsi->dsi_running = false; ++ } ++ if (dsi->clocks[RP1DSI_CLOCK_CFG]) ++ clk_disable_unprepare(dsi->clocks[RP1DSI_CLOCK_CFG]); ++ } ++} ++ ++DEFINE_DRM_GEM_DMA_FOPS(rp1dsi_fops); ++ ++static struct drm_driver rp1dsi_driver = { ++ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, ++ .fops = &rp1dsi_fops, ++ .name = "drm-rp1-dsi", ++ .desc = "drm-rp1-dsi", ++ .date = "0", ++ .major = 1, ++ .minor = 0, ++ DRM_GEM_DMA_DRIVER_OPS, ++ .release = rp1dsi_stopall, ++}; ++ ++static int rp1dsi_bind(struct rp1_dsi *dsi) ++{ ++ struct platform_device *pdev = dsi->pdev; ++ struct drm_device *drm = dsi->drm; ++ int ret; ++ ++ dsi->out_bridge = drmm_of_get_bridge(drm, pdev->dev.of_node, 0, 0); ++ if (IS_ERR(dsi->out_bridge)) ++ return PTR_ERR(dsi->out_bridge); ++ ++ ret = drmm_mode_config_init(drm); ++ if (ret) ++ goto rtn; ++ ++ drm->mode_config.max_width = 4096; ++ drm->mode_config.max_height = 4096; ++ drm->mode_config.fb_base = 0; ++ drm->mode_config.preferred_depth = 32; ++ drm->mode_config.prefer_shadow = 0; ++ drm->mode_config.prefer_shadow_fbdev = 1; ++ drm->mode_config.quirk_addfb_prefer_host_byte_order = true; ++ drm->mode_config.funcs = &rp1dsi_mode_funcs; ++ drm_vblank_init(drm, 1); ++ ++ ret = drm_simple_display_pipe_init(drm, ++ &dsi->pipe, ++ &rp1dsi_pipe_funcs, ++ rp1dsi_formats, ++ ARRAY_SIZE(rp1dsi_formats), ++ NULL, NULL); ++ if (ret) ++ goto rtn; ++ ++ /* We need slightly more complex encoder handling (enabling/disabling ++ * video mode), so add encoder helper functions. ++ */ ++ drm_encoder_helper_add(&dsi->pipe.encoder, &rp1_dsi_encoder_funcs); ++ ++ ret = drm_simple_display_pipe_attach_bridge(&dsi->pipe, &dsi->bridge); ++ if (ret) ++ goto rtn; ++ ++ drm_bridge_add(&dsi->bridge); ++ ++ drm_mode_config_reset(drm); ++ ++ if (dsi->clocks[RP1DSI_CLOCK_CFG]) ++ clk_prepare_enable(dsi->clocks[RP1DSI_CLOCK_CFG]); ++ ++ ret = drm_dev_register(drm, 0); ++ ++ if (ret == 0) ++ drm_fbdev_generic_setup(drm, 32); ++ ++rtn: ++ if (ret) ++ dev_err(&pdev->dev, "%s returned %d\n", __func__, ret); ++ else ++ dev_info(&pdev->dev, "%s succeeded", __func__); ++ ++ return ret; ++} ++ ++static void rp1dsi_unbind(struct rp1_dsi *dsi) ++{ ++ struct drm_device *drm = dsi->drm; ++ ++ rp1dsi_stopall(drm); ++ drm_dev_unregister(drm); ++ drm_atomic_helper_shutdown(drm); ++} ++ ++int rp1dsi_host_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *dsi_dev) ++{ ++ struct rp1_dsi *dsi = container_of(host, struct rp1_dsi, dsi_host); ++ ++ dev_info(&dsi->pdev->dev, "%s: Attach DSI device name=%s channel=%d lanes=%d format=%d flags=0x%lx hs_rate=%lu lp_rate=%lu", ++ __func__, dsi_dev->name, dsi_dev->channel, dsi_dev->lanes, ++ dsi_dev->format, dsi_dev->mode_flags, dsi_dev->hs_rate, ++ dsi_dev->lp_rate); ++ dsi->vc = dsi_dev->channel & 3; ++ dsi->lanes = dsi_dev->lanes; ++ ++ switch (dsi_dev->format) { ++ case MIPI_DSI_FMT_RGB666: ++ case MIPI_DSI_FMT_RGB666_PACKED: ++ case MIPI_DSI_FMT_RGB565: ++ case MIPI_DSI_FMT_RGB888: ++ break; ++ default: ++ return -EINVAL; ++ } ++ dsi->display_format = dsi_dev->format; ++ dsi->display_flags = dsi_dev->mode_flags; ++ dsi->display_hs_rate = dsi_dev->hs_rate; ++ dsi->display_lp_rate = dsi_dev->lp_rate; ++ ++ /* ++ * Previously, we added a separate component to handle panel/bridge ++ * discovery and DRM registration, but now it's just a function call. ++ * The downstream/attaching device should deal with -EPROBE_DEFER ++ */ ++ return rp1dsi_bind(dsi); ++} ++ ++int rp1dsi_host_detach(struct mipi_dsi_host *host, struct mipi_dsi_device *dsi_dev) ++{ ++ struct rp1_dsi *dsi = container_of(host, struct rp1_dsi, dsi_host); ++ ++ /* ++ * Unregister the DRM driver. ++ * TODO: Check we are cleaning up correctly and not doing things multiple times! ++ */ ++ rp1dsi_unbind(dsi); ++ return 0; ++} ++ ++ssize_t rp1dsi_host_transfer(struct mipi_dsi_host *host, const struct mipi_dsi_msg *msg) ++{ ++ struct rp1_dsi *dsi = container_of(host, struct rp1_dsi, dsi_host); ++ struct mipi_dsi_packet packet; ++ int ret = 0; ++ ++ /* Write */ ++ ret = mipi_dsi_create_packet(&packet, msg); ++ if (ret) { ++ dev_err(dsi->drm->dev, "RP1DSI: failed to create packet: %d\n", ret); ++ return ret; ++ } ++ ++ rp1dsi_dsi_send(dsi, *(u32 *)(&packet.header), packet.payload_length, packet.payload); ++ ++ /* Optional read back */ ++ if (msg->rx_len && msg->rx_buf) ++ ret = rp1dsi_dsi_recv(dsi, msg->rx_len, msg->rx_buf); ++ ++ return (ssize_t)ret; ++} ++ ++static const struct mipi_dsi_host_ops rp1dsi_mipi_dsi_host_ops = { ++ .attach = rp1dsi_host_attach, ++ .detach = rp1dsi_host_detach, ++ .transfer = rp1dsi_host_transfer ++}; ++ ++static int rp1dsi_platform_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct drm_device *drm; ++ struct rp1_dsi *dsi; ++ int i, ret; ++ ++ drm = drm_dev_alloc(&rp1dsi_driver, dev); ++ if (IS_ERR(drm)) { ++ ret = PTR_ERR(drm); ++ return ret; ++ } ++ dsi = drmm_kzalloc(drm, sizeof(*dsi), GFP_KERNEL); ++ if (!dsi) { ++ ret = -ENOMEM; ++ goto err_free_drm; ++ } ++ init_completion(&dsi->finished); ++ dsi->drm = drm; ++ dsi->pdev = pdev; ++ drm->dev_private = dsi; ++ platform_set_drvdata(pdev, drm); ++ ++ dsi->bridge.funcs = &rp1_dsi_bridge_funcs; ++ dsi->bridge.of_node = dev->of_node; ++ dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; ++ ++ /* Safe default values for DSI mode */ ++ dsi->lanes = 1; ++ dsi->display_format = MIPI_DSI_FMT_RGB888; ++ dsi->display_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM; ++ ++ /* Hardware resources */ ++ for (i = 0; i < RP1DSI_NUM_CLOCKS; i++) { ++ static const char * const myclocknames[RP1DSI_NUM_CLOCKS] = { ++ "cfgclk", "dpiclk", "byteclk", "refclk" ++ }; ++ dsi->clocks[i] = devm_clk_get(dev, myclocknames[i]); ++ if (IS_ERR(dsi->clocks[i])) { ++ ret = PTR_ERR(dsi->clocks[i]); ++ dev_err(dev, "Error getting clocks[%d]\n", i); ++ goto err_free_drm; ++ } ++ } ++ ++ for (i = 0; i < RP1DSI_NUM_HW_BLOCKS; i++) { ++ dsi->hw_base[i] = ++ devm_ioremap_resource(dev, ++ platform_get_resource(dsi->pdev, ++ IORESOURCE_MEM, ++ i)); ++ if (IS_ERR(dsi->hw_base[i])) { ++ ret = PTR_ERR(dsi->hw_base[i]); ++ dev_err(dev, "Error memory mapping regs[%d]\n", i); ++ goto err_free_drm; ++ } ++ } ++ ret = platform_get_irq(dsi->pdev, 0); ++ if (ret > 0) ++ ret = devm_request_irq(dev, ret, rp1dsi_dma_isr, ++ IRQF_SHARED, "rp1-dsi", dsi); ++ if (ret) { ++ dev_err(dev, "Unable to request interrupt\n"); ++ ret = -EINVAL; ++ goto err_free_drm; ++ } ++ rp1dsi_mipicfg_setup(dsi); ++ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); ++ ++ /* Create the MIPI DSI Host and wait for the panel/bridge to attach to it */ ++ dsi->dsi_host.ops = &rp1dsi_mipi_dsi_host_ops; ++ dsi->dsi_host.dev = dev; ++ ret = mipi_dsi_host_register(&dsi->dsi_host); ++ if (ret) ++ goto err_free_drm; ++ ++ return ret; ++ ++err_free_drm: ++ dev_err(dev, "%s fail %d\n", __func__, ret); ++ drm_dev_put(drm); ++ return ret; ++} ++ ++static int rp1dsi_platform_remove(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ struct rp1_dsi *dsi = drm->dev_private; ++ ++ mipi_dsi_host_unregister(&dsi->dsi_host); ++ return 0; ++} ++ ++static void rp1dsi_platform_shutdown(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ ++ rp1dsi_stopall(drm); ++} ++ ++static const struct of_device_id rp1dsi_of_match[] = { ++ { ++ .compatible = "raspberrypi,rp1dsi", ++ }, ++ { /* sentinel */ }, ++}; ++ ++MODULE_DEVICE_TABLE(of, rp1dsi_of_match); ++ ++static struct platform_driver rp1dsi_platform_driver = { ++ .probe = rp1dsi_platform_probe, ++ .remove = rp1dsi_platform_remove, ++ .shutdown = rp1dsi_platform_shutdown, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = rp1dsi_of_match, ++ }, ++}; ++ ++module_platform_driver(rp1dsi_platform_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("MIPI DSI driver for Raspberry Pi RP1"); ++MODULE_AUTHOR("Nick Hollinghurst"); +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h +@@ -0,0 +1,94 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++#ifndef _RP1_DSI_H_ ++#define _RP1_DSI_H_ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "drm-rp1-dsi" ++#define DRIVER_NAME "drm-rp1-dsi" ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define RP1DSI_HW_BLOCK_DMA 0 ++#define RP1DSI_HW_BLOCK_DSI 1 ++#define RP1DSI_HW_BLOCK_CFG 2 ++#define RP1DSI_NUM_HW_BLOCKS 3 ++ ++#define RP1DSI_CLOCK_CFG 0 ++#define RP1DSI_CLOCK_DPI 1 ++#define RP1DSI_CLOCK_BYTE 2 ++#define RP1DSI_CLOCK_REF 3 ++#define RP1DSI_NUM_CLOCKS 4 ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct rp1_dsi { ++ /* DRM and platform device pointers */ ++ struct drm_device *drm; ++ struct platform_device *pdev; ++ ++ /* Framework and helper objects */ ++ struct drm_simple_display_pipe pipe; ++ struct drm_bridge bridge; ++ struct drm_bridge *out_bridge; ++ struct mipi_dsi_host dsi_host; ++ ++ /* Clocks. We need DPI clock; the others are frequency references */ ++ struct clk *clocks[RP1DSI_NUM_CLOCKS]; ++ ++ /* Block (DSI DMA, DSI Host) base addresses, and current state */ ++ void __iomem *hw_base[RP1DSI_NUM_HW_BLOCKS]; ++ u32 cur_fmt; ++ bool dsi_running, dma_running, pipe_enabled; ++ struct completion finished; ++ ++ /* Attached display parameters (from mipi_dsi_device) */ ++ unsigned long display_flags, display_hs_rate, display_lp_rate; ++ enum mipi_dsi_pixel_format display_format; ++ u8 vc; ++ u8 lanes; ++ ++ /* DPHY */ ++ u8 hsfreq_index; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the DSI/DPI/DMA block */ ++ ++void rp1dsi_dma_setup(struct rp1_dsi *dsi, ++ u32 in_format, enum mipi_dsi_pixel_format out_format, ++ struct drm_display_mode const *mode); ++void rp1dsi_dma_update(struct rp1_dsi *dsi, dma_addr_t addr, u32 offset, u32 stride); ++void rp1dsi_dma_stop(struct rp1_dsi *dsi); ++int rp1dsi_dma_busy(struct rp1_dsi *dsi); ++irqreturn_t rp1dsi_dma_isr(int irq, void *dev); ++void rp1dsi_dma_vblank_ctrl(struct rp1_dsi *dsi, int enable); ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the MIPICFG block and check RP1 platform */ ++ ++void rp1dsi_mipicfg_setup(struct rp1_dsi *dsi); ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the SNPS D-PHY and DSI block setup */ ++ ++void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode); ++void rp1dsi_dsi_send(struct rp1_dsi *dsi, u32 header, int len, const u8 *buf); ++int rp1dsi_dsi_recv(struct rp1_dsi *dsi, int len, u8 *buf); ++void rp1dsi_dsi_set_cmdmode(struct rp1_dsi *dsi, int cmd_mode); ++void rp1dsi_dsi_stop(struct rp1_dsi *dsi); ++ ++#endif ++ +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dma.c +@@ -0,0 +1,443 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "rp1_dsi.h" ++ ++// --- DPI DMA REGISTERS (derived from Argon firmware, via RP1 drivers/mipi, with corrections) --- ++ ++// Control ++#define DPI_DMA_CONTROL 0x0 ++#define DPI_DMA_CONTROL_ARM_SHIFT 0 ++#define DPI_DMA_CONTROL_ARM_MASK BIT(DPI_DMA_CONTROL_ARM_SHIFT) ++#define DPI_DMA_CONTROL_ALIGN16_SHIFT 2 ++#define DPI_DMA_CONTROL_ALIGN16_MASK BIT(DPI_DMA_CONTROL_ALIGN16_SHIFT) ++#define DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT 1 ++#define DPI_DMA_CONTROL_AUTO_REPEAT_MASK BIT(DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT) ++#define DPI_DMA_CONTROL_HIGH_WATER_SHIFT 3 ++#define DPI_DMA_CONTROL_HIGH_WATER_MASK (0x1FF << DPI_DMA_CONTROL_HIGH_WATER_SHIFT) ++#define DPI_DMA_CONTROL_DEN_POL_SHIFT 12 ++#define DPI_DMA_CONTROL_DEN_POL_MASK BIT(DPI_DMA_CONTROL_DEN_POL_SHIFT) ++#define DPI_DMA_CONTROL_HSYNC_POL_SHIFT 13 ++#define DPI_DMA_CONTROL_HSYNC_POL_MASK BIT(DPI_DMA_CONTROL_HSYNC_POL_SHIFT) ++#define DPI_DMA_CONTROL_VSYNC_POL_SHIFT 14 ++#define DPI_DMA_CONTROL_VSYNC_POL_MASK BIT(DPI_DMA_CONTROL_VSYNC_POL_SHIFT) ++#define DPI_DMA_CONTROL_COLORM_SHIFT 15 ++#define DPI_DMA_CONTROL_COLORM_MASK BIT(DPI_DMA_CONTROL_COLORM_SHIFT) ++#define DPI_DMA_CONTROL_SHUTDN_SHIFT 16 ++#define DPI_DMA_CONTROL_SHUTDN_MASK BIT(DPI_DMA_CONTROL_SHUTDN_SHIFT) ++#define DPI_DMA_CONTROL_HBP_EN_SHIFT 17 ++#define DPI_DMA_CONTROL_HBP_EN_MASK BIT(DPI_DMA_CONTROL_HBP_EN_SHIFT) ++#define DPI_DMA_CONTROL_HFP_EN_SHIFT 18 ++#define DPI_DMA_CONTROL_HFP_EN_MASK BIT(DPI_DMA_CONTROL_HFP_EN_SHIFT) ++#define DPI_DMA_CONTROL_VBP_EN_SHIFT 19 ++#define DPI_DMA_CONTROL_VBP_EN_MASK BIT(DPI_DMA_CONTROL_VBP_EN_SHIFT) ++#define DPI_DMA_CONTROL_VFP_EN_SHIFT 20 ++#define DPI_DMA_CONTROL_VFP_EN_MASK BIT(DPI_DMA_CONTROL_VFP_EN_SHIFT) ++#define DPI_DMA_CONTROL_HSYNC_EN_SHIFT 21 ++#define DPI_DMA_CONTROL_HSYNC_EN_MASK BIT(DPI_DMA_CONTROL_HSYNC_EN_SHIFT) ++#define DPI_DMA_CONTROL_VSYNC_EN_SHIFT 22 ++#define DPI_DMA_CONTROL_VSYNC_EN_MASK BIT(DPI_DMA_CONTROL_VSYNC_EN_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_IMMED_SHIFT 23 ++#define DPI_DMA_CONTROL_FORCE_IMMED_MASK BIT(DPI_DMA_CONTROL_FORCE_IMMED_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT 24 ++#define DPI_DMA_CONTROL_FORCE_DRAIN_MASK BIT(DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT 25 ++#define DPI_DMA_CONTROL_FORCE_EMPTY_MASK BIT(DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT) ++ ++// IRQ_ENABLES ++#define DPI_DMA_IRQ_EN 0x04 ++#define DPI_DMA_IRQ_EN_DMA_READY_SHIFT 0 ++#define DPI_DMA_IRQ_EN_DMA_READY_MASK BIT(DPI_DMA_IRQ_EN_DMA_READY_SHIFT) ++#define DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT 1 ++#define DPI_DMA_IRQ_EN_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT) ++#define DPI_DMA_IRQ_EN_FRAME_START_SHIFT 2 ++#define DPI_DMA_IRQ_EN_FRAME_START_MASK BIT(DPI_DMA_IRQ_EN_FRAME_START_SHIFT) ++#define DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT 3 ++#define DPI_DMA_IRQ_EN_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT) ++#define DPI_DMA_IRQ_EN_TE_SHIFT 4 ++#define DPI_DMA_IRQ_EN_TE_MASK BIT(DPI_DMA_IRQ_EN_TE_SHIFT) ++#define DPI_DMA_IRQ_EN_ERROR_SHIFT 5 ++#define DPI_DMA_IRQ_EN_ERROR_MASK BIT(DPI_DMA_IRQ_EN_ERROR_SHIFT) ++#define DPI_DMA_IRQ_EN_MATCH_SHIFT 6 ++#define DPI_DMA_IRQ_EN_MATCH_MASK BIT(DPI_DMA_IRQ_EN_MATCH_SHIFT) ++#define DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT 16 ++#define DPI_DMA_IRQ_EN_MATCH_LINE_MASK (0xFFF << DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT) ++ ++// IRQ_FLAGS ++#define DPI_DMA_IRQ_FLAGS 0x08 ++#define DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT 0 ++#define DPI_DMA_IRQ_FLAGS_DMA_READY_MASK BIT(DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT 1 ++#define DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT 2 ++#define DPI_DMA_IRQ_FLAGS_FRAME_START_MASK BIT(DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT 3 ++#define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_TE_SHIFT 4 ++#define DPI_DMA_IRQ_FLAGS_TE_MASK BIT(DPI_DMA_IRQ_FLAGS_TE_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_ERROR_SHIFT 5 ++#define DPI_DMA_IRQ_FLAGS_ERROR_MASK BIT(DPI_DMA_IRQ_FLAGS_ERROR_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_MATCH_SHIFT 6 ++#define DPI_DMA_IRQ_FLAGS_MATCH_MASK BIT(DPI_DMA_IRQ_FLAGS_MATCH_SHIFT) ++ ++// QOS ++#define DPI_DMA_QOS 0xC ++#define DPI_DMA_QOS_DQOS_SHIFT 0 ++#define DPI_DMA_QOS_DQOS_MASK (0xF << DPI_DMA_QOS_DQOS_SHIFT) ++#define DPI_DMA_QOS_ULEV_SHIFT 4 ++#define DPI_DMA_QOS_ULEV_MASK (0xF << DPI_DMA_QOS_ULEV_SHIFT) ++#define DPI_DMA_QOS_UQOS_SHIFT 8 ++#define DPI_DMA_QOS_UQOS_MASK (0xF << DPI_DMA_QOS_UQOS_SHIFT) ++#define DPI_DMA_QOS_LLEV_SHIFT 12 ++#define DPI_DMA_QOS_LLEV_MASK (0xF << DPI_DMA_QOS_LLEV_SHIFT) ++#define DPI_DMA_QOS_LQOS_SHIFT 16 ++#define DPI_DMA_QOS_LQOS_MASK (0xF << DPI_DMA_QOS_LQOS_SHIFT) ++ ++// Panics ++#define DPI_DMA_PANICS 0x38 ++#define DPI_DMA_PANICS_UPPER_COUNT_SHIFT 0 ++#define DPI_DMA_PANICS_UPPER_COUNT_MASK \ ++ (0x0000FFFF << DPI_DMA_PANICS_UPPER_COUNT_SHIFT) ++#define DPI_DMA_PANICS_LOWER_COUNT_SHIFT 16 ++#define DPI_DMA_PANICS_LOWER_COUNT_MASK \ ++ (0x0000FFFF << DPI_DMA_PANICS_LOWER_COUNT_SHIFT) ++ ++// DMA Address Lower: ++#define DPI_DMA_DMA_ADDR_L 0x10 ++ ++// DMA Address Upper: ++#define DPI_DMA_DMA_ADDR_H 0x40 ++ ++// DMA stride ++#define DPI_DMA_DMA_STRIDE 0x14 ++ ++// Visible Area ++#define DPI_DMA_VISIBLE_AREA 0x18 ++#define DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT 0 ++#define DPI_DMA_VISIBLE_AREA_ROWSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT) ++#define DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT 16 ++#define DPI_DMA_VISIBLE_AREA_COLSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT) ++ ++// Sync width ++#define DPI_DMA_SYNC_WIDTH 0x1C ++#define DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT 0 ++#define DPI_DMA_SYNC_WIDTH_ROWSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT) ++#define DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT 16 ++#define DPI_DMA_SYNC_WIDTH_COLSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT) ++ ++// Back porch ++#define DPI_DMA_BACK_PORCH 0x20 ++#define DPI_DMA_BACK_PORCH_ROWSM1_SHIFT 0 ++#define DPI_DMA_BACK_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_ROWSM1_SHIFT) ++#define DPI_DMA_BACK_PORCH_COLSM1_SHIFT 16 ++#define DPI_DMA_BACK_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_COLSM1_SHIFT) ++ ++// Front porch ++#define DPI_DMA_FRONT_PORCH 0x24 ++#define DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT 0 ++#define DPI_DMA_FRONT_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT) ++#define DPI_DMA_FRONT_PORCH_COLSM1_SHIFT 16 ++#define DPI_DMA_FRONT_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_COLSM1_SHIFT) ++ ++// Input masks ++#define DPI_DMA_IMASK 0x2C ++#define DPI_DMA_IMASK_R_SHIFT 0 ++#define DPI_DMA_IMASK_R_MASK (0x3FF << DPI_DMA_IMASK_R_SHIFT) ++#define DPI_DMA_IMASK_G_SHIFT 10 ++#define DPI_DMA_IMASK_G_MASK (0x3FF << DPI_DMA_IMASK_G_SHIFT) ++#define DPI_DMA_IMASK_B_SHIFT 20 ++#define DPI_DMA_IMASK_B_MASK (0x3FF << DPI_DMA_IMASK_B_SHIFT) ++ ++// Output Masks ++#define DPI_DMA_OMASK 0x30 ++#define DPI_DMA_OMASK_R_SHIFT 0 ++#define DPI_DMA_OMASK_R_MASK (0x3FF << DPI_DMA_OMASK_R_SHIFT) ++#define DPI_DMA_OMASK_G_SHIFT 10 ++#define DPI_DMA_OMASK_G_MASK (0x3FF << DPI_DMA_OMASK_G_SHIFT) ++#define DPI_DMA_OMASK_B_SHIFT 20 ++#define DPI_DMA_OMASK_B_MASK (0x3FF << DPI_DMA_OMASK_B_SHIFT) ++ ++// Shifts ++#define DPI_DMA_SHIFT 0x28 ++#define DPI_DMA_SHIFT_IR_SHIFT 0 ++#define DPI_DMA_SHIFT_IR_MASK (0x1F << DPI_DMA_SHIFT_IR_SHIFT) ++#define DPI_DMA_SHIFT_IG_SHIFT 5 ++#define DPI_DMA_SHIFT_IG_MASK (0x1F << DPI_DMA_SHIFT_IG_SHIFT) ++#define DPI_DMA_SHIFT_IB_SHIFT 10 ++#define DPI_DMA_SHIFT_IB_MASK (0x1F << DPI_DMA_SHIFT_IB_SHIFT) ++#define DPI_DMA_SHIFT_OR_SHIFT 15 ++#define DPI_DMA_SHIFT_OR_MASK (0x1F << DPI_DMA_SHIFT_OR_SHIFT) ++#define DPI_DMA_SHIFT_OG_SHIFT 20 ++#define DPI_DMA_SHIFT_OG_MASK (0x1F << DPI_DMA_SHIFT_OG_SHIFT) ++#define DPI_DMA_SHIFT_OB_SHIFT 25 ++#define DPI_DMA_SHIFT_OB_MASK (0x1F << DPI_DMA_SHIFT_OB_SHIFT) ++ ++// Scaling ++#define DPI_DMA_RGBSZ 0x34 ++#define DPI_DMA_RGBSZ_BPP_SHIFT 16 ++#define DPI_DMA_RGBSZ_BPP_MASK (0x3 << DPI_DMA_RGBSZ_BPP_SHIFT) ++#define DPI_DMA_RGBSZ_R_SHIFT 0 ++#define DPI_DMA_RGBSZ_R_MASK (0xF << DPI_DMA_RGBSZ_R_SHIFT) ++#define DPI_DMA_RGBSZ_G_SHIFT 4 ++#define DPI_DMA_RGBSZ_G_MASK (0xF << DPI_DMA_RGBSZ_G_SHIFT) ++#define DPI_DMA_RGBSZ_B_SHIFT 8 ++#define DPI_DMA_RGBSZ_B_MASK (0xF << DPI_DMA_RGBSZ_B_SHIFT) ++ ++// Status ++#define DPI_DMA_STATUS 0x3c ++ ++#define BITS(field, val) (((val) << (field ## _SHIFT)) & (field ## _MASK)) ++ ++static unsigned int rp1dsi_dma_read(struct rp1_dsi *dsi, unsigned int reg) ++{ ++ void __iomem *addr = dsi->hw_base[RP1DSI_HW_BLOCK_DMA] + reg; ++ ++ return readl(addr); ++} ++ ++static void rp1dsi_dma_write(struct rp1_dsi *dsi, unsigned int reg, unsigned int val) ++{ ++ void __iomem *addr = dsi->hw_base[RP1DSI_HW_BLOCK_DMA] + reg; ++ ++ writel(val, addr); ++} ++ ++int rp1dsi_dma_busy(struct rp1_dsi *dsi) ++{ ++ return (rp1dsi_dma_read(dsi, DPI_DMA_STATUS) & 0xF8F) ? 1 : 0; ++} ++ ++/* Table of supported input (in-memory/DMA) pixel formats. */ ++struct rp1dsi_ipixfmt { ++ u32 format; /* DRM format code */ ++ u32 mask; /* RGB masks (10 bits each, left justified) */ ++ u32 shift; /* RGB MSB positions in the memory word */ ++ u32 rgbsz; /* Shifts used for scaling; also (BPP/8-1) */ ++}; ++ ++#define IMASK_RGB(r, g, b) (BITS(DPI_DMA_IMASK_R, r) | \ ++ BITS(DPI_DMA_IMASK_G, g) | \ ++ BITS(DPI_DMA_IMASK_B, b)) ++#define ISHIFT_RGB(r, g, b) (BITS(DPI_DMA_SHIFT_IR, r) | \ ++ BITS(DPI_DMA_SHIFT_IG, g) | \ ++ BITS(DPI_DMA_SHIFT_IB, b)) ++ ++static const struct rp1dsi_ipixfmt my_formats[] = { ++ { ++ .format = DRM_FORMAT_XRGB8888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3), ++ }, ++ { ++ .format = DRM_FORMAT_XBGR8888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3), ++ }, ++ { ++ .format = DRM_FORMAT_RGB888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2), ++ }, ++ { ++ .format = DRM_FORMAT_BGR888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2), ++ }, ++ { ++ .format = DRM_FORMAT_RGB565, ++ .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0), ++ .shift = ISHIFT_RGB(15, 10, 4), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_R, 5) | BITS(DPI_DMA_RGBSZ_G, 6) | ++ BITS(DPI_DMA_RGBSZ_B, 5) | BITS(DPI_DMA_RGBSZ_BPP, 1), ++ } ++}; ++ ++/* Choose the internal on-the-bus DPI format as expected by DSI Host. */ ++static u32 get_omask_oshift(enum mipi_dsi_pixel_format fmt, u32 *oshift) ++{ ++ switch (fmt) { ++ case MIPI_DSI_FMT_RGB565: ++ *oshift = BITS(DPI_DMA_SHIFT_OR, 15) | ++ BITS(DPI_DMA_SHIFT_OG, 10) | ++ BITS(DPI_DMA_SHIFT_OB, 4); ++ return BITS(DPI_DMA_OMASK_R, 0x3e0) | ++ BITS(DPI_DMA_OMASK_G, 0x3f0) | ++ BITS(DPI_DMA_OMASK_B, 0x3e0); ++ case MIPI_DSI_FMT_RGB666_PACKED: ++ *oshift = BITS(DPI_DMA_SHIFT_OR, 17) | ++ BITS(DPI_DMA_SHIFT_OG, 11) | ++ BITS(DPI_DMA_SHIFT_OB, 5); ++ return BITS(DPI_DMA_OMASK_R, 0x3f0) | ++ BITS(DPI_DMA_OMASK_G, 0x3f0) | ++ BITS(DPI_DMA_OMASK_B, 0x3f0); ++ case MIPI_DSI_FMT_RGB666: ++ *oshift = BITS(DPI_DMA_SHIFT_OR, 21) | ++ BITS(DPI_DMA_SHIFT_OG, 13) | ++ BITS(DPI_DMA_SHIFT_OB, 5); ++ return BITS(DPI_DMA_OMASK_R, 0x3f0) | ++ BITS(DPI_DMA_OMASK_G, 0x3f0) | ++ BITS(DPI_DMA_OMASK_B, 0x3f0); ++ default: ++ *oshift = BITS(DPI_DMA_SHIFT_OR, 23) | ++ BITS(DPI_DMA_SHIFT_OG, 15) | ++ BITS(DPI_DMA_SHIFT_OB, 7); ++ return BITS(DPI_DMA_OMASK_R, 0x3fc) | ++ BITS(DPI_DMA_OMASK_G, 0x3fc) | ++ BITS(DPI_DMA_OMASK_B, 0x3fc); ++ } ++} ++ ++void rp1dsi_dma_setup(struct rp1_dsi *dsi, ++ u32 in_format, enum mipi_dsi_pixel_format out_format, ++ struct drm_display_mode const *mode) ++{ ++ u32 oshift; ++ int i; ++ ++ /* ++ * Configure all DSI/DPI/DMA block registers, except base address. ++ * DMA will not actually start until a FB base address is specified ++ * using rp1dsi_dma_update(). ++ */ ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_VISIBLE_AREA, ++ BITS(DPI_DMA_VISIBLE_AREA_ROWSM1, mode->vdisplay - 1) | ++ BITS(DPI_DMA_VISIBLE_AREA_COLSM1, mode->hdisplay - 1)); ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_SYNC_WIDTH, ++ BITS(DPI_DMA_SYNC_WIDTH_ROWSM1, mode->vsync_end - mode->vsync_start - 1) | ++ BITS(DPI_DMA_SYNC_WIDTH_COLSM1, mode->hsync_end - mode->hsync_start - 1)); ++ ++ /* In the DPIDMA registers, "back porch" time includes sync width */ ++ rp1dsi_dma_write(dsi, DPI_DMA_BACK_PORCH, ++ BITS(DPI_DMA_BACK_PORCH_ROWSM1, mode->vtotal - mode->vsync_start - 1) | ++ BITS(DPI_DMA_BACK_PORCH_COLSM1, mode->htotal - mode->hsync_start - 1)); ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_FRONT_PORCH, ++ BITS(DPI_DMA_FRONT_PORCH_ROWSM1, mode->vsync_start - mode->vdisplay - 1) | ++ BITS(DPI_DMA_FRONT_PORCH_COLSM1, mode->hsync_start - mode->hdisplay - 1)); ++ ++ /* Input to output pixel format conversion */ ++ for (i = 0; i < ARRAY_SIZE(my_formats); ++i) { ++ if (my_formats[i].format == in_format) ++ break; ++ } ++ if (i >= ARRAY_SIZE(my_formats)) { ++ drm_err(dsi->drm, "%s: bad input format\n", __func__); ++ i = 0; ++ } ++ rp1dsi_dma_write(dsi, DPI_DMA_IMASK, my_formats[i].mask); ++ rp1dsi_dma_write(dsi, DPI_DMA_OMASK, get_omask_oshift(out_format, &oshift)); ++ rp1dsi_dma_write(dsi, DPI_DMA_SHIFT, my_formats[i].shift | oshift); ++ if (out_format == MIPI_DSI_FMT_RGB888) ++ rp1dsi_dma_write(dsi, DPI_DMA_RGBSZ, my_formats[i].rgbsz); ++ else ++ rp1dsi_dma_write(dsi, DPI_DMA_RGBSZ, my_formats[i].rgbsz & DPI_DMA_RGBSZ_BPP_MASK); ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_QOS, ++ BITS(DPI_DMA_QOS_DQOS, 0x0) | ++ BITS(DPI_DMA_QOS_ULEV, 0xb) | ++ BITS(DPI_DMA_QOS_UQOS, 0x2) | ++ BITS(DPI_DMA_QOS_LLEV, 0x8) | ++ BITS(DPI_DMA_QOS_LQOS, 0x7)); ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_IRQ_FLAGS, -1); ++ rp1dsi_dma_vblank_ctrl(dsi, 1); ++ ++ i = rp1dsi_dma_busy(dsi); ++ if (i) ++ drm_err(dsi->drm, "RP1DSI: Unexpectedly busy at start!"); ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_CONTROL, ++ BITS(DPI_DMA_CONTROL_ARM, (i == 0)) | ++ BITS(DPI_DMA_CONTROL_AUTO_REPEAT, 1) | ++ BITS(DPI_DMA_CONTROL_HIGH_WATER, 448) | ++ BITS(DPI_DMA_CONTROL_DEN_POL, 0) | ++ BITS(DPI_DMA_CONTROL_HSYNC_POL, 0) | ++ BITS(DPI_DMA_CONTROL_VSYNC_POL, 0) | ++ BITS(DPI_DMA_CONTROL_COLORM, 0) | ++ BITS(DPI_DMA_CONTROL_SHUTDN, 0) | ++ BITS(DPI_DMA_CONTROL_HBP_EN, 1) | ++ BITS(DPI_DMA_CONTROL_HFP_EN, 1) | ++ BITS(DPI_DMA_CONTROL_VBP_EN, 1) | ++ BITS(DPI_DMA_CONTROL_VFP_EN, 1) | ++ BITS(DPI_DMA_CONTROL_HSYNC_EN, 1) | ++ BITS(DPI_DMA_CONTROL_VSYNC_EN, 1)); ++} ++ ++void rp1dsi_dma_update(struct rp1_dsi *dsi, dma_addr_t addr, u32 offset, u32 stride) ++{ ++ /* ++ * Update STRIDE, DMAH and DMAL only. When called after rp1dsi_dma_setup(), ++ * DMA starts immediately; if already running, the buffer will flip at ++ * the next vertical sync event. ++ */ ++ u64 a = addr + offset; ++ ++ rp1dsi_dma_write(dsi, DPI_DMA_DMA_STRIDE, stride); ++ rp1dsi_dma_write(dsi, DPI_DMA_DMA_ADDR_H, a >> 32); ++ rp1dsi_dma_write(dsi, DPI_DMA_DMA_ADDR_L, a & 0xFFFFFFFFu); ++} ++ ++void rp1dsi_dma_stop(struct rp1_dsi *dsi) ++{ ++ /* ++ * Stop DMA by turning off the Auto-Repeat flag, and wait up to 100ms for ++ * the current and any queued frame to end. "Force drain" flags are not used, ++ * as they seem to prevent DMA from re-starting properly; it's safer to wait. ++ */ ++ u32 ctrl; ++ ++ reinit_completion(&dsi->finished); ++ ctrl = rp1dsi_dma_read(dsi, DPI_DMA_CONTROL); ++ ctrl &= ~(DPI_DMA_CONTROL_ARM_MASK | DPI_DMA_CONTROL_AUTO_REPEAT_MASK); ++ rp1dsi_dma_write(dsi, DPI_DMA_CONTROL, ctrl); ++ if (!wait_for_completion_timeout(&dsi->finished, HZ / 10)) ++ drm_err(dsi->drm, "%s: timed out waiting for idle\n", __func__); ++ rp1dsi_dma_write(dsi, DPI_DMA_IRQ_EN, 0); ++} ++ ++void rp1dsi_dma_vblank_ctrl(struct rp1_dsi *dsi, int enable) ++{ ++ rp1dsi_dma_write(dsi, DPI_DMA_IRQ_EN, ++ BITS(DPI_DMA_IRQ_EN_AFIFO_EMPTY, 1) | ++ BITS(DPI_DMA_IRQ_EN_UNDERFLOW, 1) | ++ BITS(DPI_DMA_IRQ_EN_DMA_READY, !!enable) | ++ BITS(DPI_DMA_IRQ_EN_MATCH_LINE, 4095)); ++} ++ ++irqreturn_t rp1dsi_dma_isr(int irq, void *dev) ++{ ++ struct rp1_dsi *dsi = dev; ++ u32 u = rp1dsi_dma_read(dsi, DPI_DMA_IRQ_FLAGS); ++ ++ if (u) { ++ rp1dsi_dma_write(dsi, DPI_DMA_IRQ_FLAGS, u); ++ if (dsi) { ++ if (u & DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK) ++ drm_err_ratelimited(dsi->drm, ++ "Underflow! (panics=0x%08x)\n", ++ rp1dsi_dma_read(dsi, DPI_DMA_PANICS)); ++ if (u & DPI_DMA_IRQ_FLAGS_DMA_READY_MASK) ++ drm_crtc_handle_vblank(&dsi->pipe.crtc); ++ if (u & DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK) ++ complete(&dsi->finished); ++ } ++ } ++ return u ? IRQ_HANDLED : IRQ_NONE; ++} +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c +@@ -0,0 +1,1504 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include "drm/drm_print.h" ++ ++#include "rp1_dsi.h" ++ ++/* ------------------------------- Synopsis DSI ------------------------ */ ++#define DSI_VERSION_CFG 0x000 ++#define DSI_PWR_UP 0x004 ++#define DSI_CLKMGR_CFG 0x008 ++#define DSI_DPI_VCID 0x00C ++#define DSI_DPI_COLOR_CODING 0x010 ++#define DSI_DPI_CFG_POL 0x014 ++#define DSI_DPI_LP_CMD_TIM 0x018 ++#define DSI_DBI_VCID 0x01C ++#define DSI_DBI_CFG 0x020 ++#define DSI_DBI_PARTITIONING_EN 0x024 ++#define DSI_DBI_CMDSIZE 0x028 ++#define DSI_PCKHDL_CFG 0x02C ++#define DSI_GEN_VCID 0x030 ++#define DSI_MODE_CFG 0x034 ++#define DSI_VID_MODE_CFG 0x038 ++#define DSI_VID_PKT_SIZE 0x03C ++#define DSI_VID_NUM_CHUNKS 0x040 ++#define DSI_VID_NULL_SIZE 0x044 ++#define DSI_VID_HSA_TIME 0x048 ++#define DSI_VID_HBP_TIME 0x04C ++#define DSI_VID_HLINE_TIME 0x050 ++#define DSI_VID_VSA_LINES 0x054 ++#define DSI_VID_VBP_LINES 0x058 ++#define DSI_VID_VFP_LINES 0x05C ++#define DSI_VID_VACTIVE_LINES 0x060 ++#define DSI_EDPI_CMD_SIZE 0x064 ++#define DSI_CMD_MODE_CFG 0x068 ++#define DSI_GEN_HDR 0x06C ++#define DSI_GEN_PLD_DATA 0x070 ++#define DSI_CMD_PKT_STATUS 0x074 ++#define DSI_TO_CNT_CFG 0x078 ++#define DSI_HS_RD_TO_CNT 0x07C ++#define DSI_LP_RD_TO_CNT 0x080 ++#define DSI_HS_WR_TO_CNT 0x084 ++#define DSI_LP_WR_TO_CNT 0x088 ++#define DSI_BTA_TO_CNT 0x08C ++#define DSI_SDF_3D 0x090 ++#define DSI_LPCLK_CTRL 0x094 ++#define DSI_PHY_TMR_LPCLK_CFG 0x098 ++#define DSI_PHY_TMR_HS2LP_LSB 16 ++#define DSI_PHY_TMR_LP2HS_LSB 0 ++#define DSI_PHY_TMR_CFG 0x09C ++#define DSI_PHY_TMR_RD_CFG 0x0F4 ++#define DSI_PHYRSTZ 0x0A0 ++#define DSI_PHY_IF_CFG 0x0A4 ++#define DSI_PHY_ULPS_CTRL 0x0A8 ++#define DSI_PHY_TX_TRIGGERS 0x0AC ++#define DSI_PHY_STATUS 0x0B0 ++ ++#define DSI_PHY_TST_CTRL0 0x0B4 ++#define DSI_PHY_TST_CTRL1 0x0B8 ++#define DSI_INT_ST0 0x0BC ++#define DSI_INT_ST1 0x0C0 ++#define DSI_INT_MASK0_CFG 0x0C4 ++#define DSI_INT_MASK1_CFG 0x0C8 ++#define DSI_PHY_CAL 0x0CC ++#define DSI_HEXP_NPKT_CLR 0x104 ++#define DSI_HEXP_NPKT_SIZE 0x108 ++#define DSI_VID_SHADOW_CTRL 0x100 ++ ++#define DSI_DPI_VCID_ACT 0x10C ++#define DSI_DPI_COLOR_CODING_ACT 0x110 ++#define DSI_DPI_LP_CMD_TIM_ACT 0x118 ++#define DSI_VID_MODE_CFG_ACT 0x138 ++#define DSI_VID_PKT_SIZE_ACT 0x13C ++#define DSI_VID_NUM_CHUNKS_ACT 0x140 ++#define DSI_VID_NULL_SIZE_ACT 0x144 ++#define DSI_VID_HSA_TIME_ACT 0x148 ++#define DSI_VID_HBP_TIME_ACT 0x14C ++#define DSI_VID_HLINE_TIME_ACT 0x150 ++#define DSI_VID_VSA_LINES_ACT 0x154 ++#define DSI_VID_VBP_LINES_ACT 0x158 ++#define DSI_VID_VFP_LINES_ACT 0x15C ++#define DSI_VID_VACTIVE_LINES_ACT 0x160 ++#define DSI_SDF_3D_CFG_ACT 0x190 ++ ++#define DSI_INT_FORCE0 0x0D8 ++#define DSI_INT_FORCE1 0x0DC ++ ++#define DSI_AUTO_ULPS_MODE 0x0E0 ++#define DSI_AUTO_ULPS_ENTRY_DELAY 0x0E4 ++#define DSI_AUTO_ULPS_WAKEUP_TIME 0x0E8 ++#define DSI_EDPI_ADV_FEATURES 0x0EC ++ ++#define DSI_DSC_PARAMETER 0x0F0 ++ ++/* And some bitfield definitions */ ++ ++#define DPHY_PWR_UP_SHUTDOWNZ_LSB 0 ++#define DPHY_PWR_UP_SHUTDOWNZ_BITS BIT(DPHY_PWR_UP_SHUTDOWNZ_LSB) ++ ++#define DPHY_CTRL0_PHY_TESTCLK_LSB 1 ++#define DPHY_CTRL0_PHY_TESTCLK_BITS BIT(DPHY_CTRL0_PHY_TESTCLK_LSB) ++#define DPHY_CTRL0_PHY_TESTCLR_LSB 0 ++#define DPHY_CTRL0_PHY_TESTCLR_BITS BIT(DPHY_CTRL0_PHY_TESTCLR_LSB) ++ ++#define DPHY_CTRL1_PHY_TESTDIN_LSB 0 ++#define DPHY_CTRL1_PHY_TESTDIN_BITS (0xff << DPHY_CTRL1_PHY_TESTDIN_LSB) ++#define DPHY_CTRL1_PHY_TESTDOUT_LSB 8 ++#define DPHY_CTRL1_PHY_TESTDOUT_BITS (0xff << DPHY_CTRL1_PHY_TESTDOUT_LSB) ++#define DPHY_CTRL1_PHY_TESTEN_LSB 16 ++#define DPHY_CTRL1_PHY_TESTEN_BITS BIT(DPHY_CTRL1_PHY_TESTEN_LSB) ++ ++#define DSI_PHYRSTZ_SHUTDOWNZ_LSB 0 ++#define DSI_PHYRSTZ_SHUTDOWNZ_BITS BIT(DSI_PHYRSTZ_SHUTDOWNZ_LSB) ++#define DSI_PHYRSTZ_RSTZ_LSB 1 ++#define DSI_PHYRSTZ_RSTZ_BITS BIT(DSI_PHYRSTZ_RSTZ_LSB) ++#define DSI_PHYRSTZ_ENABLECLK_LSB 2 ++#define DSI_PHYRSTZ_ENABLECLK_BITS BIT(DSI_PHYRSTZ_ENABLECLK_LSB) ++#define DSI_PHYRSTZ_FORCEPLL_LSB 3 ++#define DSI_PHYRSTZ_FORCEPLL_BITS BIT(DSI_PHYRSTZ_FORCEPLL_LSB) ++ ++#define DPHY_HS_RX_CTRL_LANE0_OFFSET 0x44 ++#define DPHY_PLL_INPUT_DIV_OFFSET 0x17 ++#define DPHY_PLL_LOOP_DIV_OFFSET 0x18 ++#define DPHY_PLL_DIV_CTRL_OFFSET 0x19 ++ ++#define DPHY_PLL_BIAS_OFFSET 0x10 ++#define DPHY_PLL_BIAS_VCO_RANGE_LSB 3 ++#define DPHY_PLL_BIAS_USE_PROGRAMMED_VCO_RANGE BIT(7) ++ ++#define DPHY_PLL_CHARGE_PUMP_OFFSET 0x11 ++#define DPHY_PLL_LPF_OFFSET 0x12 ++ ++#define DSI_WRITE(reg, val) writel((val), dsi->hw_base[RP1DSI_HW_BLOCK_DSI] + (reg)) ++#define DSI_READ(reg) readl(dsi->hw_base[RP1DSI_HW_BLOCK_DSI] + (reg)) ++ ++// ================================================================================ ++// Register block : RPI_MIPICFG ++// Version : 1 ++// Bus type : apb ++// Description : Register block to control mipi DPHY ++// ================================================================================ ++#define RPI_MIPICFG_REGS_RWTYPE_MSB 13 ++#define RPI_MIPICFG_REGS_RWTYPE_LSB 12 ++// ================================================================================ ++// Register : RPI_MIPICFG_CLK2FC ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_CLK2FC_OFFSET 0x00000000 ++#define RPI_MIPICFG_CLK2FC_BITS 0x00000007 ++#define RPI_MIPICFG_CLK2FC_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_CLK2FC_SEL ++// Description : select a clock to be sent to the frequency counter ++// 7 = none ++// 6 = none ++// 5 = none ++// 4 = rxbyteclkhs (187.5MHz) ++// 3 = rxclkesc0 (20MHz) ++// 2 = txbyteclkhs (187.5MHz) ++// 1 = txclkesc (125MHz) ++// 0 = none ++#define RPI_MIPICFG_CLK2FC_SEL_RESET 0x0 ++#define RPI_MIPICFG_CLK2FC_SEL_BITS 0x00000007 ++#define RPI_MIPICFG_CLK2FC_SEL_MSB 2 ++#define RPI_MIPICFG_CLK2FC_SEL_LSB 0 ++#define RPI_MIPICFG_CLK2FC_SEL_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_CFG ++// JTAG access : asynchronous ++// Description : Top level configuration ++#define RPI_MIPICFG_CFG_OFFSET 0x00000004 ++#define RPI_MIPICFG_CFG_BITS 0x00000111 ++#define RPI_MIPICFG_CFG_RESET 0x00000001 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_CFG_DPIUPDATE ++// Description : Indicate the DSI block that the next frame will have a new video configuration ++#define RPI_MIPICFG_CFG_DPIUPDATE_RESET 0x0 ++#define RPI_MIPICFG_CFG_DPIUPDATE_BITS 0x00000100 ++#define RPI_MIPICFG_CFG_DPIUPDATE_MSB 8 ++#define RPI_MIPICFG_CFG_DPIUPDATE_LSB 8 ++#define RPI_MIPICFG_CFG_DPIUPDATE_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_CFG_SEL_TE_EXT ++// Description : Select the TE source: 1 - ext, 0 - int ++#define RPI_MIPICFG_CFG_SEL_TE_EXT_RESET 0x0 ++#define RPI_MIPICFG_CFG_SEL_TE_EXT_BITS 0x00000010 ++#define RPI_MIPICFG_CFG_SEL_TE_EXT_MSB 4 ++#define RPI_MIPICFG_CFG_SEL_TE_EXT_LSB 4 ++#define RPI_MIPICFG_CFG_SEL_TE_EXT_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_CFG_SEL_CSI_DSI_N ++// Description : Select PHY direction: input to CSI, output from DSI. CSI 1 DSI 0 ++#define RPI_MIPICFG_CFG_SEL_CSI_DSI_N_RESET 0x1 ++#define RPI_MIPICFG_CFG_SEL_CSI_DSI_N_BITS 0x00000001 ++#define RPI_MIPICFG_CFG_SEL_CSI_DSI_N_MSB 0 ++#define RPI_MIPICFG_CFG_SEL_CSI_DSI_N_LSB 0 ++#define RPI_MIPICFG_CFG_SEL_CSI_DSI_N_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_TE ++// JTAG access : synchronous ++// Description : Tearing effect processing ++#define RPI_MIPICFG_TE_OFFSET 0x00000008 ++#define RPI_MIPICFG_TE_BITS 0x10ffffff ++#define RPI_MIPICFG_TE_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_TE_ARM ++// Description : Tearing effect arm ++#define RPI_MIPICFG_TE_ARM_RESET 0x0 ++#define RPI_MIPICFG_TE_ARM_BITS 0x10000000 ++#define RPI_MIPICFG_TE_ARM_MSB 28 ++#define RPI_MIPICFG_TE_ARM_LSB 28 ++#define RPI_MIPICFG_TE_ARM_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_TE_HALT_CYC ++// Description : When arm pulse has been seen, wait for te; then halt the dpi block ++// for this many clk_dpi cycles ++#define RPI_MIPICFG_TE_HALT_CYC_RESET 0x000000 ++#define RPI_MIPICFG_TE_HALT_CYC_BITS 0x00ffffff ++#define RPI_MIPICFG_TE_HALT_CYC_MSB 23 ++#define RPI_MIPICFG_TE_HALT_CYC_LSB 0 ++#define RPI_MIPICFG_TE_HALT_CYC_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_MONITOR ++// JTAG access : asynchronous ++// Description : DPHY status monitors for analog DFT ++#define RPI_MIPICFG_DPHY_MONITOR_OFFSET 0x00000010 ++#define RPI_MIPICFG_DPHY_MONITOR_BITS 0x00111fff ++#define RPI_MIPICFG_DPHY_MONITOR_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_MONITOR_LOCK ++// Description : None ++#define RPI_MIPICFG_DPHY_MONITOR_LOCK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_MONITOR_LOCK_BITS 0x00100000 ++#define RPI_MIPICFG_DPHY_MONITOR_LOCK_MSB 20 ++#define RPI_MIPICFG_DPHY_MONITOR_LOCK_LSB 20 ++#define RPI_MIPICFG_DPHY_MONITOR_LOCK_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_MONITOR_BISTOK ++// Description : None ++#define RPI_MIPICFG_DPHY_MONITOR_BISTOK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_MONITOR_BISTOK_BITS 0x00010000 ++#define RPI_MIPICFG_DPHY_MONITOR_BISTOK_MSB 16 ++#define RPI_MIPICFG_DPHY_MONITOR_BISTOK_LSB 16 ++#define RPI_MIPICFG_DPHY_MONITOR_BISTOK_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK ++// Description : None ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK_BITS 0x00001000 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK_MSB 12 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK_LSB 12 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATECLK_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA ++// Description : None ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA_RESET 0x0 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA_BITS 0x00000f00 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA_MSB 11 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA_LSB 8 ++#define RPI_MIPICFG_DPHY_MONITOR_STOPSTATEDATA_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_MONITOR_TESTDOUT ++// Description : None ++#define RPI_MIPICFG_DPHY_MONITOR_TESTDOUT_RESET 0x00 ++#define RPI_MIPICFG_DPHY_MONITOR_TESTDOUT_BITS 0x000000ff ++#define RPI_MIPICFG_DPHY_MONITOR_TESTDOUT_MSB 7 ++#define RPI_MIPICFG_DPHY_MONITOR_TESTDOUT_LSB 0 ++#define RPI_MIPICFG_DPHY_MONITOR_TESTDOUT_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_CTRL_0 ++// JTAG access : asynchronous ++// Description : DPHY control for analog DFT ++#define RPI_MIPICFG_DPHY_CTRL_0_OFFSET 0x00000014 ++#define RPI_MIPICFG_DPHY_CTRL_0_BITS 0x0000003f ++#define RPI_MIPICFG_DPHY_CTRL_0_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE ++// Description : When set in lpmode, TXCLKESC is driven from clk_vec(driven from clocks block) ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE_BITS 0x00000020 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE_MSB 5 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE_LSB 5 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_LPMODE_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA ++// Description : When set, drive the DPHY from the test registers ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA_BITS 0x00000010 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA_MSB 4 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA_LSB 4 ++#define RPI_MIPICFG_DPHY_CTRL_0_TEST_ENA_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS ++// Description : When test_ena is set, disable cfg_clk ++#define RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS_BITS 0x00000008 ++#define RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS_MSB 3 ++#define RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS_LSB 3 ++#define RPI_MIPICFG_DPHY_CTRL_0_CFG_CLK_DIS_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS ++// Description : When test_ena is set, disable refclk ++#define RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS_BITS 0x00000004 ++#define RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS_MSB 2 ++#define RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS_LSB 2 ++#define RPI_MIPICFG_DPHY_CTRL_0_REFCLK_DIS_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS ++// Description : When test_ena is set, disable txclkesc ++#define RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS_BITS 0x00000002 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS_MSB 1 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS_LSB 1 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXCLKESC_DIS_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS ++// Description : When test_ena is set, disable txbyteclkhs ++#define RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS_BITS 0x00000001 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS_MSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS_LSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_0_TXBYTECLKHS_DIS_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_CTRL_1 ++// JTAG access : asynchronous ++// Description : DPHY control for analog DFT ++#define RPI_MIPICFG_DPHY_CTRL_1_OFFSET 0x00000018 ++#define RPI_MIPICFG_DPHY_CTRL_1_BITS 0x7fffffff ++#define RPI_MIPICFG_DPHY_CTRL_1_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL_BITS 0x40000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL_MSB 30 ++#define RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL_LSB 30 ++#define RPI_MIPICFG_DPHY_CTRL_1_FORCEPLL_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ_BITS 0x20000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ_MSB 29 ++#define RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ_LSB 29 ++#define RPI_MIPICFG_DPHY_CTRL_1_SHUTDOWNZ_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_RSTZ ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_RSTZ_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_RSTZ_BITS 0x10000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_RSTZ_MSB 28 ++#define RPI_MIPICFG_DPHY_CTRL_1_RSTZ_LSB 28 ++#define RPI_MIPICFG_DPHY_CTRL_1_RSTZ_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ_BITS 0x08000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ_MSB 27 ++#define RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ_LSB 27 ++#define RPI_MIPICFG_DPHY_CTRL_1_MASTERSLAVEZ_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_BISTON ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_BISTON_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_BISTON_BITS 0x04000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_BISTON_MSB 26 ++#define RPI_MIPICFG_DPHY_CTRL_1_BISTON_LSB 26 ++#define RPI_MIPICFG_DPHY_CTRL_1_BISTON_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK_BITS 0x02000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK_MSB 25 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK_LSB 25 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTHSCLK_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK_BITS 0x01000000 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK_MSB 24 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK_LSB 24 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLECLK_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3_BITS 0x00800000 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3_MSB 23 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3_LSB 23 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2_BITS 0x00400000 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2_MSB 22 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2_LSB 22 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1_BITS 0x00200000 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1_MSB 21 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1_LSB 21 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0_BITS 0x00100000 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0_MSB 20 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0_LSB 20 ++#define RPI_MIPICFG_DPHY_CTRL_1_ENABLE_0_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3_BITS 0x00080000 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3_MSB 19 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3_LSB 19 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2_BITS 0x00040000 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2_MSB 18 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2_LSB 18 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1_BITS 0x00020000 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1_MSB 17 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1_LSB 17 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0_BITS 0x00010000 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0_MSB 16 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0_LSB 16 ++#define RPI_MIPICFG_DPHY_CTRL_1_BASEDIR_0_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3_BITS 0x00008000 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3_MSB 15 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3_LSB 15 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2_BITS 0x00004000 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2_MSB 14 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2_LSB 14 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1_BITS 0x00002000 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1_MSB 13 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1_LSB 13 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0_BITS 0x00001000 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0_MSB 12 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0_LSB 12 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXLPDTESC_0_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3_BITS 0x00000800 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3_MSB 11 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3_LSB 11 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2_BITS 0x00000400 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2_MSB 10 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2_LSB 10 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1_BITS 0x00000200 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1_MSB 9 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1_LSB 9 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0_BITS 0x00000100 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0_MSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0_LSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXVALIDESC_0_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3_BITS 0x00000080 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3_MSB 7 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3_LSB 7 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2_BITS 0x00000040 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2_MSB 6 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2_LSB 6 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1_BITS 0x00000020 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1_MSB 5 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1_LSB 5 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0_BITS 0x00000010 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0_MSB 4 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0_LSB 4 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTESC_0_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3_BITS 0x00000008 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3_MSB 3 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3_LSB 3 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2_BITS 0x00000004 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2_MSB 2 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2_LSB 2 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1_BITS 0x00000002 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1_MSB 1 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1_LSB 1 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0_BITS 0x00000001 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0_MSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0_LSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_1_TXREQUESTDATAHS_0_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_CTRL_2 ++// JTAG access : asynchronous ++// Description : DPHY control for analog DFT ++#define RPI_MIPICFG_DPHY_CTRL_2_OFFSET 0x0000001c ++#define RPI_MIPICFG_DPHY_CTRL_2_BITS 0x000007ff ++#define RPI_MIPICFG_DPHY_CTRL_2_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_2_TESTCLK ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLK_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLK_BITS 0x00000400 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLK_MSB 10 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLK_LSB 10 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLK_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_2_TESTEN ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTEN_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTEN_BITS 0x00000200 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTEN_MSB 9 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTEN_LSB 9 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTEN_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_2_TESTCLR ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLR_RESET 0x0 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLR_BITS 0x00000100 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLR_MSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLR_LSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTCLR_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_2_TESTDIN ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTDIN_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTDIN_BITS 0x000000ff ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTDIN_MSB 7 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTDIN_LSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_2_TESTDIN_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_CTRL_3 ++// JTAG access : asynchronous ++// Description : DPHY control for analog DFT ++#define RPI_MIPICFG_DPHY_CTRL_3_OFFSET 0x00000020 ++#define RPI_MIPICFG_DPHY_CTRL_3_BITS 0xffffffff ++#define RPI_MIPICFG_DPHY_CTRL_3_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3_BITS 0xff000000 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3_MSB 31 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3_LSB 24 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2_BITS 0x00ff0000 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2_MSB 23 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2_LSB 16 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1_BITS 0x0000ff00 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1_MSB 15 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1_LSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0_BITS 0x000000ff ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0_MSB 7 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0_LSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_3_TXDATAESC_0_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_DPHY_CTRL_4 ++// JTAG access : asynchronous ++// Description : DPHY control for analog DFT ++#define RPI_MIPICFG_DPHY_CTRL_4_OFFSET 0x00000024 ++#define RPI_MIPICFG_DPHY_CTRL_4_BITS 0xffffffff ++#define RPI_MIPICFG_DPHY_CTRL_4_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3_BITS 0xff000000 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3_MSB 31 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3_LSB 24 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_3_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2_BITS 0x00ff0000 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2_MSB 23 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2_LSB 16 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_2_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1_BITS 0x0000ff00 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1_MSB 15 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1_LSB 8 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_1_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0 ++// Description : None ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0_RESET 0x00 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0_BITS 0x000000ff ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0_MSB 7 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0_LSB 0 ++#define RPI_MIPICFG_DPHY_CTRL_4_TXDATAHS_0_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_INTR ++// JTAG access : synchronous ++// Description : Raw Interrupts ++#define RPI_MIPICFG_INTR_OFFSET 0x00000028 ++#define RPI_MIPICFG_INTR_BITS 0x0000000f ++#define RPI_MIPICFG_INTR_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTR_DSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTR_DSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTR_DSI_HOST_BITS 0x00000008 ++#define RPI_MIPICFG_INTR_DSI_HOST_MSB 3 ++#define RPI_MIPICFG_INTR_DSI_HOST_LSB 3 ++#define RPI_MIPICFG_INTR_DSI_HOST_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTR_CSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTR_CSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTR_CSI_HOST_BITS 0x00000004 ++#define RPI_MIPICFG_INTR_CSI_HOST_MSB 2 ++#define RPI_MIPICFG_INTR_CSI_HOST_LSB 2 ++#define RPI_MIPICFG_INTR_CSI_HOST_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTR_DSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTR_DSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTR_DSI_DMA_BITS 0x00000002 ++#define RPI_MIPICFG_INTR_DSI_DMA_MSB 1 ++#define RPI_MIPICFG_INTR_DSI_DMA_LSB 1 ++#define RPI_MIPICFG_INTR_DSI_DMA_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTR_CSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTR_CSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTR_CSI_DMA_BITS 0x00000001 ++#define RPI_MIPICFG_INTR_CSI_DMA_MSB 0 ++#define RPI_MIPICFG_INTR_CSI_DMA_LSB 0 ++#define RPI_MIPICFG_INTR_CSI_DMA_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_INTE ++// JTAG access : synchronous ++// Description : Interrupt Enable ++#define RPI_MIPICFG_INTE_OFFSET 0x0000002c ++#define RPI_MIPICFG_INTE_BITS 0x0000000f ++#define RPI_MIPICFG_INTE_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTE_DSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTE_DSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTE_DSI_HOST_BITS 0x00000008 ++#define RPI_MIPICFG_INTE_DSI_HOST_MSB 3 ++#define RPI_MIPICFG_INTE_DSI_HOST_LSB 3 ++#define RPI_MIPICFG_INTE_DSI_HOST_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTE_CSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTE_CSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTE_CSI_HOST_BITS 0x00000004 ++#define RPI_MIPICFG_INTE_CSI_HOST_MSB 2 ++#define RPI_MIPICFG_INTE_CSI_HOST_LSB 2 ++#define RPI_MIPICFG_INTE_CSI_HOST_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTE_DSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTE_DSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTE_DSI_DMA_BITS 0x00000002 ++#define RPI_MIPICFG_INTE_DSI_DMA_MSB 1 ++#define RPI_MIPICFG_INTE_DSI_DMA_LSB 1 ++#define RPI_MIPICFG_INTE_DSI_DMA_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTE_CSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTE_CSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTE_CSI_DMA_BITS 0x00000001 ++#define RPI_MIPICFG_INTE_CSI_DMA_MSB 0 ++#define RPI_MIPICFG_INTE_CSI_DMA_LSB 0 ++#define RPI_MIPICFG_INTE_CSI_DMA_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_INTF ++// JTAG access : synchronous ++// Description : Interrupt Force ++#define RPI_MIPICFG_INTF_OFFSET 0x00000030 ++#define RPI_MIPICFG_INTF_BITS 0x0000000f ++#define RPI_MIPICFG_INTF_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTF_DSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTF_DSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTF_DSI_HOST_BITS 0x00000008 ++#define RPI_MIPICFG_INTF_DSI_HOST_MSB 3 ++#define RPI_MIPICFG_INTF_DSI_HOST_LSB 3 ++#define RPI_MIPICFG_INTF_DSI_HOST_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTF_CSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTF_CSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTF_CSI_HOST_BITS 0x00000004 ++#define RPI_MIPICFG_INTF_CSI_HOST_MSB 2 ++#define RPI_MIPICFG_INTF_CSI_HOST_LSB 2 ++#define RPI_MIPICFG_INTF_CSI_HOST_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTF_DSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTF_DSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTF_DSI_DMA_BITS 0x00000002 ++#define RPI_MIPICFG_INTF_DSI_DMA_MSB 1 ++#define RPI_MIPICFG_INTF_DSI_DMA_LSB 1 ++#define RPI_MIPICFG_INTF_DSI_DMA_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTF_CSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTF_CSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTF_CSI_DMA_BITS 0x00000001 ++#define RPI_MIPICFG_INTF_CSI_DMA_MSB 0 ++#define RPI_MIPICFG_INTF_CSI_DMA_LSB 0 ++#define RPI_MIPICFG_INTF_CSI_DMA_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_INTS ++// JTAG access : synchronous ++// Description : Interrupt status after masking & forcing ++#define RPI_MIPICFG_INTS_OFFSET 0x00000034 ++#define RPI_MIPICFG_INTS_BITS 0x0000000f ++#define RPI_MIPICFG_INTS_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTS_DSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTS_DSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTS_DSI_HOST_BITS 0x00000008 ++#define RPI_MIPICFG_INTS_DSI_HOST_MSB 3 ++#define RPI_MIPICFG_INTS_DSI_HOST_LSB 3 ++#define RPI_MIPICFG_INTS_DSI_HOST_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTS_CSI_HOST ++// Description : None ++#define RPI_MIPICFG_INTS_CSI_HOST_RESET 0x0 ++#define RPI_MIPICFG_INTS_CSI_HOST_BITS 0x00000004 ++#define RPI_MIPICFG_INTS_CSI_HOST_MSB 2 ++#define RPI_MIPICFG_INTS_CSI_HOST_LSB 2 ++#define RPI_MIPICFG_INTS_CSI_HOST_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTS_DSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTS_DSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTS_DSI_DMA_BITS 0x00000002 ++#define RPI_MIPICFG_INTS_DSI_DMA_MSB 1 ++#define RPI_MIPICFG_INTS_DSI_DMA_LSB 1 ++#define RPI_MIPICFG_INTS_DSI_DMA_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_INTS_CSI_DMA ++// Description : None ++#define RPI_MIPICFG_INTS_CSI_DMA_RESET 0x0 ++#define RPI_MIPICFG_INTS_CSI_DMA_BITS 0x00000001 ++#define RPI_MIPICFG_INTS_CSI_DMA_MSB 0 ++#define RPI_MIPICFG_INTS_CSI_DMA_LSB 0 ++#define RPI_MIPICFG_INTS_CSI_DMA_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_BLOCK_ID ++// JTAG access : asynchronous ++// Description : Block Identifier ++#define RPI_MIPICFG_BLOCK_ID_OFFSET 0x00000038 ++#define RPI_MIPICFG_BLOCK_ID_BITS 0xffffffff ++#define RPI_MIPICFG_BLOCK_ID_RESET 0x4d495049 ++#define RPI_MIPICFG_BLOCK_ID_MSB 31 ++#define RPI_MIPICFG_BLOCK_ID_LSB 0 ++#define RPI_MIPICFG_BLOCK_ID_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_INSTANCE_ID ++// JTAG access : asynchronous ++// Description : Block Instance Identifier ++#define RPI_MIPICFG_INSTANCE_ID_OFFSET 0x0000003c ++#define RPI_MIPICFG_INSTANCE_ID_BITS 0x0000000f ++#define RPI_MIPICFG_INSTANCE_ID_RESET 0x00000000 ++#define RPI_MIPICFG_INSTANCE_ID_MSB 3 ++#define RPI_MIPICFG_INSTANCE_ID_LSB 0 ++#define RPI_MIPICFG_INSTANCE_ID_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_RSTSEQ_AUTO ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_RSTSEQ_AUTO_OFFSET 0x00000040 ++#define RPI_MIPICFG_RSTSEQ_AUTO_BITS 0x00000007 ++#define RPI_MIPICFG_RSTSEQ_AUTO_RESET 0x00000007 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_AUTO_CSI ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define RPI_MIPICFG_RSTSEQ_AUTO_CSI_RESET 0x1 ++#define RPI_MIPICFG_RSTSEQ_AUTO_CSI_BITS 0x00000004 ++#define RPI_MIPICFG_RSTSEQ_AUTO_CSI_MSB 2 ++#define RPI_MIPICFG_RSTSEQ_AUTO_CSI_LSB 2 ++#define RPI_MIPICFG_RSTSEQ_AUTO_CSI_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_AUTO_DPI ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define RPI_MIPICFG_RSTSEQ_AUTO_DPI_RESET 0x1 ++#define RPI_MIPICFG_RSTSEQ_AUTO_DPI_BITS 0x00000002 ++#define RPI_MIPICFG_RSTSEQ_AUTO_DPI_MSB 1 ++#define RPI_MIPICFG_RSTSEQ_AUTO_DPI_LSB 1 ++#define RPI_MIPICFG_RSTSEQ_AUTO_DPI_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER_RESET 0x1 ++#define RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER_BITS 0x00000001 ++#define RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER_MSB 0 ++#define RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER_LSB 0 ++#define RPI_MIPICFG_RSTSEQ_AUTO_BUSADAPTER_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_RSTSEQ_PARALLEL ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_OFFSET 0x00000044 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BITS 0x00000007 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_RESET 0x00000006 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_PARALLEL_CSI ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_CSI_RESET 0x1 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_CSI_BITS 0x00000004 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_CSI_MSB 2 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_CSI_LSB 2 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_CSI_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_PARALLEL_DPI ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_DPI_RESET 0x1 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_DPI_BITS 0x00000002 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_DPI_MSB 1 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_DPI_LSB 1 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_DPI_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER_BITS 0x00000001 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER_MSB 0 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER_LSB 0 ++#define RPI_MIPICFG_RSTSEQ_PARALLEL_BUSADAPTER_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_RSTSEQ_CTRL ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_RSTSEQ_CTRL_OFFSET 0x00000048 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BITS 0x00000007 ++#define RPI_MIPICFG_RSTSEQ_CTRL_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_CTRL_CSI ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define RPI_MIPICFG_RSTSEQ_CTRL_CSI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_CTRL_CSI_BITS 0x00000004 ++#define RPI_MIPICFG_RSTSEQ_CTRL_CSI_MSB 2 ++#define RPI_MIPICFG_RSTSEQ_CTRL_CSI_LSB 2 ++#define RPI_MIPICFG_RSTSEQ_CTRL_CSI_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_CTRL_DPI ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define RPI_MIPICFG_RSTSEQ_CTRL_DPI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_CTRL_DPI_BITS 0x00000002 ++#define RPI_MIPICFG_RSTSEQ_CTRL_DPI_MSB 1 ++#define RPI_MIPICFG_RSTSEQ_CTRL_DPI_LSB 1 ++#define RPI_MIPICFG_RSTSEQ_CTRL_DPI_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER_BITS 0x00000001 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER_MSB 0 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER_LSB 0 ++#define RPI_MIPICFG_RSTSEQ_CTRL_BUSADAPTER_ACCESS "RW" ++// ================================================================================ ++// Register : RPI_MIPICFG_RSTSEQ_TRIG ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_RSTSEQ_TRIG_OFFSET 0x0000004c ++#define RPI_MIPICFG_RSTSEQ_TRIG_BITS 0x00000007 ++#define RPI_MIPICFG_RSTSEQ_TRIG_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_TRIG_CSI ++// Description : Pulses the reset output ++#define RPI_MIPICFG_RSTSEQ_TRIG_CSI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_TRIG_CSI_BITS 0x00000004 ++#define RPI_MIPICFG_RSTSEQ_TRIG_CSI_MSB 2 ++#define RPI_MIPICFG_RSTSEQ_TRIG_CSI_LSB 2 ++#define RPI_MIPICFG_RSTSEQ_TRIG_CSI_ACCESS "SC" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_TRIG_DPI ++// Description : Pulses the reset output ++#define RPI_MIPICFG_RSTSEQ_TRIG_DPI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_TRIG_DPI_BITS 0x00000002 ++#define RPI_MIPICFG_RSTSEQ_TRIG_DPI_MSB 1 ++#define RPI_MIPICFG_RSTSEQ_TRIG_DPI_LSB 1 ++#define RPI_MIPICFG_RSTSEQ_TRIG_DPI_ACCESS "SC" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER ++// Description : Pulses the reset output ++#define RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER_BITS 0x00000001 ++#define RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER_MSB 0 ++#define RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER_LSB 0 ++#define RPI_MIPICFG_RSTSEQ_TRIG_BUSADAPTER_ACCESS "SC" ++// ================================================================================ ++// Register : RPI_MIPICFG_RSTSEQ_DONE ++// JTAG access : synchronous ++// Description : None ++#define RPI_MIPICFG_RSTSEQ_DONE_OFFSET 0x00000050 ++#define RPI_MIPICFG_RSTSEQ_DONE_BITS 0x00000007 ++#define RPI_MIPICFG_RSTSEQ_DONE_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_DONE_CSI ++// Description : Indicates the current state of the reset ++#define RPI_MIPICFG_RSTSEQ_DONE_CSI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_DONE_CSI_BITS 0x00000004 ++#define RPI_MIPICFG_RSTSEQ_DONE_CSI_MSB 2 ++#define RPI_MIPICFG_RSTSEQ_DONE_CSI_LSB 2 ++#define RPI_MIPICFG_RSTSEQ_DONE_CSI_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_DONE_DPI ++// Description : Indicates the current state of the reset ++#define RPI_MIPICFG_RSTSEQ_DONE_DPI_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_DONE_DPI_BITS 0x00000002 ++#define RPI_MIPICFG_RSTSEQ_DONE_DPI_MSB 1 ++#define RPI_MIPICFG_RSTSEQ_DONE_DPI_LSB 1 ++#define RPI_MIPICFG_RSTSEQ_DONE_DPI_ACCESS "RO" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER ++// Description : Indicates the current state of the reset ++#define RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER_RESET 0x0 ++#define RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER_BITS 0x00000001 ++#define RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER_MSB 0 ++#define RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER_LSB 0 ++#define RPI_MIPICFG_RSTSEQ_DONE_BUSADAPTER_ACCESS "RO" ++// ================================================================================ ++// Register : RPI_MIPICFG_DFTSS ++// JTAG access : asynchronous ++// Description : None ++#define RPI_MIPICFG_DFTSS_OFFSET 0x00000054 ++#define RPI_MIPICFG_DFTSS_BITS 0x0000001f ++#define RPI_MIPICFG_DFTSS_RESET 0x00000000 ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DFTSS_JTAG_COPY ++// Description : None ++#define RPI_MIPICFG_DFTSS_JTAG_COPY_RESET 0x0 ++#define RPI_MIPICFG_DFTSS_JTAG_COPY_BITS 0x00000010 ++#define RPI_MIPICFG_DFTSS_JTAG_COPY_MSB 4 ++#define RPI_MIPICFG_DFTSS_JTAG_COPY_LSB 4 ++#define RPI_MIPICFG_DFTSS_JTAG_COPY_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY ++// Description : None ++#define RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY_RESET 0x0 ++#define RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY_BITS 0x00000008 ++#define RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY_MSB 3 ++#define RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY_LSB 3 ++#define RPI_MIPICFG_DFTSS_JTAG_ACCESS_ONLY_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS ++// Description : None ++#define RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS_RESET 0x0 ++#define RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS_BITS 0x00000004 ++#define RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS_MSB 2 ++#define RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS_LSB 2 ++#define RPI_MIPICFG_DFTSS_BYPASS_OUTSYNCS_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DFTSS_BYPASS_INSYNCS ++// Description : None ++#define RPI_MIPICFG_DFTSS_BYPASS_INSYNCS_RESET 0x0 ++#define RPI_MIPICFG_DFTSS_BYPASS_INSYNCS_BITS 0x00000002 ++#define RPI_MIPICFG_DFTSS_BYPASS_INSYNCS_MSB 1 ++#define RPI_MIPICFG_DFTSS_BYPASS_INSYNCS_LSB 1 ++#define RPI_MIPICFG_DFTSS_BYPASS_INSYNCS_ACCESS "RW" ++// -------------------------------------------------------------------------------- ++// Field : RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS ++// Description : None ++#define RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS_RESET 0x0 ++#define RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS_BITS 0x00000001 ++#define RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS_MSB 0 ++#define RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS_LSB 0 ++#define RPI_MIPICFG_DFTSS_BYPASS_RESETSYNCS_ACCESS "RW" ++ ++#define CFG_WRITE(reg, val) writel((val), dsi->hw_base[RP1DSI_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++#define CFG_READ(reg) readl(dsi->hw_base[RP1DSI_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++ ++/* ------------------------------- DPHY setup stuff ------------------------ */ ++ ++static void dphy_transaction(struct rp1_dsi *dsi, uint8_t test_code, uint8_t test_data) ++{ ++ /* ++ * See pg 101 of mipi dphy bidir databook ++ * Assume we start with testclk high. ++ * Each APB write takes at least 10ns and we ignore TESTDOUT ++ * so there is no need for extra delays between the transitions. ++ */ ++ u32 tmp; ++ ++ DSI_WRITE(DSI_PHY_TST_CTRL1, test_code | DPHY_CTRL1_PHY_TESTEN_BITS); ++ DSI_WRITE(DSI_PHY_TST_CTRL0, 0); ++ tmp = (DSI_READ(DSI_PHY_TST_CTRL1) >> DPHY_CTRL1_PHY_TESTDOUT_LSB) & 0xFF; ++ DSI_WRITE(DSI_PHY_TST_CTRL1, test_data); ++ DSI_WRITE(DSI_PHY_TST_CTRL0, DPHY_CTRL0_PHY_TESTCLK_BITS); ++} ++ ++static uint8_t dphy_get_div(u32 refclk_khz, u32 vco_freq_khz, u32 *ptr_m, u32 *ptr_n) ++{ ++ /* ++ * See pg 77-78 of dphy databook ++ * fvco = m/n * refclk ++ * with the limit ++ * 40MHz >= fREFCLK / N >= 5MHz ++ * M (multiplier) must be an even number between 2 and 300 ++ * N (input divider) must be an integer between 1 and 100 ++ * ++ * In practice, given a 50MHz reference clock, it can produce any ++ * multiple of 10MHz, 11.1111MHz, 12.5MHz, 14.286MHz or 16.667MHz ++ * with < 1% error for all frequencies above 495MHz. ++ */ ++ ++ static const u32 REF_DIVN_MAX = 40000u; ++ static const u32 REF_DIVN_MIN = 5000u; ++ u32 best_n, best_m, best_err = 0x7fffffff; ++ unsigned int n; ++ ++ for (n = 1 + refclk_khz / REF_DIVN_MAX; n * REF_DIVN_MIN <= refclk_khz && n < 100; ++n) { ++ u32 half_m = (n * vco_freq_khz + refclk_khz) / (2 * refclk_khz); ++ ++ if (half_m < 150) { ++ u32 f = (2 * half_m * refclk_khz) / n; ++ u32 err = (f > vco_freq_khz) ? f - vco_freq_khz : vco_freq_khz - f; ++ ++ if (err < best_err) { ++ best_n = n; ++ best_m = 2 * half_m; ++ best_err = err; ++ if (err == 0) ++ break; ++ } ++ } ++ } ++ ++ if (64 * best_err < vco_freq_khz) { /* tolerate small error */ ++ *ptr_n = best_n; ++ *ptr_m = best_m; ++ return 1; ++ } ++ return 0; ++} ++ ++struct hsfreq_range { ++ u16 mhz_max; ++ u8 hsfreqrange; ++ u8 clk_lp2hs; ++ u8 clk_hs2lp; ++ u8 data_lp2hs; /* excluding clk lane entry */ ++ u8 data_hs2lp; ++}; ++ ++/* See Table A-3 on page 258 of dphy databook */ ++static const struct hsfreq_range hsfreq_table[] = { ++ { 89, 0b000000, 32, 20, 26, 13 }, ++ { 99, 0b010000, 35, 23, 28, 14 }, ++ { 109, 0b100000, 32, 22, 26, 13 }, ++ { 129, 0b000001, 31, 20, 27, 13 }, ++ { 139, 0b010001, 33, 22, 26, 14 }, ++ { 149, 0b100001, 33, 21, 26, 14 }, ++ { 169, 0b000010, 32, 20, 27, 13 }, ++ { 179, 0b010010, 36, 23, 30, 15 }, ++ { 199, 0b100010, 40, 22, 33, 15 }, ++ { 219, 0b000011, 40, 22, 33, 15 }, ++ { 239, 0b010011, 44, 24, 36, 16 }, ++ { 249, 0b100011, 48, 24, 38, 17 }, ++ { 269, 0b000100, 48, 24, 38, 17 }, ++ { 299, 0b010100, 50, 27, 41, 18 }, ++ { 329, 0b000101, 56, 28, 45, 18 }, ++ { 359, 0b010101, 59, 28, 48, 19 }, ++ { 399, 0b100101, 61, 30, 50, 20 }, ++ { 449, 0b000110, 67, 31, 55, 21 }, ++ { 499, 0b010110, 73, 31, 59, 22 }, ++ { 549, 0b000111, 79, 36, 63, 24 }, ++ { 599, 0b010111, 83, 37, 68, 25 }, ++ { 649, 0b001000, 90, 38, 73, 27 }, ++ { 699, 0b011000, 95, 40, 77, 28 }, ++ { 749, 0b001001, 102, 40, 84, 28 }, ++ { 799, 0b011001, 106, 42, 87, 30 }, ++ { 849, 0b101001, 113, 44, 93, 31 }, ++ { 899, 0b111001, 118, 47, 98, 32 }, ++ { 949, 0b001010, 124, 47, 102, 34 }, ++ { 999, 0b011010, 130, 49, 107, 35 }, ++ { 1049, 0b101010, 135, 51, 111, 37 }, ++ { 1099, 0b111010, 139, 51, 114, 38 }, ++ { 1149, 0b001011, 146, 54, 120, 40 }, ++ { 1199, 0b011011, 153, 57, 125, 41 }, ++ { 1249, 0b101011, 158, 58, 130, 42 }, ++ { 1299, 0b111011, 163, 58, 135, 44 }, ++ { 1349, 0b001100, 168, 60, 140, 45 }, ++ { 1399, 0b011100, 172, 64, 144, 47 }, ++ { 1449, 0b101100, 176, 65, 148, 48 }, ++ { 1500, 0b111100, 181, 66, 153, 50 }, ++}; ++ ++static void dphy_set_hsfreqrange(struct rp1_dsi *dsi, u32 freq_mhz) ++{ ++ unsigned int i; ++ ++ if (freq_mhz < 80 || freq_mhz > 1500) ++ drm_err(dsi->drm, "DPHY: Frequency %u MHz out of range\n", ++ freq_mhz); ++ ++ for (i = 0; i < ARRAY_SIZE(hsfreq_table) - 1; i++) { ++ if (freq_mhz <= hsfreq_table[i].mhz_max) ++ break; ++ } ++ ++ dsi->hsfreq_index = i; ++ dphy_transaction(dsi, DPHY_HS_RX_CTRL_LANE0_OFFSET, ++ hsfreq_table[i].hsfreqrange << 1); ++} ++ ++static void dphy_configure_pll(struct rp1_dsi *dsi, u32 refclk_khz, u32 vco_freq_khz) ++{ ++ u32 m = 0; ++ u32 n = 0; ++ ++ if (dphy_get_div(refclk_khz, vco_freq_khz, &m, &n)) { ++ dphy_set_hsfreqrange(dsi, vco_freq_khz / 1000); ++ /* Program m,n from registers */ ++ dphy_transaction(dsi, DPHY_PLL_DIV_CTRL_OFFSET, 0x30); ++ /* N (program N-1) */ ++ dphy_transaction(dsi, DPHY_PLL_INPUT_DIV_OFFSET, n - 1); ++ /* M[8:5] ?? */ ++ dphy_transaction(dsi, DPHY_PLL_LOOP_DIV_OFFSET, 0x80 | ((m - 1) >> 5)); ++ /* M[4:0] (program M-1) */ ++ dphy_transaction(dsi, DPHY_PLL_LOOP_DIV_OFFSET, ((m - 1) & 0x1F)); ++ drm_dbg_driver(dsi->drm, ++ "DPHY: vco freq want %dkHz got %dkHz = %d * (%dkHz / %d), hsfreqrange = 0x%02x\r\n", ++ vco_freq_khz, refclk_khz * m / n, m, refclk_khz, ++ n, hsfreq_table[dsi->hsfreq_index].hsfreqrange); ++ } else { ++ drm_info(dsi->drm, ++ "rp1dsi: Error configuring DPHY PLL! %dkHz = %d * (%dkHz / %d)\r\n", ++ vco_freq_khz, m, refclk_khz, n); ++ } ++} ++ ++static void dphy_init_khz(struct rp1_dsi *dsi, u32 ref_freq, u32 vco_freq) ++{ ++ /* Reset the PHY */ ++ DSI_WRITE(DSI_PHYRSTZ, 0); ++ DSI_WRITE(DSI_PHY_TST_CTRL0, DPHY_CTRL0_PHY_TESTCLK_BITS); ++ DSI_WRITE(DSI_PHY_TST_CTRL1, 0); ++ DSI_WRITE(DSI_PHY_TST_CTRL0, (DPHY_CTRL0_PHY_TESTCLK_BITS | DPHY_CTRL0_PHY_TESTCLR_BITS)); ++ udelay(1); ++ DSI_WRITE(DSI_PHY_TST_CTRL0, DPHY_CTRL0_PHY_TESTCLK_BITS); ++ udelay(1); ++ /* Since we are in DSI (not CSI2) mode here, start the PLL */ ++ dphy_configure_pll(dsi, ref_freq, vco_freq); ++ udelay(1); ++ /* Unreset */ ++ DSI_WRITE(DSI_PHYRSTZ, DSI_PHYRSTZ_SHUTDOWNZ_BITS); ++ udelay(1); ++ DSI_WRITE(DSI_PHYRSTZ, (DSI_PHYRSTZ_SHUTDOWNZ_BITS | DSI_PHYRSTZ_RSTZ_BITS)); ++ udelay(1); /* so we can see PLL coming up? */ ++} ++ ++void rp1dsi_mipicfg_setup(struct rp1_dsi *dsi) ++{ ++ /* Select DSI rather than CSI-2 */ ++ CFG_WRITE(RPI_MIPICFG_CFG, 0); ++ /* Enable DSIDMA interrupt only */ ++ CFG_WRITE(RPI_MIPICFG_INTE, RPI_MIPICFG_INTE_DSI_DMA_BITS); ++} ++ ++static unsigned long rp1dsi_refclk_freq(struct rp1_dsi *dsi) ++{ ++ unsigned long u; ++ ++ u = (dsi->clocks[RP1DSI_CLOCK_REF]) ? clk_get_rate(dsi->clocks[RP1DSI_CLOCK_REF]) : 0; ++ if (u < 1 || u >= (1ul << 30)) ++ u = 50000000ul; /* default XOSC frequency */ ++ return u; ++} ++ ++static void rp1dsi_dpiclk_start(struct rp1_dsi *dsi, unsigned int bpp, unsigned int lanes) ++{ ++ unsigned long u; ++ ++ if (dsi->clocks[RP1DSI_CLOCK_DPI]) { ++ u = (dsi->clocks[RP1DSI_CLOCK_BYTE]) ? ++ clk_get_rate(dsi->clocks[RP1DSI_CLOCK_BYTE]) : 0; ++ drm_info(dsi->drm, ++ "rp1dsi: Nominal byte clock %lu; scale by %u/%u", ++ u, 4 * lanes, (bpp >> 1)); ++ if (u < 1 || u >= (1ul << 28)) ++ u = 72000000ul; /* default DUMMY frequency for byteclock */ ++ ++ clk_set_parent(dsi->clocks[RP1DSI_CLOCK_DPI], dsi->clocks[RP1DSI_CLOCK_BYTE]); ++ clk_set_rate(dsi->clocks[RP1DSI_CLOCK_DPI], (4 * lanes * u) / (bpp >> 1)); ++ clk_prepare_enable(dsi->clocks[RP1DSI_CLOCK_DPI]); ++ } ++} ++ ++static void rp1dsi_dpiclk_stop(struct rp1_dsi *dsi) ++{ ++ if (dsi->clocks[RP1DSI_CLOCK_DPI]) ++ clk_disable_unprepare(dsi->clocks[RP1DSI_CLOCK_DPI]); ++} ++ ++/* Choose the internal on-the-bus DPI format, and DSI packing flag. */ ++static u32 get_colorcode(enum mipi_dsi_pixel_format fmt) ++{ ++ switch (fmt) { ++ case MIPI_DSI_FMT_RGB666: ++ return 0x104; ++ case MIPI_DSI_FMT_RGB666_PACKED: ++ return 0x003; ++ case MIPI_DSI_FMT_RGB565: ++ return 0x000; ++ case MIPI_DSI_FMT_RGB888: ++ return 0x005; ++ } ++ ++ /* This should be impossible as the format is validated in ++ * rp1dsi_host_attach ++ */ ++ WARN_ONCE(1, "Invalid colour format configured for DSI"); ++ return 0x005; ++} ++ ++void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode) ++{ ++ u32 timeout, mask, vid_mode_cfg; ++ u32 freq_khz; ++ unsigned int bpp = mipi_dsi_pixel_format_to_bpp(dsi->display_format); ++ ++ DSI_WRITE(DSI_PHY_IF_CFG, dsi->lanes - 1); ++ DSI_WRITE(DSI_DPI_CFG_POL, 0); ++ DSI_WRITE(DSI_GEN_VCID, dsi->vc); ++ DSI_WRITE(DSI_DPI_COLOR_CODING, get_colorcode(dsi->display_format)); ++ /* a conservative guess (LP escape is slow!) */ ++ DSI_WRITE(DSI_DPI_LP_CMD_TIM, 0x00100000); ++ ++ /* Drop to LP where possible */ ++ vid_mode_cfg = 0xbf00; ++ if (!(dsi->display_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) ++ vid_mode_cfg |= 0x01; ++ if (dsi->display_flags & MIPI_DSI_MODE_VIDEO_BURST) ++ vid_mode_cfg |= 0x02; ++ DSI_WRITE(DSI_VID_MODE_CFG, vid_mode_cfg); ++ ++ /* Use LP Escape Data signalling for all commands */ ++ DSI_WRITE(DSI_CMD_MODE_CFG, 0x10F7F00); ++ /* Select Command Mode */ ++ DSI_WRITE(DSI_MODE_CFG, 1); ++ /* XXX magic number */ ++ DSI_WRITE(DSI_TO_CNT_CFG, 0x02000200); ++ /* XXX magic number */ ++ DSI_WRITE(DSI_BTA_TO_CNT, 0x800); ++ ++ DSI_WRITE(DSI_VID_PKT_SIZE, mode->hdisplay); ++ DSI_WRITE(DSI_VID_NUM_CHUNKS, 0); ++ DSI_WRITE(DSI_VID_NULL_SIZE, 0); ++ ++ /* Note, unlike Argon firmware, here we DON'T consider sync to be concurrent with porch */ ++ DSI_WRITE(DSI_VID_HSA_TIME, ++ (bpp * (mode->hsync_end - mode->hsync_start)) / (8 * dsi->lanes)); ++ DSI_WRITE(DSI_VID_HBP_TIME, ++ (bpp * (mode->htotal - mode->hsync_end)) / (8 * dsi->lanes)); ++ DSI_WRITE(DSI_VID_HLINE_TIME, (bpp * mode->htotal) / (8 * dsi->lanes)); ++ DSI_WRITE(DSI_VID_VSA_LINES, (mode->vsync_end - mode->vsync_start)); ++ DSI_WRITE(DSI_VID_VBP_LINES, (mode->vtotal - mode->vsync_end)); ++ DSI_WRITE(DSI_VID_VFP_LINES, (mode->vsync_start - mode->vdisplay)); ++ DSI_WRITE(DSI_VID_VACTIVE_LINES, mode->vdisplay); ++ ++ freq_khz = (bpp * mode->clock) / dsi->lanes; ++ ++ dphy_init_khz(dsi, rp1dsi_refclk_freq(dsi) / 1000, freq_khz); ++ ++ DSI_WRITE(DSI_PHY_TMR_LPCLK_CFG, ++ (hsfreq_table[dsi->hsfreq_index].clk_lp2hs << DSI_PHY_TMR_LP2HS_LSB) | ++ (hsfreq_table[dsi->hsfreq_index].clk_hs2lp << DSI_PHY_TMR_HS2LP_LSB)); ++ DSI_WRITE(DSI_PHY_TMR_CFG, ++ (hsfreq_table[dsi->hsfreq_index].data_lp2hs << DSI_PHY_TMR_LP2HS_LSB) | ++ (hsfreq_table[dsi->hsfreq_index].data_hs2lp << DSI_PHY_TMR_HS2LP_LSB)); ++ ++ DSI_WRITE(DSI_CLKMGR_CFG, 0x00000505); ++ ++ /* Wait for PLL lock */ ++ for (timeout = (1 << 14); timeout != 0; --timeout) { ++ usleep_range(10, 50); ++ if (DSI_READ(DSI_PHY_STATUS) & (1 << 0)) ++ break; ++ } ++ if (timeout == 0) ++ drm_err(dsi->drm, "RP1DSI: Time out waiting for PLL\n"); ++ ++ DSI_WRITE(DSI_LPCLK_CTRL, 0x1); /* configure the requesthsclk */ ++ DSI_WRITE(DSI_PHY_TST_CTRL0, 0x2); ++ DSI_WRITE(DSI_PCKHDL_CFG, 1 << 2); /* allow bus turnaround */ ++ DSI_WRITE(DSI_PWR_UP, 0x1); /* power up */ ++ ++ /* Now it should be safe to start the external DPI clock divider */ ++ rp1dsi_dpiclk_start(dsi, bpp, dsi->lanes); ++ ++ /* Wait for all lane(s) to be in Stopstate */ ++ mask = (1 << 4); ++ if (dsi->lanes >= 2) ++ mask |= (1 << 7); ++ if (dsi->lanes >= 3) ++ mask |= (1 << 9); ++ if (dsi->lanes >= 4) ++ mask |= (1 << 11); ++ for (timeout = (1 << 10); timeout != 0; --timeout) { ++ usleep_range(10, 50); ++ if ((DSI_READ(DSI_PHY_STATUS) & mask) == mask) ++ break; ++ } ++ if (timeout == 0) ++ drm_err(dsi->drm, "RP1DSI: Time out waiting for lanes (%x %x)\n", ++ mask, DSI_READ(DSI_PHY_STATUS)); ++} ++ ++void rp1dsi_dsi_send(struct rp1_dsi *dsi, u32 hdr, int len, const u8 *buf) ++{ ++ u32 val; ++ ++ /* Wait for both FIFOs empty */ ++ for (val = 256; val > 0; --val) { ++ if ((DSI_READ(DSI_CMD_PKT_STATUS) & 0xF) == 0x5) ++ break; ++ usleep_range(100, 150); ++ } ++ ++ /* Write payload (in 32-bit words) and header */ ++ for (; len > 0; len -= 4) { ++ val = *buf++; ++ if (len > 1) ++ val |= (*buf++) << 8; ++ if (len > 2) ++ val |= (*buf++) << 16; ++ if (len > 3) ++ val |= (*buf++) << 24; ++ DSI_WRITE(DSI_GEN_PLD_DATA, val); ++ } ++ DSI_WRITE(DSI_GEN_HDR, hdr); ++ ++ /* Wait for both FIFOs empty */ ++ for (val = 256; val > 0; --val) { ++ if ((DSI_READ(DSI_CMD_PKT_STATUS) & 0xF) == 0x5) ++ break; ++ usleep_range(100, 150); ++ } ++} ++ ++int rp1dsi_dsi_recv(struct rp1_dsi *dsi, int len, u8 *buf) ++{ ++ int i, j; ++ u32 val; ++ ++ /* Wait until not busy and FIFO not empty */ ++ for (i = 1024; i > 0; --i) { ++ val = DSI_READ(DSI_CMD_PKT_STATUS); ++ if ((val & ((1 << 6) | (1 << 4))) == 0) ++ break; ++ usleep_range(100, 150); ++ } ++ if (i == 0) ++ return -EIO; ++ ++ for (i = 0; i < len; i += 4) { ++ /* Read fifo must not be empty before all bytes are read */ ++ if (DSI_READ(DSI_CMD_PKT_STATUS) & (1 << 4)) ++ break; ++ ++ val = DSI_READ(DSI_GEN_PLD_DATA); ++ for (j = 0; j < 4 && j + i < len; j++) ++ *buf++ = val >> (8 * j); ++ } ++ ++ return (i >= len) ? len : (i > 0) ? i : -EIO; ++} ++ ++void rp1dsi_dsi_stop(struct rp1_dsi *dsi) ++{ ++ DSI_WRITE(DSI_MODE_CFG, 1); /* Return to Command Mode */ ++ DSI_WRITE(DSI_LPCLK_CTRL, 2); /* Stop the HS clock */ ++ DSI_WRITE(DSI_PWR_UP, 0x0); /* Power down host controller */ ++ DSI_WRITE(DSI_PHYRSTZ, 0); /* PHY into reset. */ ++ rp1dsi_dpiclk_stop(dsi); ++} ++ ++void rp1dsi_dsi_set_cmdmode(struct rp1_dsi *dsi, int mode) ++{ ++ DSI_WRITE(DSI_MODE_CFG, mode); ++} diff --git a/target/linux/bcm27xx/patches-6.1/950-0886-drm-Add-RP1-DPI-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0886-drm-Add-RP1-DPI-driver.patch new file mode 100644 index 0000000000..2023bf73e8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0886-drm-Add-RP1-DPI-driver.patch @@ -0,0 +1,1552 @@ +From 61c3065f89d4447c7e4cf61a466ebc3c4a834ad2 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Tue, 19 Sep 2023 17:51:49 +0100 +Subject: [PATCH] drm: Add RP1 DPI driver + +Add support for the RP1 DPI hardware. + +Signed-off-by: Nick Hollinghurst +--- + drivers/gpu/drm/rp1/rp1-dpi/Kconfig | 12 + + drivers/gpu/drm/rp1/rp1-dpi/Makefile | 5 + + drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c | 429 ++++++++++++++++++ + drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h | 69 +++ + drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_cfg.c | 510 ++++++++++++++++++++++ + drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c | 486 +++++++++++++++++++++ + 6 files changed, 1511 insertions(+) + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/Kconfig + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/Makefile + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_cfg.c + create mode 100644 drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c + +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/Kconfig +@@ -0,0 +1,12 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config DRM_RP1_DPI ++ tristate "DRM Support for RP1 DPI" ++ depends on DRM ++ select MFD_RP1 ++ select DRM_GEM_DMA_HELPER ++ select DRM_KMS_HELPER ++ select DRM_VRAM_HELPER ++ select DRM_TTM ++ select DRM_TTM_HELPER ++ help ++ Choose this option to enable Video Out on RP1 +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/Makefile +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++drm-rp1-dpi-y := rp1_dpi.o rp1_dpi_hw.o rp1_dpi_cfg.o ++ ++obj-$(CONFIG_DRM_RP1_DPI) += drm-rp1-dpi.o +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.c +@@ -0,0 +1,429 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DPI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_dpi.h" ++ ++/* ++ * Default bus format, where not specified by a connector/bridge ++ * and not overridden by the OF property "default_bus_fmt". ++ * This value is for compatibility with vc4 and VGA666-style boards, ++ * even though RP1 hardware cannot achieve the full 18-bit depth ++ * with that pinout (MEDIA_BUS_FMT_RGB666_1X24_CPADHI is preferred). ++ */ ++static unsigned int default_bus_fmt = MEDIA_BUS_FMT_RGB666_1X18; ++module_param(default_bus_fmt, uint, 0644); ++ ++/* -------------------------------------------------------------- */ ++ ++static void rp1dpi_pipe_update(struct drm_simple_display_pipe *pipe, ++ struct drm_plane_state *old_state) ++{ ++ struct drm_pending_vblank_event *event; ++ unsigned long flags; ++ struct drm_framebuffer *fb = pipe->plane.state->fb; ++ struct rp1_dpi *dpi = pipe->crtc.dev->dev_private; ++ struct drm_gem_object *gem = fb ? drm_gem_fb_get_obj(fb, 0) : NULL; ++ struct drm_gem_dma_object *dma_obj = gem ? to_drm_gem_dma_obj(gem) : NULL; ++ bool can_update = fb && dma_obj && dpi && dpi->pipe_enabled; ++ ++ /* (Re-)start DPI-DMA where required; and update FB address */ ++ if (can_update) { ++ if (!dpi->dpi_running || fb->format->format != dpi->cur_fmt) { ++ if (dpi->dpi_running && ++ fb->format->format != dpi->cur_fmt) { ++ rp1dpi_hw_stop(dpi); ++ dpi->dpi_running = false; ++ } ++ if (!dpi->dpi_running) { ++ rp1dpi_hw_setup(dpi, ++ fb->format->format, ++ dpi->bus_fmt, ++ dpi->de_inv, ++ &pipe->crtc.state->mode); ++ dpi->dpi_running = true; ++ } ++ dpi->cur_fmt = fb->format->format; ++ drm_crtc_vblank_on(&pipe->crtc); ++ } ++ rp1dpi_hw_update(dpi, dma_obj->dma_addr, fb->offsets[0], fb->pitches[0]); ++ } ++ ++ /* Arm VBLANK event (or call it immediately in some error cases) */ ++ spin_lock_irqsave(&pipe->crtc.dev->event_lock, flags); ++ event = pipe->crtc.state->event; ++ if (event) { ++ pipe->crtc.state->event = NULL; ++ if (can_update && drm_crtc_vblank_get(&pipe->crtc) == 0) ++ drm_crtc_arm_vblank_event(&pipe->crtc, event); ++ else ++ drm_crtc_send_vblank_event(&pipe->crtc, event); ++ } ++ spin_unlock_irqrestore(&pipe->crtc.dev->event_lock, flags); ++} ++ ++static void rp1dpi_pipe_enable(struct drm_simple_display_pipe *pipe, ++ struct drm_crtc_state *crtc_state, ++ struct drm_plane_state *plane_state) ++{ ++ static const unsigned int M = 1000000; ++ struct rp1_dpi *dpi = pipe->crtc.dev->dev_private; ++ struct drm_connector *conn; ++ struct drm_connector_list_iter conn_iter; ++ unsigned int fpix, fdiv, fvco; ++ int ret; ++ ++ /* Look up the connector attached to DPI so we can get the ++ * bus_format. Ideally the bridge would tell us the ++ * bus_format we want, but it doesn't yet, so assume that it's ++ * uniform throughout the bridge chain. ++ */ ++ dev_info(&dpi->pdev->dev, __func__); ++ drm_connector_list_iter_begin(pipe->encoder.dev, &conn_iter); ++ drm_for_each_connector_iter(conn, &conn_iter) { ++ if (conn->encoder == &pipe->encoder) { ++ dpi->de_inv = !!(conn->display_info.bus_flags & ++ DRM_BUS_FLAG_DE_LOW); ++ dpi->clk_inv = !!(conn->display_info.bus_flags & ++ DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE); ++ if (conn->display_info.num_bus_formats) ++ dpi->bus_fmt = conn->display_info.bus_formats[0]; ++ break; ++ } ++ } ++ drm_connector_list_iter_end(&conn_iter); ++ ++ /* Set DPI clock to desired frequency. Currently (experimentally) ++ * we take control of the VideoPLL, to ensure we can generate it ++ * accurately. NB: this prevents concurrent use of DPI and VEC! ++ * Magic numbers ensure the parent clock is within [100MHz, 200MHz] ++ * with VCO in [1GHz, 1.33GHz]. The initial divide is by 6, 8 or 10. ++ */ ++ fpix = 1000 * pipe->crtc.state->mode.clock; ++ fpix = clamp(fpix, 1 * M, 200 * M); ++ fdiv = fpix; ++ while (fdiv < 100 * M) ++ fdiv *= 2; ++ fvco = fdiv * 2 * DIV_ROUND_UP(500 * M, fdiv); ++ ret = clk_set_rate(dpi->clocks[RP1DPI_CLK_PLLCORE], fvco); ++ if (ret) ++ dev_err(&dpi->pdev->dev, "Failed to set PLL VCO to %u (%d)", fvco, ret); ++ ret = clk_set_rate(dpi->clocks[RP1DPI_CLK_PLLDIV], fdiv); ++ if (ret) ++ dev_err(&dpi->pdev->dev, "Failed to set PLL output to %u (%d)", fdiv, ret); ++ ret = clk_set_rate(dpi->clocks[RP1DPI_CLK_DPI], fpix); ++ if (ret) ++ dev_err(&dpi->pdev->dev, "Failed to set DPI clock to %u (%d)", fpix, ret); ++ ++ rp1dpi_vidout_setup(dpi, dpi->clk_inv); ++ clk_prepare_enable(dpi->clocks[RP1DPI_CLK_PLLCORE]); ++ clk_prepare_enable(dpi->clocks[RP1DPI_CLK_PLLDIV]); ++ pinctrl_pm_select_default_state(&dpi->pdev->dev); ++ clk_prepare_enable(dpi->clocks[RP1DPI_CLK_DPI]); ++ dev_info(&dpi->pdev->dev, "Want %u /%u %u /%u %u; got VCO=%lu DIV=%lu DPI=%lu", ++ fvco, fvco / fdiv, fdiv, fdiv / fpix, fpix, ++ clk_get_rate(dpi->clocks[RP1DPI_CLK_PLLCORE]), ++ clk_get_rate(dpi->clocks[RP1DPI_CLK_PLLDIV]), ++ clk_get_rate(dpi->clocks[RP1DPI_CLK_DPI])); ++ ++ /* Start DPI-DMA. pipe already has the new crtc and plane state. */ ++ dpi->pipe_enabled = true; ++ dpi->cur_fmt = 0xdeadbeef; ++ rp1dpi_pipe_update(pipe, 0); ++} ++ ++static void rp1dpi_pipe_disable(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_dpi *dpi = pipe->crtc.dev->dev_private; ++ ++ dev_info(&dpi->pdev->dev, __func__); ++ drm_crtc_vblank_off(&pipe->crtc); ++ if (dpi->dpi_running) { ++ rp1dpi_hw_stop(dpi); ++ dpi->dpi_running = false; ++ } ++ clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_DPI]); ++ pinctrl_pm_select_sleep_state(&dpi->pdev->dev); ++ clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_PLLDIV]); ++ clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_PLLCORE]); ++ dpi->pipe_enabled = false; ++} ++ ++static int rp1dpi_pipe_enable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_dpi *dpi = pipe->crtc.dev->dev_private; ++ ++ if (dpi) ++ rp1dpi_hw_vblank_ctrl(dpi, 1); ++ ++ return 0; ++} ++ ++static void rp1dpi_pipe_disable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_dpi *dpi = pipe->crtc.dev->dev_private; ++ ++ if (dpi) ++ rp1dpi_hw_vblank_ctrl(dpi, 0); ++} ++ ++static const struct drm_simple_display_pipe_funcs rp1dpi_pipe_funcs = { ++ .enable = rp1dpi_pipe_enable, ++ .update = rp1dpi_pipe_update, ++ .disable = rp1dpi_pipe_disable, ++ .prepare_fb = drm_gem_simple_display_pipe_prepare_fb, ++ .enable_vblank = rp1dpi_pipe_enable_vblank, ++ .disable_vblank = rp1dpi_pipe_disable_vblank, ++}; ++ ++static const struct drm_mode_config_funcs rp1dpi_mode_funcs = { ++ .fb_create = drm_gem_fb_create, ++ .atomic_check = drm_atomic_helper_check, ++ .atomic_commit = drm_atomic_helper_commit, ++}; ++ ++static void rp1dpi_stopall(struct drm_device *drm) ++{ ++ if (drm->dev_private) { ++ struct rp1_dpi *dpi = drm->dev_private; ++ ++ if (dpi->dpi_running || rp1dpi_hw_busy(dpi)) { ++ rp1dpi_hw_stop(dpi); ++ clk_disable_unprepare(dpi->clocks[RP1DPI_CLK_DPI]); ++ dpi->dpi_running = false; ++ } ++ rp1dpi_vidout_poweroff(dpi); ++ pinctrl_pm_select_sleep_state(&dpi->pdev->dev); ++ } ++} ++ ++DEFINE_DRM_GEM_DMA_FOPS(rp1dpi_fops); ++ ++static struct drm_driver rp1dpi_driver = { ++ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, ++ .fops = &rp1dpi_fops, ++ .name = "drm-rp1-dpi", ++ .desc = "drm-rp1-dpi", ++ .date = "0", ++ .major = 1, ++ .minor = 0, ++ DRM_GEM_DMA_DRIVER_OPS, ++ .release = rp1dpi_stopall, ++}; ++ ++static const u32 rp1dpi_formats[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_RGB888, ++ DRM_FORMAT_BGR888, ++ DRM_FORMAT_RGB565 ++}; ++ ++static int rp1dpi_platform_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct drm_device *drm; ++ struct rp1_dpi *dpi; ++ struct drm_bridge *bridge = NULL; ++ struct drm_panel *panel; ++ int i, ret; ++ ++ dev_info(dev, __func__); ++ ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 0, 0, ++ &panel, &bridge); ++ if (ret) { ++ dev_info(dev, "%s: bridge not found\n", __func__); ++ return -EPROBE_DEFER; ++ } ++ if (panel) { ++ bridge = devm_drm_panel_bridge_add(dev, panel); ++ if (IS_ERR(bridge)) ++ return PTR_ERR(bridge); ++ } ++ ++ drm = drm_dev_alloc(&rp1dpi_driver, dev); ++ if (IS_ERR(drm)) { ++ dev_info(dev, "%s %d", __func__, (int)__LINE__); ++ ret = PTR_ERR(drm); ++ return ret; ++ } ++ dpi = drmm_kzalloc(drm, sizeof(*dpi), GFP_KERNEL); ++ if (!dpi) { ++ dev_info(dev, "%s %d", __func__, (int)__LINE__); ++ drm_dev_put(drm); ++ return -ENOMEM; ++ } ++ ++ init_completion(&dpi->finished); ++ dpi->drm = drm; ++ dpi->pdev = pdev; ++ drm->dev_private = dpi; ++ platform_set_drvdata(pdev, drm); ++ ++ dpi->bus_fmt = default_bus_fmt; ++ ret = of_property_read_u32(dev->of_node, "default_bus_fmt", &dpi->bus_fmt); ++ ++ for (i = 0; i < RP1DPI_NUM_HW_BLOCKS; i++) { ++ dpi->hw_base[i] = ++ devm_ioremap_resource(dev, ++ platform_get_resource(dpi->pdev, IORESOURCE_MEM, i)); ++ if (IS_ERR(dpi->hw_base[i])) { ++ ret = PTR_ERR(dpi->hw_base[i]); ++ dev_err(dev, "Error memory mapping regs[%d]\n", i); ++ goto err_free_drm; ++ } ++ } ++ ret = platform_get_irq(dpi->pdev, 0); ++ if (ret > 0) ++ ret = devm_request_irq(dev, ret, rp1dpi_hw_isr, ++ IRQF_SHARED, "rp1-dpi", dpi); ++ if (ret) { ++ dev_err(dev, "Unable to request interrupt\n"); ++ ret = -EINVAL; ++ goto err_free_drm; ++ } ++ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); ++ ++ for (i = 0; i < RP1DPI_NUM_CLOCKS; i++) { ++ static const char * const myclocknames[RP1DPI_NUM_CLOCKS] = { ++ "dpiclk", "plldiv", "pllcore" ++ }; ++ dpi->clocks[i] = devm_clk_get(dev, myclocknames[i]); ++ if (IS_ERR(dpi->clocks[i])) { ++ ret = PTR_ERR(dpi->clocks[i]); ++ goto err_free_drm; ++ } ++ } ++ ++ ret = drmm_mode_config_init(drm); ++ if (ret) ++ goto err_free_drm; ++ ++ drm->mode_config.max_width = 4096; ++ drm->mode_config.max_height = 4096; ++ drm->mode_config.fb_base = 0; ++ drm->mode_config.preferred_depth = 32; ++ drm->mode_config.prefer_shadow = 0; ++ drm->mode_config.prefer_shadow_fbdev = 1; ++ drm->mode_config.quirk_addfb_prefer_host_byte_order = true; ++ drm->mode_config.funcs = &rp1dpi_mode_funcs; ++ drm_vblank_init(drm, 1); ++ ++ ret = drm_simple_display_pipe_init(drm, ++ &dpi->pipe, ++ &rp1dpi_pipe_funcs, ++ rp1dpi_formats, ++ ARRAY_SIZE(rp1dpi_formats), ++ NULL, NULL); ++ if (!ret) ++ ret = drm_simple_display_pipe_attach_bridge(&dpi->pipe, bridge); ++ if (ret) ++ goto err_free_drm; ++ ++ drm_mode_config_reset(drm); ++ ++ ret = drm_dev_register(drm, 0); ++ if (ret) ++ goto err_free_drm; ++ ++ drm_fbdev_generic_setup(drm, 32); ++ ++ dev_info(dev, "%s success\n", __func__); ++ return ret; ++ ++err_free_drm: ++ dev_err(dev, "%s fail %d\n", __func__, ret); ++ drm_dev_put(drm); ++ return ret; ++} ++ ++static int rp1dpi_platform_remove(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ ++ rp1dpi_stopall(drm); ++ drm_dev_unregister(drm); ++ drm_atomic_helper_shutdown(drm); ++ drm_dev_put(drm); ++ ++ return 0; ++} ++ ++static void rp1dpi_platform_shutdown(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ ++ rp1dpi_stopall(drm); ++} ++ ++static const struct of_device_id rp1dpi_of_match[] = { ++ { ++ .compatible = "raspberrypi,rp1dpi", ++ }, ++ { /* sentinel */ }, ++}; ++ ++MODULE_DEVICE_TABLE(of, rp1dpi_of_match); ++ ++static struct platform_driver rp1dpi_platform_driver = { ++ .probe = rp1dpi_platform_probe, ++ .remove = rp1dpi_platform_remove, ++ .shutdown = rp1dpi_platform_shutdown, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = rp1dpi_of_match, ++ }, ++}; ++ ++module_platform_driver(rp1dpi_platform_driver); ++ ++MODULE_AUTHOR("Nick Hollinghurst"); ++MODULE_DESCRIPTION("DRM driver for DPI output on Raspberry Pi RP1"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi.h +@@ -0,0 +1,69 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "drm-rp1-dpi" ++#define DRIVER_NAME "drm-rp1-dpi" ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define RP1DPI_HW_BLOCK_DPI 0 ++#define RP1DPI_HW_BLOCK_CFG 1 ++#define RP1DPI_NUM_HW_BLOCKS 2 ++ ++#define RP1DPI_CLK_DPI 0 ++#define RP1DPI_CLK_PLLDIV 1 ++#define RP1DPI_CLK_PLLCORE 2 ++#define RP1DPI_NUM_CLOCKS 3 ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct rp1_dpi { ++ /* DRM and platform device pointers */ ++ struct drm_device *drm; ++ struct platform_device *pdev; ++ ++ /* Framework and helper objects */ ++ struct drm_simple_display_pipe pipe; ++ struct drm_connector connector; ++ ++ /* Clocks: Video PLL, its primary divider, and DPI clock. */ ++ struct clk *clocks[RP1DPI_NUM_CLOCKS]; ++ ++ /* Block (DPI, VOCFG) base addresses, and current state */ ++ void __iomem *hw_base[RP1DPI_NUM_HW_BLOCKS]; ++ u32 cur_fmt; ++ u32 bus_fmt; ++ bool de_inv, clk_inv; ++ bool dpi_running, pipe_enabled; ++ struct completion finished; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the DPI/DMA block */ ++ ++void rp1dpi_hw_setup(struct rp1_dpi *dpi, ++ u32 in_format, ++ u32 bus_format, ++ bool de_inv, ++ struct drm_display_mode const *mode); ++void rp1dpi_hw_update(struct rp1_dpi *dpi, dma_addr_t addr, u32 offset, u32 stride); ++void rp1dpi_hw_stop(struct rp1_dpi *dpi); ++int rp1dpi_hw_busy(struct rp1_dpi *dpi); ++irqreturn_t rp1dpi_hw_isr(int irq, void *dev); ++void rp1dpi_hw_vblank_ctrl(struct rp1_dpi *dpi, int enable); ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the VIDEO OUT CFG block and check RP1 platform */ ++ ++void rp1dpi_vidout_setup(struct rp1_dpi *dpi, bool drive_negedge); ++void rp1dpi_vidout_poweroff(struct rp1_dpi *dpi); +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_cfg.c +@@ -0,0 +1,510 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DPI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_dpi.h" ++ ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_SEL ++// JTAG access : synchronous ++// Description : Selects source: VEC or DPI ++#define VIDEO_OUT_CFG_SEL_OFFSET 0x00000000 ++#define VIDEO_OUT_CFG_SEL_BITS 0x00000013 ++#define VIDEO_OUT_CFG_SEL_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_PCLK_INV ++// Description : Select dpi_pclk output port polarity inversion. ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_BITS 0x00000010 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_MSB 4 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_LSB 4 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_PAD_MUX ++// Description : VEC 1 DPI 0 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_BITS 0x00000002 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_MSB 1 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_LSB 1 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_VDAC_MUX ++// Description : VEC 1 DPI 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_BITS 0x00000001 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_MSB 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_LSB 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_VDAC_CFG ++// JTAG access : synchronous ++// Description : Configure SNPS VDAC ++#define VIDEO_OUT_CFG_VDAC_CFG_OFFSET 0x00000004 ++#define VIDEO_OUT_CFG_VDAC_CFG_BITS 0x1fffffff ++#define VIDEO_OUT_CFG_VDAC_CFG_RESET 0x0003ffff ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENCTR ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_BITS 0x1c000000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_MSB 28 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_LSB 26 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENSC ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_BITS 0x03800000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_MSB 25 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_LSB 23 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENDAC ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_BITS 0x00700000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_MSB 22 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_LSB 20 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENVBG ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_BITS 0x00080000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_MSB 19 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_LSB 19 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_BITS 0x00040000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_MSB 18 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_LSB 18 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC2GC ++// Description : dac2 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_BITS 0x0003f000 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_MSB 17 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_LSB 12 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC1GC ++// Description : dac1 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_BITS 0x00000fc0 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_MSB 11 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_LSB 6 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC0GC ++// Description : dac0 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_BITS 0x0000003f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_MSB 5 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_LSB 0 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_VDAC_STATUS ++// JTAG access : synchronous ++// Description : Read VDAC status ++#define VIDEO_OUT_CFG_VDAC_STATUS_OFFSET 0x00000008 ++#define VIDEO_OUT_CFG_VDAC_STATUS_BITS 0x00000017 ++#define VIDEO_OUT_CFG_VDAC_STATUS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3 ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_BITS 0x00000010 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_MSB 4 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_LSB 4 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_RESET "-" ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_BITS 0x00000007 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_MSB 2 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_LSB 0 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_MEM_PD ++// JTAG access : synchronous ++// Description : Control memory power down ++#define VIDEO_OUT_CFG_MEM_PD_OFFSET 0x0000000c ++#define VIDEO_OUT_CFG_MEM_PD_BITS 0x00000003 ++#define VIDEO_OUT_CFG_MEM_PD_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_MEM_PD_VEC ++// Description : None ++#define VIDEO_OUT_CFG_MEM_PD_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_BITS 0x00000002 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_MSB 1 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_LSB 1 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_MEM_PD_DPI ++// Description : None ++#define VIDEO_OUT_CFG_MEM_PD_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_BITS 0x00000001 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_MSB 0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_LSB 0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_TEST_OVERRIDE ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_OFFSET 0x00000010 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_BITS 0xffffffff ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_PAD ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_RESET 0x0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_BITS 0x80000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_MSB 31 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_LSB 31 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_RESET 0x0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_BITS 0x40000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_MSB 30 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_LSB 30 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_RESET 0x00000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_BITS 0x3fffffff ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_MSB 29 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_LSB 0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTR ++// JTAG access : synchronous ++// Description : Raw Interrupts ++#define VIDEO_OUT_CFG_INTR_OFFSET 0x00000014 ++#define VIDEO_OUT_CFG_INTR_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTR_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTR_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTR_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTR_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTR_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTR_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTR_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTR_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTR_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTR_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTR_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTR_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTR_VEC_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTE ++// JTAG access : synchronous ++// Description : Interrupt Enable ++#define VIDEO_OUT_CFG_INTE_OFFSET 0x00000018 ++#define VIDEO_OUT_CFG_INTE_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTE_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTE_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTE_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTE_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTE_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTE_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTE_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTE_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTE_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTE_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTE_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTE_VEC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTF ++// JTAG access : synchronous ++// Description : Interrupt Force ++#define VIDEO_OUT_CFG_INTF_OFFSET 0x0000001c ++#define VIDEO_OUT_CFG_INTF_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTF_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTF_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTF_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTF_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTF_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTF_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTF_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTF_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTF_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTF_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTF_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTF_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTF_VEC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTS ++// JTAG access : synchronous ++// Description : Interrupt status after masking & forcing ++#define VIDEO_OUT_CFG_INTS_OFFSET 0x00000020 ++#define VIDEO_OUT_CFG_INTS_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTS_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTS_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTS_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTS_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTS_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTS_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTS_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTS_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTS_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTS_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTS_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTS_VEC_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_BLOCK_ID ++// JTAG access : synchronous ++// Description : Block Identifier ++// Hexadecimal representation of "VOCF" ++#define VIDEO_OUT_CFG_BLOCK_ID_OFFSET 0x00000024 ++#define VIDEO_OUT_CFG_BLOCK_ID_BITS 0xffffffff ++#define VIDEO_OUT_CFG_BLOCK_ID_RESET 0x564f4346 ++#define VIDEO_OUT_CFG_BLOCK_ID_MSB 31 ++#define VIDEO_OUT_CFG_BLOCK_ID_LSB 0 ++#define VIDEO_OUT_CFG_BLOCK_ID_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INSTANCE_ID ++// JTAG access : synchronous ++// Description : Block Instance Identifier ++#define VIDEO_OUT_CFG_INSTANCE_ID_OFFSET 0x00000028 ++#define VIDEO_OUT_CFG_INSTANCE_ID_BITS 0x0000000f ++#define VIDEO_OUT_CFG_INSTANCE_ID_RESET 0x00000000 ++#define VIDEO_OUT_CFG_INSTANCE_ID_MSB 3 ++#define VIDEO_OUT_CFG_INSTANCE_ID_LSB 0 ++#define VIDEO_OUT_CFG_INSTANCE_ID_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_AUTO ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_OFFSET 0x0000002c ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_RESET 0x00000007 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_PARALLEL ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_OFFSET 0x00000030 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_RESET 0x00000006 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_CTRL ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_OFFSET 0x00000034 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_TRIG ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_OFFSET 0x00000038 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_ACCESS "SC" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_ACCESS "SC" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_ACCESS "SC" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_DONE ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_OFFSET 0x0000003c ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_VEC ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_DPI ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_ACCESS "RO" ++// ============================================================================= ++ ++#define CFG_WRITE(reg, val) writel((val), dpi->hw_base[RP1DPI_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++#define CFG_READ(reg) readl(dpi->hw_base[RP1DPI_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++ ++void rp1dpi_vidout_setup(struct rp1_dpi *dpi, bool drive_negedge) ++{ ++ /* ++ * We assume DPI and VEC can't be used at the same time (due to ++ * clashing requirements for PLL_VIDEO, and potentially for VDAC). ++ * We therefore leave VEC memories powered down. ++ */ ++ CFG_WRITE(VIDEO_OUT_CFG_MEM_PD, VIDEO_OUT_CFG_MEM_PD_VEC_BITS); ++ CFG_WRITE(VIDEO_OUT_CFG_TEST_OVERRIDE, ++ VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_BITS); ++ ++ /* DPI->Pads; DPI->VDAC; optionally flip PCLK polarity */ ++ CFG_WRITE(VIDEO_OUT_CFG_SEL, ++ drive_negedge ? VIDEO_OUT_CFG_SEL_PCLK_INV_BITS : 0); ++ ++ /* configure VDAC for 3 channels, bandgap on, 710mV swing */ ++ CFG_WRITE(VIDEO_OUT_CFG_VDAC_CFG, 0); ++ ++ /* enable DPI interrupt */ ++ CFG_WRITE(VIDEO_OUT_CFG_INTE, VIDEO_OUT_CFG_INTE_DPI_BITS); ++} ++ ++void rp1dpi_vidout_poweroff(struct rp1_dpi *dpi) ++{ ++ /* disable DPI interrupt */ ++ CFG_WRITE(VIDEO_OUT_CFG_INTE, 0); ++ ++ /* Ensure VDAC is turned off; power down DPI,VEC memories */ ++ CFG_WRITE(VIDEO_OUT_CFG_VDAC_CFG, 0); ++ CFG_WRITE(VIDEO_OUT_CFG_MEM_PD, VIDEO_OUT_CFG_MEM_PD_BITS); ++} +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-dpi/rp1_dpi_hw.c +@@ -0,0 +1,486 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DPI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_dpi.h" ++ ++// --- DPI DMA REGISTERS --- ++ ++// Control ++#define DPI_DMA_CONTROL 0x0 ++#define DPI_DMA_CONTROL_ARM_SHIFT 0 ++#define DPI_DMA_CONTROL_ARM_MASK BIT(DPI_DMA_CONTROL_ARM_SHIFT) ++#define DPI_DMA_CONTROL_ALIGN16_SHIFT 2 ++#define DPI_DMA_CONTROL_ALIGN16_MASK BIT(DPI_DMA_CONTROL_ALIGN16_SHIFT) ++#define DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT 1 ++#define DPI_DMA_CONTROL_AUTO_REPEAT_MASK BIT(DPI_DMA_CONTROL_AUTO_REPEAT_SHIFT) ++#define DPI_DMA_CONTROL_HIGH_WATER_SHIFT 3 ++#define DPI_DMA_CONTROL_HIGH_WATER_MASK (0x1FF << DPI_DMA_CONTROL_HIGH_WATER_SHIFT) ++#define DPI_DMA_CONTROL_DEN_POL_SHIFT 12 ++#define DPI_DMA_CONTROL_DEN_POL_MASK BIT(DPI_DMA_CONTROL_DEN_POL_SHIFT) ++#define DPI_DMA_CONTROL_HSYNC_POL_SHIFT 13 ++#define DPI_DMA_CONTROL_HSYNC_POL_MASK BIT(DPI_DMA_CONTROL_HSYNC_POL_SHIFT) ++#define DPI_DMA_CONTROL_VSYNC_POL_SHIFT 14 ++#define DPI_DMA_CONTROL_VSYNC_POL_MASK BIT(DPI_DMA_CONTROL_VSYNC_POL_SHIFT) ++#define DPI_DMA_CONTROL_COLORM_SHIFT 15 ++#define DPI_DMA_CONTROL_COLORM_MASK BIT(DPI_DMA_CONTROL_COLORM_SHIFT) ++#define DPI_DMA_CONTROL_SHUTDN_SHIFT 16 ++#define DPI_DMA_CONTROL_SHUTDN_MASK BIT(DPI_DMA_CONTROL_SHUTDN_SHIFT) ++#define DPI_DMA_CONTROL_HBP_EN_SHIFT 17 ++#define DPI_DMA_CONTROL_HBP_EN_MASK BIT(DPI_DMA_CONTROL_HBP_EN_SHIFT) ++#define DPI_DMA_CONTROL_HFP_EN_SHIFT 18 ++#define DPI_DMA_CONTROL_HFP_EN_MASK BIT(DPI_DMA_CONTROL_HFP_EN_SHIFT) ++#define DPI_DMA_CONTROL_VBP_EN_SHIFT 19 ++#define DPI_DMA_CONTROL_VBP_EN_MASK BIT(DPI_DMA_CONTROL_VBP_EN_SHIFT) ++#define DPI_DMA_CONTROL_VFP_EN_SHIFT 20 ++#define DPI_DMA_CONTROL_VFP_EN_MASK BIT(DPI_DMA_CONTROL_VFP_EN_SHIFT) ++#define DPI_DMA_CONTROL_HSYNC_EN_SHIFT 21 ++#define DPI_DMA_CONTROL_HSYNC_EN_MASK BIT(DPI_DMA_CONTROL_HSYNC_EN_SHIFT) ++#define DPI_DMA_CONTROL_VSYNC_EN_SHIFT 22 ++#define DPI_DMA_CONTROL_VSYNC_EN_MASK BIT(DPI_DMA_CONTROL_VSYNC_EN_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_IMMED_SHIFT 23 ++#define DPI_DMA_CONTROL_FORCE_IMMED_MASK BIT(DPI_DMA_CONTROL_FORCE_IMMED_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT 24 ++#define DPI_DMA_CONTROL_FORCE_DRAIN_MASK BIT(DPI_DMA_CONTROL_FORCE_DRAIN_SHIFT) ++#define DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT 25 ++#define DPI_DMA_CONTROL_FORCE_EMPTY_MASK BIT(DPI_DMA_CONTROL_FORCE_EMPTY_SHIFT) ++ ++// IRQ_ENABLES ++#define DPI_DMA_IRQ_EN 0x04 ++#define DPI_DMA_IRQ_EN_DMA_READY_SHIFT 0 ++#define DPI_DMA_IRQ_EN_DMA_READY_MASK BIT(DPI_DMA_IRQ_EN_DMA_READY_SHIFT) ++#define DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT 1 ++#define DPI_DMA_IRQ_EN_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_EN_UNDERFLOW_SHIFT) ++#define DPI_DMA_IRQ_EN_FRAME_START_SHIFT 2 ++#define DPI_DMA_IRQ_EN_FRAME_START_MASK BIT(DPI_DMA_IRQ_EN_FRAME_START_SHIFT) ++#define DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT 3 ++#define DPI_DMA_IRQ_EN_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_EN_AFIFO_EMPTY_SHIFT) ++#define DPI_DMA_IRQ_EN_TE_SHIFT 4 ++#define DPI_DMA_IRQ_EN_TE_MASK BIT(DPI_DMA_IRQ_EN_TE_SHIFT) ++#define DPI_DMA_IRQ_EN_ERROR_SHIFT 5 ++#define DPI_DMA_IRQ_EN_ERROR_MASK BIT(DPI_DMA_IRQ_EN_ERROR_SHIFT) ++#define DPI_DMA_IRQ_EN_MATCH_SHIFT 6 ++#define DPI_DMA_IRQ_EN_MATCH_MASK BIT(DPI_DMA_IRQ_EN_MATCH_SHIFT) ++#define DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT 16 ++#define DPI_DMA_IRQ_EN_MATCH_LINE_MASK (0xFFF << DPI_DMA_IRQ_EN_MATCH_LINE_SHIFT) ++ ++// IRQ_FLAGS ++#define DPI_DMA_IRQ_FLAGS 0x08 ++#define DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT 0 ++#define DPI_DMA_IRQ_FLAGS_DMA_READY_MASK BIT(DPI_DMA_IRQ_FLAGS_DMA_READY_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT 1 ++#define DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK BIT(DPI_DMA_IRQ_FLAGS_UNDERFLOW_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT 2 ++#define DPI_DMA_IRQ_FLAGS_FRAME_START_MASK BIT(DPI_DMA_IRQ_FLAGS_FRAME_START_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT 3 ++#define DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK BIT(DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_TE_SHIFT 4 ++#define DPI_DMA_IRQ_FLAGS_TE_MASK BIT(DPI_DMA_IRQ_FLAGS_TE_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_ERROR_SHIFT 5 ++#define DPI_DMA_IRQ_FLAGS_ERROR_MASK BIT(DPI_DMA_IRQ_FLAGS_ERROR_SHIFT) ++#define DPI_DMA_IRQ_FLAGS_MATCH_SHIFT 6 ++#define DPI_DMA_IRQ_FLAGS_MATCH_MASK BIT(DPI_DMA_IRQ_FLAGS_MATCH_SHIFT) ++ ++// QOS ++#define DPI_DMA_QOS 0xC ++#define DPI_DMA_QOS_DQOS_SHIFT 0 ++#define DPI_DMA_QOS_DQOS_MASK (0xF << DPI_DMA_QOS_DQOS_SHIFT) ++#define DPI_DMA_QOS_ULEV_SHIFT 4 ++#define DPI_DMA_QOS_ULEV_MASK (0xF << DPI_DMA_QOS_ULEV_SHIFT) ++#define DPI_DMA_QOS_UQOS_SHIFT 8 ++#define DPI_DMA_QOS_UQOS_MASK (0xF << DPI_DMA_QOS_UQOS_SHIFT) ++#define DPI_DMA_QOS_LLEV_SHIFT 12 ++#define DPI_DMA_QOS_LLEV_MASK (0xF << DPI_DMA_QOS_LLEV_SHIFT) ++#define DPI_DMA_QOS_LQOS_SHIFT 16 ++#define DPI_DMA_QOS_LQOS_MASK (0xF << DPI_DMA_QOS_LQOS_SHIFT) ++ ++// Panics ++#define DPI_DMA_PANICS 0x38 ++#define DPI_DMA_PANICS_UPPER_COUNT_SHIFT 0 ++#define DPI_DMA_PANICS_UPPER_COUNT_MASK \ ++ (0x0000FFFF << DPI_DMA_PANICS_UPPER_COUNT_SHIFT) ++#define DPI_DMA_PANICS_LOWER_COUNT_SHIFT 16 ++#define DPI_DMA_PANICS_LOWER_COUNT_MASK \ ++ (0x0000FFFF << DPI_DMA_PANICS_LOWER_COUNT_SHIFT) ++ ++// DMA Address Lower: ++#define DPI_DMA_DMA_ADDR_L 0x10 ++ ++// DMA Address Upper: ++#define DPI_DMA_DMA_ADDR_H 0x40 ++ ++// DMA stride ++#define DPI_DMA_DMA_STRIDE 0x14 ++ ++// Visible Area ++#define DPI_DMA_VISIBLE_AREA 0x18 ++#define DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT 0 ++#define DPI_DMA_VISIBLE_AREA_ROWSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_ROWSM1_SHIFT) ++#define DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT 16 ++#define DPI_DMA_VISIBLE_AREA_COLSM1_MASK (0x0FFF << DPI_DMA_VISIBLE_AREA_COLSM1_SHIFT) ++ ++// Sync width ++#define DPI_DMA_SYNC_WIDTH 0x1C ++#define DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT 0 ++#define DPI_DMA_SYNC_WIDTH_ROWSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_ROWSM1_SHIFT) ++#define DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT 16 ++#define DPI_DMA_SYNC_WIDTH_COLSM1_MASK (0x0FFF << DPI_DMA_SYNC_WIDTH_COLSM1_SHIFT) ++ ++// Back porch ++#define DPI_DMA_BACK_PORCH 0x20 ++#define DPI_DMA_BACK_PORCH_ROWSM1_SHIFT 0 ++#define DPI_DMA_BACK_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_ROWSM1_SHIFT) ++#define DPI_DMA_BACK_PORCH_COLSM1_SHIFT 16 ++#define DPI_DMA_BACK_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_BACK_PORCH_COLSM1_SHIFT) ++ ++// Front porch ++#define DPI_DMA_FRONT_PORCH 0x24 ++#define DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT 0 ++#define DPI_DMA_FRONT_PORCH_ROWSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_ROWSM1_SHIFT) ++#define DPI_DMA_FRONT_PORCH_COLSM1_SHIFT 16 ++#define DPI_DMA_FRONT_PORCH_COLSM1_MASK (0x0FFF << DPI_DMA_FRONT_PORCH_COLSM1_SHIFT) ++ ++// Input masks ++#define DPI_DMA_IMASK 0x2C ++#define DPI_DMA_IMASK_R_SHIFT 0 ++#define DPI_DMA_IMASK_R_MASK (0x3FF << DPI_DMA_IMASK_R_SHIFT) ++#define DPI_DMA_IMASK_G_SHIFT 10 ++#define DPI_DMA_IMASK_G_MASK (0x3FF << DPI_DMA_IMASK_G_SHIFT) ++#define DPI_DMA_IMASK_B_SHIFT 20 ++#define DPI_DMA_IMASK_B_MASK (0x3FF << DPI_DMA_IMASK_B_SHIFT) ++ ++// Output Masks ++#define DPI_DMA_OMASK 0x30 ++#define DPI_DMA_OMASK_R_SHIFT 0 ++#define DPI_DMA_OMASK_R_MASK (0x3FF << DPI_DMA_OMASK_R_SHIFT) ++#define DPI_DMA_OMASK_G_SHIFT 10 ++#define DPI_DMA_OMASK_G_MASK (0x3FF << DPI_DMA_OMASK_G_SHIFT) ++#define DPI_DMA_OMASK_B_SHIFT 20 ++#define DPI_DMA_OMASK_B_MASK (0x3FF << DPI_DMA_OMASK_B_SHIFT) ++ ++// Shifts ++#define DPI_DMA_SHIFT 0x28 ++#define DPI_DMA_SHIFT_IR_SHIFT 0 ++#define DPI_DMA_SHIFT_IR_MASK (0x1F << DPI_DMA_SHIFT_IR_SHIFT) ++#define DPI_DMA_SHIFT_IG_SHIFT 5 ++#define DPI_DMA_SHIFT_IG_MASK (0x1F << DPI_DMA_SHIFT_IG_SHIFT) ++#define DPI_DMA_SHIFT_IB_SHIFT 10 ++#define DPI_DMA_SHIFT_IB_MASK (0x1F << DPI_DMA_SHIFT_IB_SHIFT) ++#define DPI_DMA_SHIFT_OR_SHIFT 15 ++#define DPI_DMA_SHIFT_OR_MASK (0x1F << DPI_DMA_SHIFT_OR_SHIFT) ++#define DPI_DMA_SHIFT_OG_SHIFT 20 ++#define DPI_DMA_SHIFT_OG_MASK (0x1F << DPI_DMA_SHIFT_OG_SHIFT) ++#define DPI_DMA_SHIFT_OB_SHIFT 25 ++#define DPI_DMA_SHIFT_OB_MASK (0x1F << DPI_DMA_SHIFT_OB_SHIFT) ++ ++// Scaling ++#define DPI_DMA_RGBSZ 0x34 ++#define DPI_DMA_RGBSZ_BPP_SHIFT 16 ++#define DPI_DMA_RGBSZ_BPP_MASK (0x3 << DPI_DMA_RGBSZ_BPP_SHIFT) ++#define DPI_DMA_RGBSZ_R_SHIFT 0 ++#define DPI_DMA_RGBSZ_R_MASK (0xF << DPI_DMA_RGBSZ_R_SHIFT) ++#define DPI_DMA_RGBSZ_G_SHIFT 4 ++#define DPI_DMA_RGBSZ_G_MASK (0xF << DPI_DMA_RGBSZ_G_SHIFT) ++#define DPI_DMA_RGBSZ_B_SHIFT 8 ++#define DPI_DMA_RGBSZ_B_MASK (0xF << DPI_DMA_RGBSZ_B_SHIFT) ++ ++// Status ++#define DPI_DMA_STATUS 0x3c ++ ++#define BITS(field, val) (((val) << (field ## _SHIFT)) & (field ## _MASK)) ++ ++static unsigned int rp1dpi_hw_read(struct rp1_dpi *dpi, unsigned int reg) ++{ ++ void __iomem *addr = dpi->hw_base[RP1DPI_HW_BLOCK_DPI] + reg; ++ ++ return readl(addr); ++} ++ ++static void rp1dpi_hw_write(struct rp1_dpi *dpi, unsigned int reg, unsigned int val) ++{ ++ void __iomem *addr = dpi->hw_base[RP1DPI_HW_BLOCK_DPI] + reg; ++ ++ writel(val, addr); ++} ++ ++int rp1dpi_hw_busy(struct rp1_dpi *dpi) ++{ ++ return (rp1dpi_hw_read(dpi, DPI_DMA_STATUS) & 0xF8F) ? 1 : 0; ++} ++ ++/* Table of supported input (in-memory/DMA) pixel formats. */ ++struct rp1dpi_ipixfmt { ++ u32 format; /* DRM format code */ ++ u32 mask; /* RGB masks (10 bits each, left justified) */ ++ u32 shift; /* RGB MSB positions in the memory word */ ++ u32 rgbsz; /* Shifts used for scaling; also (BPP/8-1) */ ++}; ++ ++#define IMASK_RGB(r, g, b) (BITS(DPI_DMA_IMASK_R, r) | \ ++ BITS(DPI_DMA_IMASK_G, g) | \ ++ BITS(DPI_DMA_IMASK_B, b)) ++#define OMASK_RGB(r, g, b) (BITS(DPI_DMA_OMASK_R, r) | \ ++ BITS(DPI_DMA_OMASK_G, g) | \ ++ BITS(DPI_DMA_OMASK_B, b)) ++#define ISHIFT_RGB(r, g, b) (BITS(DPI_DMA_SHIFT_IR, r) | \ ++ BITS(DPI_DMA_SHIFT_IG, g) | \ ++ BITS(DPI_DMA_SHIFT_IB, b)) ++#define OSHIFT_RGB(r, g, b) (BITS(DPI_DMA_SHIFT_OR, r) | \ ++ BITS(DPI_DMA_SHIFT_OG, g) | \ ++ BITS(DPI_DMA_SHIFT_OB, b)) ++ ++static const struct rp1dpi_ipixfmt my_formats[] = { ++ { ++ .format = DRM_FORMAT_XRGB8888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3), ++ }, ++ { ++ .format = DRM_FORMAT_XBGR8888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 3), ++ }, ++ { ++ .format = DRM_FORMAT_RGB888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2), ++ }, ++ { ++ .format = DRM_FORMAT_BGR888, ++ .mask = IMASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = ISHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_BPP, 2), ++ }, ++ { ++ .format = DRM_FORMAT_RGB565, ++ .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0), ++ .shift = ISHIFT_RGB(15, 10, 4), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_R, 5) | BITS(DPI_DMA_RGBSZ_G, 6) | ++ BITS(DPI_DMA_RGBSZ_B, 5) | BITS(DPI_DMA_RGBSZ_BPP, 1), ++ }, ++ { ++ .format = DRM_FORMAT_BGR565, ++ .mask = IMASK_RGB(0x3e0, 0x3f0, 0x3e0), ++ .shift = ISHIFT_RGB(4, 10, 15), ++ .rgbsz = BITS(DPI_DMA_RGBSZ_R, 5) | BITS(DPI_DMA_RGBSZ_G, 6) | ++ BITS(DPI_DMA_RGBSZ_B, 5) | BITS(DPI_DMA_RGBSZ_BPP, 1), ++ } ++}; ++ ++static u32 set_output_format(u32 bus_format, u32 *shift, u32 *imask, u32 *rgbsz) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_RGB565_1X16: ++ if (*shift == ISHIFT_RGB(15, 10, 4)) { ++ /* When framebuffer is RGB565, we can output RGB565 */ ++ *shift = ISHIFT_RGB(15, 7, 0) | OSHIFT_RGB(19, 9, 0); ++ *rgbsz &= DPI_DMA_RGBSZ_BPP_MASK; ++ return OMASK_RGB(0x3fc, 0x3fc, 0); ++ } ++ ++ /* due to a HW limitation, bit-depth is effectively RGB535 */ ++ *shift |= OSHIFT_RGB(19, 14, 6); ++ *imask &= IMASK_RGB(0x3e0, 0x380, 0x3e0); ++ *rgbsz = BITS(DPI_DMA_RGBSZ_G, 5) | (*rgbsz & DPI_DMA_RGBSZ_BPP_MASK); ++ return OMASK_RGB(0x3e0, 0x39c, 0x3e0); ++ ++ case MEDIA_BUS_FMT_RGB666_1X18: ++ case MEDIA_BUS_FMT_BGR666_1X18: ++ /* due to a HW limitation, bit-depth is effectively RGB444 */ ++ *shift |= OSHIFT_RGB(23, 15, 7); ++ *imask &= IMASK_RGB(0x3c0, 0x3c0, 0x3c0); ++ *rgbsz = BITS(DPI_DMA_RGBSZ_R, 2) | (*rgbsz & DPI_DMA_RGBSZ_BPP_MASK); ++ return OMASK_RGB(0x330, 0x3c0, 0x3c0); ++ ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ case MEDIA_BUS_FMT_BGR888_1X24: ++ case MEDIA_BUS_FMT_RGB101010_1X30: ++ /* The full 24 bits can be output. Note that RP1's internal wiring means ++ * that 8.8.8 to GPIO pads can share with 10.10.10 to the onboard VDAC. ++ */ ++ *shift |= OSHIFT_RGB(29, 19, 9); ++ return OMASK_RGB(0x3fc, 0x3fc, 0x3fc); ++ ++ default: ++ /* RGB666_1x24_CPADHI, BGR666_1X24_CPADHI and "RGB565_666" formats */ ++ *shift |= OSHIFT_RGB(27, 17, 7); ++ *rgbsz &= DPI_DMA_RGBSZ_BPP_MASK; ++ return OMASK_RGB(0x3f0, 0x3f0, 0x3f0); ++ } ++} ++ ++#define BUS_FMT_IS_BGR(fmt) ( \ ++ ((fmt) == MEDIA_BUS_FMT_BGR666_1X18) || \ ++ ((fmt) == MEDIA_BUS_FMT_BGR666_1X24_CPADHI) || \ ++ ((fmt) == MEDIA_BUS_FMT_BGR888_1X24)) ++ ++void rp1dpi_hw_setup(struct rp1_dpi *dpi, ++ u32 in_format, u32 bus_format, bool de_inv, ++ struct drm_display_mode const *mode) ++{ ++ u32 shift, imask, omask, rgbsz; ++ int i; ++ ++ pr_info("%s: in_fmt=\'%c%c%c%c\' bus_fmt=0x%x mode=%dx%d total=%dx%d %dkHz %cH%cV%cD%cC", ++ __func__, in_format, in_format >> 8, in_format >> 16, in_format >> 24, bus_format, ++ mode->hdisplay, mode->vdisplay, ++ mode->htotal, mode->vtotal, ++ mode->clock, ++ (mode->flags & DRM_MODE_FLAG_NHSYNC) ? '-' : '+', ++ (mode->flags & DRM_MODE_FLAG_NVSYNC) ? '-' : '+', ++ de_inv ? '-' : '+', ++ dpi->clk_inv ? '-' : '+'); ++ ++ /* ++ * Configure all DPI/DMA block registers, except base address. ++ * DMA will not actually start until a FB base address is specified ++ * using rp1dpi_hw_update(). ++ */ ++ rp1dpi_hw_write(dpi, DPI_DMA_VISIBLE_AREA, ++ BITS(DPI_DMA_VISIBLE_AREA_ROWSM1, mode->vdisplay - 1) | ++ BITS(DPI_DMA_VISIBLE_AREA_COLSM1, mode->hdisplay - 1)); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_SYNC_WIDTH, ++ BITS(DPI_DMA_SYNC_WIDTH_ROWSM1, mode->vsync_end - mode->vsync_start - 1) | ++ BITS(DPI_DMA_SYNC_WIDTH_COLSM1, mode->hsync_end - mode->hsync_start - 1)); ++ ++ /* In these registers, "back porch" time includes sync width */ ++ rp1dpi_hw_write(dpi, DPI_DMA_BACK_PORCH, ++ BITS(DPI_DMA_BACK_PORCH_ROWSM1, mode->vtotal - mode->vsync_start - 1) | ++ BITS(DPI_DMA_BACK_PORCH_COLSM1, mode->htotal - mode->hsync_start - 1)); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_FRONT_PORCH, ++ BITS(DPI_DMA_FRONT_PORCH_ROWSM1, mode->vsync_start - mode->vdisplay - 1) | ++ BITS(DPI_DMA_FRONT_PORCH_COLSM1, mode->hsync_start - mode->hdisplay - 1)); ++ ++ /* Input to output pixel format conversion */ ++ for (i = 0; i < ARRAY_SIZE(my_formats); ++i) { ++ if (my_formats[i].format == in_format) ++ break; ++ } ++ if (i >= ARRAY_SIZE(my_formats)) { ++ pr_err("%s: bad input format\n", __func__); ++ i = 4; ++ } ++ if (BUS_FMT_IS_BGR(bus_format)) ++ i ^= 1; ++ shift = my_formats[i].shift; ++ imask = my_formats[i].mask; ++ rgbsz = my_formats[i].rgbsz; ++ omask = set_output_format(bus_format, &shift, &imask, &rgbsz); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_IMASK, imask); ++ rp1dpi_hw_write(dpi, DPI_DMA_OMASK, omask); ++ rp1dpi_hw_write(dpi, DPI_DMA_SHIFT, shift); ++ rp1dpi_hw_write(dpi, DPI_DMA_RGBSZ, rgbsz); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_QOS, ++ BITS(DPI_DMA_QOS_DQOS, 0x0) | ++ BITS(DPI_DMA_QOS_ULEV, 0xb) | ++ BITS(DPI_DMA_QOS_UQOS, 0x2) | ++ BITS(DPI_DMA_QOS_LLEV, 0x8) | ++ BITS(DPI_DMA_QOS_LQOS, 0x7)); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_IRQ_FLAGS, -1); ++ rp1dpi_hw_vblank_ctrl(dpi, 1); ++ ++ i = rp1dpi_hw_busy(dpi); ++ if (i) ++ pr_warn("%s: Unexpectedly busy at start!", __func__); ++ ++ rp1dpi_hw_write(dpi, DPI_DMA_CONTROL, ++ BITS(DPI_DMA_CONTROL_ARM, !i) | ++ BITS(DPI_DMA_CONTROL_AUTO_REPEAT, 1) | ++ BITS(DPI_DMA_CONTROL_HIGH_WATER, 448) | ++ BITS(DPI_DMA_CONTROL_DEN_POL, de_inv) | ++ BITS(DPI_DMA_CONTROL_HSYNC_POL, !!(mode->flags & DRM_MODE_FLAG_NHSYNC)) | ++ BITS(DPI_DMA_CONTROL_VSYNC_POL, !!(mode->flags & DRM_MODE_FLAG_NVSYNC)) | ++ BITS(DPI_DMA_CONTROL_COLORM, 0) | ++ BITS(DPI_DMA_CONTROL_SHUTDN, 0) | ++ BITS(DPI_DMA_CONTROL_HBP_EN, (mode->htotal != mode->hsync_end)) | ++ BITS(DPI_DMA_CONTROL_HFP_EN, (mode->hsync_start != mode->hdisplay)) | ++ BITS(DPI_DMA_CONTROL_VBP_EN, (mode->vtotal != mode->vsync_end)) | ++ BITS(DPI_DMA_CONTROL_VFP_EN, (mode->vsync_start != mode->vdisplay)) | ++ BITS(DPI_DMA_CONTROL_HSYNC_EN, (mode->hsync_end != mode->hsync_start)) | ++ BITS(DPI_DMA_CONTROL_VSYNC_EN, (mode->vsync_end != mode->vsync_start))); ++} ++ ++void rp1dpi_hw_update(struct rp1_dpi *dpi, dma_addr_t addr, u32 offset, u32 stride) ++{ ++ u64 a = addr + offset; ++ ++ /* ++ * Update STRIDE, DMAH and DMAL only. When called after rp1dpi_hw_setup(), ++ * DMA starts immediately; if already running, the buffer will flip at ++ * the next vertical sync event. ++ */ ++ rp1dpi_hw_write(dpi, DPI_DMA_DMA_STRIDE, stride); ++ rp1dpi_hw_write(dpi, DPI_DMA_DMA_ADDR_H, a >> 32); ++ rp1dpi_hw_write(dpi, DPI_DMA_DMA_ADDR_L, a & 0xFFFFFFFFu); ++} ++ ++void rp1dpi_hw_stop(struct rp1_dpi *dpi) ++{ ++ u32 ctrl; ++ ++ /* ++ * Stop DMA by turning off the Auto-Repeat flag, and wait up to 100ms for ++ * the current and any queued frame to end. "Force drain" flags are not used, ++ * as they seem to prevent DMA from re-starting properly; it's safer to wait. ++ */ ++ reinit_completion(&dpi->finished); ++ ctrl = rp1dpi_hw_read(dpi, DPI_DMA_CONTROL); ++ ctrl &= ~(DPI_DMA_CONTROL_ARM_MASK | DPI_DMA_CONTROL_AUTO_REPEAT_MASK); ++ rp1dpi_hw_write(dpi, DPI_DMA_CONTROL, ctrl); ++ if (!wait_for_completion_timeout(&dpi->finished, HZ / 10)) ++ drm_err(dpi->drm, "%s: timed out waiting for idle\n", __func__); ++ rp1dpi_hw_write(dpi, DPI_DMA_IRQ_EN, 0); ++} ++ ++void rp1dpi_hw_vblank_ctrl(struct rp1_dpi *dpi, int enable) ++{ ++ rp1dpi_hw_write(dpi, DPI_DMA_IRQ_EN, ++ BITS(DPI_DMA_IRQ_EN_AFIFO_EMPTY, 1) | ++ BITS(DPI_DMA_IRQ_EN_UNDERFLOW, 1) | ++ BITS(DPI_DMA_IRQ_EN_DMA_READY, !!enable) | ++ BITS(DPI_DMA_IRQ_EN_MATCH_LINE, 4095)); ++} ++ ++irqreturn_t rp1dpi_hw_isr(int irq, void *dev) ++{ ++ struct rp1_dpi *dpi = dev; ++ u32 u = rp1dpi_hw_read(dpi, DPI_DMA_IRQ_FLAGS); ++ ++ if (u) { ++ rp1dpi_hw_write(dpi, DPI_DMA_IRQ_FLAGS, u); ++ if (dpi) { ++ if (u & DPI_DMA_IRQ_FLAGS_UNDERFLOW_MASK) ++ drm_err_ratelimited(dpi->drm, ++ "Underflow! (panics=0x%08x)\n", ++ rp1dpi_hw_read(dpi, DPI_DMA_PANICS)); ++ if (u & DPI_DMA_IRQ_FLAGS_DMA_READY_MASK) ++ drm_crtc_handle_vblank(&dpi->pipe.crtc); ++ if (u & DPI_DMA_IRQ_FLAGS_AFIFO_EMPTY_MASK) ++ complete(&dpi->finished); ++ } ++ } ++ return u ? IRQ_HANDLED : IRQ_NONE; ++} diff --git a/target/linux/bcm27xx/patches-6.1/950-0887-drm-Add-RP1-VEC-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0887-drm-Add-RP1-VEC-driver.patch new file mode 100644 index 0000000000..5bf657ab24 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0887-drm-Add-RP1-VEC-driver.patch @@ -0,0 +1,3078 @@ +From 09c2c6aad0fed44182defecd274579770feb0ae2 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Tue, 19 Sep 2023 17:54:41 +0100 +Subject: [PATCH] drm: Add RP1 VEC driver + +Add support for the RP1 VEC hardware. + +Signed-off-by: Nick Hollinghurst +--- + drivers/gpu/drm/rp1/rp1-vec/Kconfig | 12 + + drivers/gpu/drm/rp1/rp1-vec/Makefile | 5 + + drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c | 539 ++++++++ + drivers/gpu/drm/rp1/rp1-vec/rp1_vec.h | 79 ++ + drivers/gpu/drm/rp1/rp1-vec/rp1_vec_cfg.c | 508 ++++++++ + drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c | 469 +++++++ + drivers/gpu/drm/rp1/rp1-vec/vec_regs.h | 1420 +++++++++++++++++++++ + 7 files changed, 3032 insertions(+) + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/Kconfig + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/Makefile + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/rp1_vec.h + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/rp1_vec_cfg.c + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c + create mode 100644 drivers/gpu/drm/rp1/rp1-vec/vec_regs.h + +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/Kconfig +@@ -0,0 +1,12 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config DRM_RP1_VEC ++ tristate "DRM Support for RP1 VEC" ++ depends on DRM ++ select MFD_RP1 ++ select DRM_GEM_DMA_HELPER ++ select DRM_KMS_HELPER ++ select DRM_VRAM_HELPER ++ select DRM_TTM ++ select DRM_TTM_HELPER ++ help ++ Choose this option to enable Video Out on RP1 +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/Makefile +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++drm-rp1-vec-y := rp1_vec.o rp1_vec_hw.o rp1_vec_cfg.o ++ ++obj-$(CONFIG_DRM_RP1_VEC) += drm-rp1-vec.o +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c +@@ -0,0 +1,539 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for VEC output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_vec.h" ++ ++/* ++ * Default TV standard parameter; it may be overridden by the OF ++ * property "tv_norm" (which should be one of the strings below). ++ * ++ * The default (empty string) supports various 60Hz and 50Hz modes, ++ * and will automatically select NTSC[-M] or PAL[-BDGHIKL]; the two ++ * "fake" 60Hz standards NTSC-443 and PAL60 also support 50Hz PAL. ++ * Other values will restrict the set of video modes offered. ++ * ++ * Finally, the DRM connector property "mode" (which is an integer) ++ * can be used to override this value, but it does not prevent the ++ * selection of an inapplicable video mode. ++ */ ++ ++static char *rp1vec_tv_norm_str; ++module_param_named(tv_norm, rp1vec_tv_norm_str, charp, 0600); ++MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" ++ "\t\tSupported: NTSC, NTSC-J, NTSC-443, PAL, PAL-M, PAL-N,\n" ++ "\t\t\tPAL60.\n" ++ "\t\tDefault: empty string: infer PAL for a 50 Hz mode,\n" ++ "\t\t\tNTSC otherwise"); ++ ++const char * const rp1vec_tvstd_names[] = { ++ [RP1VEC_TVSTD_NTSC] = "NTSC", ++ [RP1VEC_TVSTD_NTSC_J] = "NTSC-J", ++ [RP1VEC_TVSTD_NTSC_443] = "NTSC-443", ++ [RP1VEC_TVSTD_PAL] = "PAL", ++ [RP1VEC_TVSTD_PAL_M] = "PAL-M", ++ [RP1VEC_TVSTD_PAL_N] = "PAL-N", ++ [RP1VEC_TVSTD_PAL60] = "PAL60", ++ [RP1VEC_TVSTD_DEFAULT] = "", ++}; ++ ++static int rp1vec_parse_tv_norm(const char *str) ++{ ++ int i; ++ ++ if (str && *str) { ++ for (i = 0; i < ARRAY_SIZE(rp1vec_tvstd_names); ++i) { ++ if (strcasecmp(str, rp1vec_tvstd_names[i]) == 0) ++ return i; ++ } ++ } ++ return RP1VEC_TVSTD_DEFAULT; ++} ++ ++static void rp1vec_pipe_update(struct drm_simple_display_pipe *pipe, ++ struct drm_plane_state *old_state) ++{ ++ struct drm_pending_vblank_event *event; ++ unsigned long flags; ++ struct drm_framebuffer *fb = pipe->plane.state->fb; ++ struct rp1_vec *vec = pipe->crtc.dev->dev_private; ++ struct drm_gem_object *gem = fb ? drm_gem_fb_get_obj(fb, 0) : NULL; ++ struct drm_gem_dma_object *dma_obj = gem ? to_drm_gem_dma_obj(gem) : NULL; ++ bool can_update = fb && dma_obj && vec && vec->pipe_enabled; ++ ++ /* (Re-)start VEC where required; and update FB address */ ++ if (can_update) { ++ if (!vec->vec_running || fb->format->format != vec->cur_fmt) { ++ if (vec->vec_running && fb->format->format != vec->cur_fmt) { ++ rp1vec_hw_stop(vec); ++ vec->vec_running = false; ++ } ++ if (!vec->vec_running) { ++ rp1vec_hw_setup(vec, ++ fb->format->format, ++ &pipe->crtc.state->mode, ++ vec->connector.state->tv.mode); ++ vec->vec_running = true; ++ } ++ vec->cur_fmt = fb->format->format; ++ drm_crtc_vblank_on(&pipe->crtc); ++ } ++ rp1vec_hw_update(vec, dma_obj->dma_addr, fb->offsets[0], fb->pitches[0]); ++ } ++ ++ /* Check if VBLANK callback needs to be armed (or sent immediately in some error cases). ++ * Note there is a tiny probability of a race between rp1vec_dma_update() and IRQ; ++ * ordering it this way around is safe, but theoretically might delay an extra frame. ++ */ ++ spin_lock_irqsave(&pipe->crtc.dev->event_lock, flags); ++ event = pipe->crtc.state->event; ++ if (event) { ++ pipe->crtc.state->event = NULL; ++ if (can_update && drm_crtc_vblank_get(&pipe->crtc) == 0) ++ drm_crtc_arm_vblank_event(&pipe->crtc, event); ++ else ++ drm_crtc_send_vblank_event(&pipe->crtc, event); ++ } ++ spin_unlock_irqrestore(&pipe->crtc.dev->event_lock, flags); ++} ++ ++static void rp1vec_pipe_enable(struct drm_simple_display_pipe *pipe, ++ struct drm_crtc_state *crtc_state, ++ struct drm_plane_state *plane_state) ++{ ++ struct rp1_vec *vec = pipe->crtc.dev->dev_private; ++ ++ dev_info(&vec->pdev->dev, __func__); ++ vec->pipe_enabled = true; ++ vec->cur_fmt = 0xdeadbeef; ++ rp1vec_vidout_setup(vec); ++ rp1vec_pipe_update(pipe, 0); ++} ++ ++static void rp1vec_pipe_disable(struct drm_simple_display_pipe *pipe) ++{ ++ struct rp1_vec *vec = pipe->crtc.dev->dev_private; ++ ++ dev_info(&vec->pdev->dev, __func__); ++ drm_crtc_vblank_off(&pipe->crtc); ++ if (vec) { ++ if (vec->vec_running) { ++ rp1vec_hw_stop(vec); ++ vec->vec_running = false; ++ } ++ vec->pipe_enabled = false; ++ } ++} ++ ++static int rp1vec_pipe_enable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ if (pipe && pipe->crtc.dev) { ++ struct rp1_vec *vec = pipe->crtc.dev->dev_private; ++ ++ if (vec) ++ rp1vec_hw_vblank_ctrl(vec, 1); ++ } ++ return 0; ++} ++ ++static void rp1vec_pipe_disable_vblank(struct drm_simple_display_pipe *pipe) ++{ ++ if (pipe && pipe->crtc.dev) { ++ struct rp1_vec *vec = pipe->crtc.dev->dev_private; ++ ++ if (vec) ++ rp1vec_hw_vblank_ctrl(vec, 0); ++ } ++} ++ ++static const struct drm_simple_display_pipe_funcs rp1vec_pipe_funcs = { ++ .enable = rp1vec_pipe_enable, ++ .update = rp1vec_pipe_update, ++ .disable = rp1vec_pipe_disable, ++ .prepare_fb = drm_gem_simple_display_pipe_prepare_fb, ++ .enable_vblank = rp1vec_pipe_enable_vblank, ++ .disable_vblank = rp1vec_pipe_disable_vblank, ++}; ++ ++static void rp1vec_connector_destroy(struct drm_connector *connector) ++{ ++ drm_connector_unregister(connector); ++ drm_connector_cleanup(connector); ++} ++ ++static const struct drm_display_mode rp1vec_modes[4] = { ++ { /* Full size 525/60i with Rec.601 pixel rate */ ++ DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, ++ 720, 720 + 14, 720 + 14 + 64, 858, 0, ++ 480, 480 + 7, 480 + 7 + 6, 525, 0, ++ DRM_MODE_FLAG_INTERLACE) ++ }, ++ { /* Cropped and horizontally squashed to be TV-safe */ ++ DRM_MODE("704x432i", DRM_MODE_TYPE_DRIVER, 15429, ++ 704, 704 + 72, 704 + 72 + 72, 980, 0, ++ 432, 432 + 31, 432 + 31 + 6, 525, 0, ++ DRM_MODE_FLAG_INTERLACE) ++ }, ++ { /* Full size 625/50i with Rec.601 pixel rate */ ++ DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, ++ 720, 720 + 20, 720 + 20 + 64, 864, 0, ++ 576, 576 + 4, 576 + 4 + 6, 625, 0, ++ DRM_MODE_FLAG_INTERLACE) ++ }, ++ { /* Cropped and squashed, for square(ish) pixels */ ++ DRM_MODE("704x512i", DRM_MODE_TYPE_DRIVER, 15429, ++ 704, 704 + 80, 704 + 80 + 72, 987, 0, ++ 512, 512 + 36, 512 + 36 + 6, 625, 0, ++ DRM_MODE_FLAG_INTERLACE) ++ } ++}; ++ ++static int rp1vec_connector_get_modes(struct drm_connector *connector) ++{ ++ struct rp1_vec *vec = container_of(connector, struct rp1_vec, connector); ++ bool ok525 = RP1VEC_TVSTD_SUPPORT_525(vec->tv_norm); ++ bool ok625 = RP1VEC_TVSTD_SUPPORT_625(vec->tv_norm); ++ int i, prog, n = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(rp1vec_modes); i++) { ++ if ((rp1vec_modes[i].vtotal == 625) ? ok625 : ok525) { ++ for (prog = 0; prog < 2; prog++) { ++ struct drm_display_mode *mode = ++ drm_mode_duplicate(connector->dev, ++ &rp1vec_modes[i]); ++ ++ if (prog) { ++ mode->flags &= ~DRM_MODE_FLAG_INTERLACE; ++ mode->vdisplay >>= 1; ++ mode->vsync_start >>= 1; ++ mode->vsync_end >>= 1; ++ mode->vtotal >>= 1; ++ } ++ ++ if (mode->hdisplay == 704 && ++ mode->vtotal == ((ok525) ? 525 : 625)) ++ mode->type |= DRM_MODE_TYPE_PREFERRED; ++ ++ drm_mode_set_name(mode); ++ drm_mode_probed_add(connector, mode); ++ n++; ++ } ++ } ++ } ++ ++ return n; ++} ++ ++static void rp1vec_connector_reset(struct drm_connector *connector) ++{ ++ struct rp1_vec *vec = container_of(connector, struct rp1_vec, connector); ++ ++ drm_atomic_helper_connector_reset(connector); ++ if (connector->state) ++ connector->state->tv.mode = vec->tv_norm; ++} ++ ++static int rp1vec_connector_atomic_check(struct drm_connector *conn, ++ struct drm_atomic_state *state) ++{ struct drm_connector_state *old_state = ++ drm_atomic_get_old_connector_state(state, conn); ++ struct drm_connector_state *new_state = ++ drm_atomic_get_new_connector_state(state, conn); ++ ++ if (new_state->crtc && old_state->tv.mode != new_state->tv.mode) { ++ struct drm_crtc_state *crtc_state = ++ drm_atomic_get_new_crtc_state(state, new_state->crtc); ++ ++ crtc_state->mode_changed = true; ++ } ++ ++ return 0; ++} ++ ++static enum drm_mode_status rp1vec_mode_valid(struct drm_device *dev, ++ const struct drm_display_mode *mode) ++{ ++ /* ++ * Check the mode roughly matches one of our standard modes ++ * (optionally half-height and progressive). Ignore H/V sync ++ * timings which for interlaced TV are approximate at best. ++ */ ++ int i, prog; ++ ++ prog = !(mode->flags & DRM_MODE_FLAG_INTERLACE); ++ ++ for (i = 0; i < ARRAY_SIZE(rp1vec_modes); i++) { ++ const struct drm_display_mode *ref = rp1vec_modes + i; ++ ++ if (mode->hdisplay == ref->hdisplay && ++ mode->vdisplay == (ref->vdisplay >> prog) && ++ mode->clock + 2 >= ref->clock && ++ mode->clock <= ref->clock + 2 && ++ mode->htotal + 2 >= ref->htotal && ++ mode->htotal <= ref->htotal + 2 && ++ mode->vtotal + 2 >= (ref->vtotal >> prog) && ++ mode->vtotal <= (ref->vtotal >> prog) + 2) ++ return MODE_OK; ++ } ++ return MODE_BAD; ++} ++ ++static const struct drm_connector_helper_funcs rp1vec_connector_helper_funcs = { ++ .get_modes = rp1vec_connector_get_modes, ++ .atomic_check = rp1vec_connector_atomic_check, ++}; ++ ++static const struct drm_connector_funcs rp1vec_connector_funcs = { ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .destroy = rp1vec_connector_destroy, ++ .reset = rp1vec_connector_reset, ++ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, ++}; ++ ++static const struct drm_mode_config_funcs rp1vec_mode_funcs = { ++ .fb_create = drm_gem_fb_create, ++ .atomic_check = drm_atomic_helper_check, ++ .atomic_commit = drm_atomic_helper_commit, ++ .mode_valid = rp1vec_mode_valid, ++}; ++ ++static const u32 rp1vec_formats[] = { ++ DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_XBGR8888, ++ DRM_FORMAT_RGB888, ++ DRM_FORMAT_BGR888, ++ DRM_FORMAT_RGB565 ++}; ++ ++static void rp1vec_stopall(struct drm_device *drm) ++{ ++ if (drm->dev_private) { ++ struct rp1_vec *vec = drm->dev_private; ++ ++ if (vec->vec_running || rp1vec_hw_busy(vec)) { ++ rp1vec_hw_stop(vec); ++ vec->vec_running = false; ++ } ++ rp1vec_vidout_poweroff(vec); ++ } ++} ++ ++DEFINE_DRM_GEM_DMA_FOPS(rp1vec_fops); ++ ++static struct drm_driver rp1vec_driver = { ++ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, ++ .fops = &rp1vec_fops, ++ .name = "drm-rp1-vec", ++ .desc = "drm-rp1-vec", ++ .date = "0", ++ .major = 1, ++ .minor = 0, ++ DRM_GEM_DMA_DRIVER_OPS, ++ .release = rp1vec_stopall, ++}; ++ ++static int rp1vec_platform_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct drm_device *drm; ++ struct rp1_vec *vec; ++ const char *str; ++ int i, ret; ++ ++ dev_info(dev, __func__); ++ drm = drm_dev_alloc(&rp1vec_driver, dev); ++ if (IS_ERR(drm)) { ++ ret = PTR_ERR(drm); ++ dev_err(dev, "%s drm_dev_alloc %d", __func__, ret); ++ return ret; ++ } ++ ++ vec = drmm_kzalloc(drm, sizeof(*vec), GFP_KERNEL); ++ if (!vec) { ++ dev_err(dev, "%s drmm_kzalloc failed", __func__); ++ ret = -ENOMEM; ++ goto err_free_drm; ++ } ++ init_completion(&vec->finished); ++ vec->drm = drm; ++ vec->pdev = pdev; ++ drm->dev_private = vec; ++ platform_set_drvdata(pdev, drm); ++ ++ str = rp1vec_tv_norm_str; ++ of_property_read_string(dev->of_node, "tv_norm", &str); ++ vec->tv_norm = rp1vec_parse_tv_norm(str); ++ ++ for (i = 0; i < RP1VEC_NUM_HW_BLOCKS; i++) { ++ vec->hw_base[i] = ++ devm_ioremap_resource(dev, ++ platform_get_resource(vec->pdev, IORESOURCE_MEM, i)); ++ if (IS_ERR(vec->hw_base[i])) { ++ ret = PTR_ERR(vec->hw_base[i]); ++ dev_err(dev, "Error memory mapping regs[%d]\n", i); ++ goto err_free_drm; ++ } ++ } ++ ret = platform_get_irq(vec->pdev, 0); ++ if (ret > 0) ++ ret = devm_request_irq(dev, ret, rp1vec_hw_isr, ++ IRQF_SHARED, "rp1-vec", vec); ++ if (ret) { ++ dev_err(dev, "Unable to request interrupt\n"); ++ ret = -EINVAL; ++ goto err_free_drm; ++ } ++ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); ++ ++ vec->vec_clock = devm_clk_get(dev, NULL); ++ if (IS_ERR(vec->vec_clock)) { ++ ret = PTR_ERR(vec->vec_clock); ++ goto err_free_drm; ++ } ++ ret = clk_prepare_enable(vec->vec_clock); ++ ++ ret = drmm_mode_config_init(drm); ++ if (ret) ++ goto err_free_drm; ++ drm->mode_config.max_width = 768; ++ drm->mode_config.max_height = 576; ++ drm->mode_config.fb_base = 0; ++ drm->mode_config.preferred_depth = 32; ++ drm->mode_config.prefer_shadow = 0; ++ drm->mode_config.prefer_shadow_fbdev = 1; ++ //drm->mode_config.fbdev_use_iomem = false; ++ drm->mode_config.quirk_addfb_prefer_host_byte_order = true; ++ drm->mode_config.funcs = &rp1vec_mode_funcs; ++ drm_vblank_init(drm, 1); ++ ++ ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(rp1vec_tvstd_names), ++ rp1vec_tvstd_names); ++ if (ret) ++ goto err_free_drm; ++ ++ drm_connector_init(drm, &vec->connector, &rp1vec_connector_funcs, ++ DRM_MODE_CONNECTOR_Composite); ++ if (ret) ++ goto err_free_drm; ++ ++ vec->connector.interlace_allowed = true; ++ drm_connector_helper_add(&vec->connector, &rp1vec_connector_helper_funcs); ++ ++ drm_object_attach_property(&vec->connector.base, ++ drm->mode_config.tv_mode_property, ++ vec->tv_norm); ++ ++ ret = drm_simple_display_pipe_init(drm, ++ &vec->pipe, ++ &rp1vec_pipe_funcs, ++ rp1vec_formats, ++ ARRAY_SIZE(rp1vec_formats), ++ NULL, ++ &vec->connector); ++ if (ret) ++ goto err_free_drm; ++ ++ drm_mode_config_reset(drm); ++ ++ ret = drm_dev_register(drm, 0); ++ if (ret) ++ goto err_free_drm; ++ ++ drm_fbdev_generic_setup(drm, 32); /* the "32" is preferred BPP */ ++ return ret; ++ ++err_free_drm: ++ dev_info(dev, "%s fail %d", __func__, ret); ++ drm_dev_put(drm); ++ return ret; ++} ++ ++static int rp1vec_platform_remove(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ ++ rp1vec_stopall(drm); ++ drm_dev_unregister(drm); ++ drm_atomic_helper_shutdown(drm); ++ drm_dev_put(drm); ++ ++ return 0; ++} ++ ++static void rp1vec_platform_shutdown(struct platform_device *pdev) ++{ ++ struct drm_device *drm = platform_get_drvdata(pdev); ++ ++ rp1vec_stopall(drm); ++} ++ ++static const struct of_device_id rp1vec_of_match[] = { ++ { ++ .compatible = "raspberrypi,rp1vec", ++ }, ++ { /* sentinel */ }, ++}; ++ ++MODULE_DEVICE_TABLE(of, rp1vec_of_match); ++ ++static struct platform_driver rp1vec_platform_driver = { ++ .probe = rp1vec_platform_probe, ++ .remove = rp1vec_platform_remove, ++ .shutdown = rp1vec_platform_shutdown, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = rp1vec_of_match, ++ }, ++}; ++ ++module_platform_driver(rp1vec_platform_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("DRM driver for Composite Video on Raspberry Pi RP1"); ++MODULE_AUTHOR("Nick Hollinghurst"); +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.h +@@ -0,0 +1,79 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "drm-rp1-vec" ++#define DRIVER_NAME "drm-rp1-vec" ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define RP1VEC_HW_BLOCK_VEC 0 ++#define RP1VEC_HW_BLOCK_CFG 1 ++#define RP1VEC_NUM_HW_BLOCKS 2 ++ ++enum { ++ RP1VEC_TVSTD_NTSC = 0, /* +525 => NTSC 625 => PAL */ ++ RP1VEC_TVSTD_NTSC_J, /* +525 => NTSC-J 625 => PAL */ ++ RP1VEC_TVSTD_NTSC_443, /* +525 => NTSC-443 +625 => PAL */ ++ RP1VEC_TVSTD_PAL, /* 525 => NTSC +625 => PAL */ ++ RP1VEC_TVSTD_PAL_M, /* +525 => PAL-M 625 => PAL */ ++ RP1VEC_TVSTD_PAL_N, /* 525 => NTSC +625 => PAL-N */ ++ RP1VEC_TVSTD_PAL60, /* +525 => PAL60 +625 => PAL */ ++ RP1VEC_TVSTD_DEFAULT, /* +525 => NTSC +625 => PAL */ ++}; ++ ++/* Which standards support which modes? Those marked with + above */ ++#define RP1VEC_TVSTD_SUPPORT_525(n) ((0xD7 >> (n)) & 1) ++#define RP1VEC_TVSTD_SUPPORT_625(n) ((0xEC >> (n)) & 1) ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct rp1_vec { ++ /* DRM and platform device pointers */ ++ struct drm_device *drm; ++ struct platform_device *pdev; ++ ++ /* Framework and helper objects */ ++ struct drm_simple_display_pipe pipe; ++ struct drm_connector connector; ++ ++ /* Clock. We assume this is always at 108 MHz. */ ++ struct clk *vec_clock; ++ ++ /* Block (VCC, CFG) base addresses, and current state */ ++ void __iomem *hw_base[RP1VEC_NUM_HW_BLOCKS]; ++ u32 cur_fmt; ++ int tv_norm; ++ bool vec_running, pipe_enabled; ++ struct completion finished; ++}; ++ ++extern const char * const rp1vec_tvstd_names[]; ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the VEC/DMA block */ ++ ++void rp1vec_hw_setup(struct rp1_vec *vec, ++ u32 in_format, ++ struct drm_display_mode const *mode, ++ int tvstd); ++void rp1vec_hw_update(struct rp1_vec *vec, dma_addr_t addr, u32 offset, u32 stride); ++void rp1vec_hw_stop(struct rp1_vec *vec); ++int rp1vec_hw_busy(struct rp1_vec *vec); ++irqreturn_t rp1vec_hw_isr(int irq, void *dev); ++void rp1vec_hw_vblank_ctrl(struct rp1_vec *vec, int enable); ++ ++/* ---------------------------------------------------------------------- */ ++/* Functions to control the VIDEO OUT CFG block and check RP1 platform */ ++ ++void rp1vec_vidout_setup(struct rp1_vec *vec); ++void rp1vec_vidout_poweroff(struct rp1_vec *vec); +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec_cfg.c +@@ -0,0 +1,508 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for DSI output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_vec.h" ++ ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_SEL ++// JTAG access : synchronous ++// Description : Selects source: VEC or DPI ++#define VIDEO_OUT_CFG_SEL_OFFSET 0x00000000 ++#define VIDEO_OUT_CFG_SEL_BITS 0x00000013 ++#define VIDEO_OUT_CFG_SEL_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_PCLK_INV ++// Description : Select dpi_pclk output port polarity inversion. ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_BITS 0x00000010 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_MSB 4 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_LSB 4 ++#define VIDEO_OUT_CFG_SEL_PCLK_INV_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_PAD_MUX ++// Description : VEC 1 DPI 0 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_BITS 0x00000002 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_MSB 1 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_LSB 1 ++#define VIDEO_OUT_CFG_SEL_PAD_MUX_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_SEL_VDAC_MUX ++// Description : VEC 1 DPI 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_RESET 0x0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_BITS 0x00000001 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_MSB 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_LSB 0 ++#define VIDEO_OUT_CFG_SEL_VDAC_MUX_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_VDAC_CFG ++// JTAG access : synchronous ++// Description : Configure SNPS VDAC ++#define VIDEO_OUT_CFG_VDAC_CFG_OFFSET 0x00000004 ++#define VIDEO_OUT_CFG_VDAC_CFG_BITS 0x1fffffff ++#define VIDEO_OUT_CFG_VDAC_CFG_RESET 0x0003ffff ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENCTR ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_BITS 0x1c000000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_MSB 28 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_LSB 26 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENCTR_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENSC ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_BITS 0x03800000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_MSB 25 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_LSB 23 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENSC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENDAC ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_BITS 0x00700000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_MSB 22 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_LSB 20 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENDAC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENVBG ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_BITS 0x00080000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_MSB 19 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_LSB 19 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENVBG_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_BITS 0x00040000 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_MSB 18 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_LSB 18 ++#define VIDEO_OUT_CFG_VDAC_CFG_ENEXTREF_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC2GC ++// Description : dac2 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_BITS 0x0003f000 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_MSB 17 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_LSB 12 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC2GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC1GC ++// Description : dac1 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_BITS 0x00000fc0 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_MSB 11 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_LSB 6 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC1GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_CFG_DAC0GC ++// Description : dac0 gain control ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_RESET 0x3f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_BITS 0x0000003f ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_MSB 5 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_LSB 0 ++#define VIDEO_OUT_CFG_VDAC_CFG_DAC0GC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_VDAC_STATUS ++// JTAG access : synchronous ++// Description : Read VDAC status ++#define VIDEO_OUT_CFG_VDAC_STATUS_OFFSET 0x00000008 ++#define VIDEO_OUT_CFG_VDAC_STATUS_BITS 0x00000017 ++#define VIDEO_OUT_CFG_VDAC_STATUS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3 ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_RESET 0x0 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_BITS 0x00000010 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_MSB 4 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_LSB 4 ++#define VIDEO_OUT_CFG_VDAC_STATUS_ENCTR3_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT ++// Description : None ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_RESET "-" ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_BITS 0x00000007 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_MSB 2 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_LSB 0 ++#define VIDEO_OUT_CFG_VDAC_STATUS_CABLEOUT_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_MEM_PD ++// JTAG access : synchronous ++// Description : Control memory power down ++#define VIDEO_OUT_CFG_MEM_PD_OFFSET 0x0000000c ++#define VIDEO_OUT_CFG_MEM_PD_BITS 0x00000003 ++#define VIDEO_OUT_CFG_MEM_PD_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_MEM_PD_VEC ++// Description : None ++#define VIDEO_OUT_CFG_MEM_PD_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_BITS 0x00000002 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_MSB 1 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_LSB 1 ++#define VIDEO_OUT_CFG_MEM_PD_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_MEM_PD_DPI ++// Description : None ++#define VIDEO_OUT_CFG_MEM_PD_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_BITS 0x00000001 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_MSB 0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_LSB 0 ++#define VIDEO_OUT_CFG_MEM_PD_DPI_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_TEST_OVERRIDE ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_OFFSET 0x00000010 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_BITS 0xffffffff ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_PAD ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_RESET 0x0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_BITS 0x80000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_MSB 31 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_LSB 31 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_PAD_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_RESET 0x0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_BITS 0x40000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_MSB 30 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_LSB 30 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_VDAC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL ++// Description : None ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_RESET 0x00000000 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_BITS 0x3fffffff ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_MSB 29 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_LSB 0 ++#define VIDEO_OUT_CFG_TEST_OVERRIDE_RGBVAL_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTR ++// JTAG access : synchronous ++// Description : Raw Interrupts ++#define VIDEO_OUT_CFG_INTR_OFFSET 0x00000014 ++#define VIDEO_OUT_CFG_INTR_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTR_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTR_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTR_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTR_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTR_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTR_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTR_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTR_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTR_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTR_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTR_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTR_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTR_VEC_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTE ++// JTAG access : synchronous ++// Description : Interrupt Enable ++#define VIDEO_OUT_CFG_INTE_OFFSET 0x00000018 ++#define VIDEO_OUT_CFG_INTE_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTE_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTE_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTE_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTE_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTE_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTE_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTE_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTE_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTE_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTE_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTE_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTE_VEC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTF ++// JTAG access : synchronous ++// Description : Interrupt Force ++#define VIDEO_OUT_CFG_INTF_OFFSET 0x0000001c ++#define VIDEO_OUT_CFG_INTF_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTF_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTF_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTF_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTF_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTF_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTF_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTF_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTF_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTF_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTF_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTF_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTF_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTF_VEC_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INTS ++// JTAG access : synchronous ++// Description : Interrupt status after masking & forcing ++#define VIDEO_OUT_CFG_INTS_OFFSET 0x00000020 ++#define VIDEO_OUT_CFG_INTS_BITS 0x00000003 ++#define VIDEO_OUT_CFG_INTS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTS_DPI ++// Description : None ++#define VIDEO_OUT_CFG_INTS_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_INTS_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_INTS_DPI_MSB 1 ++#define VIDEO_OUT_CFG_INTS_DPI_LSB 1 ++#define VIDEO_OUT_CFG_INTS_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_INTS_VEC ++// Description : None ++#define VIDEO_OUT_CFG_INTS_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_INTS_VEC_BITS 0x00000001 ++#define VIDEO_OUT_CFG_INTS_VEC_MSB 0 ++#define VIDEO_OUT_CFG_INTS_VEC_LSB 0 ++#define VIDEO_OUT_CFG_INTS_VEC_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_BLOCK_ID ++// JTAG access : synchronous ++// Description : Block Identifier ++// Hexadecimal representation of "VOCF" ++#define VIDEO_OUT_CFG_BLOCK_ID_OFFSET 0x00000024 ++#define VIDEO_OUT_CFG_BLOCK_ID_BITS 0xffffffff ++#define VIDEO_OUT_CFG_BLOCK_ID_RESET 0x564f4346 ++#define VIDEO_OUT_CFG_BLOCK_ID_MSB 31 ++#define VIDEO_OUT_CFG_BLOCK_ID_LSB 0 ++#define VIDEO_OUT_CFG_BLOCK_ID_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_INSTANCE_ID ++// JTAG access : synchronous ++// Description : Block Instance Identifier ++#define VIDEO_OUT_CFG_INSTANCE_ID_OFFSET 0x00000028 ++#define VIDEO_OUT_CFG_INSTANCE_ID_BITS 0x0000000f ++#define VIDEO_OUT_CFG_INSTANCE_ID_RESET 0x00000000 ++#define VIDEO_OUT_CFG_INSTANCE_ID_MSB 3 ++#define VIDEO_OUT_CFG_INSTANCE_ID_LSB 0 ++#define VIDEO_OUT_CFG_INSTANCE_ID_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_AUTO ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_OFFSET 0x0000002c ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_RESET 0x00000007 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER ++// Description : 1 = reset is controlled by the sequencer ++// 0 = reset is controlled by rstseq_ctrl ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_AUTO_BUSADAPTER_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_PARALLEL ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_OFFSET 0x00000030 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_RESET 0x00000006 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_VEC_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_RESET 0x1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER ++// Description : Is this reset parallel (i.e. not part of the sequence) ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_PARALLEL_BUSADAPTER_ACCESS "RO" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_CTRL ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_OFFSET 0x00000034 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_VEC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_DPI_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER ++// Description : 1 = keep the reset asserted ++// 0 = keep the reset deasserted ++// This is ignored if rstseq_auto=1 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_CTRL_BUSADAPTER_ACCESS "RW" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_TRIG ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_OFFSET 0x00000038 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_VEC_ACCESS "SC" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_DPI_ACCESS "SC" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER ++// Description : Pulses the reset output ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_TRIG_BUSADAPTER_ACCESS "SC" ++// ============================================================================= ++// Register : VIDEO_OUT_CFG_RSTSEQ_DONE ++// JTAG access : synchronous ++// Description : None ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_OFFSET 0x0000003c ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BITS 0x00000007 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_VEC ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_BITS 0x00000004 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_MSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_LSB 2 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_VEC_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_DPI ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_BITS 0x00000002 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_MSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_LSB 1 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_DPI_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER ++// Description : Indicates the current state of the reset ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_RESET 0x0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_BITS 0x00000001 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_MSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_LSB 0 ++#define VIDEO_OUT_CFG_RSTSEQ_DONE_BUSADAPTER_ACCESS "RO" ++// ============================================================================= ++ ++#define CFG_WRITE(reg, val) writel((val), vec->hw_base[RP1VEC_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++#define CFG_READ(reg) readl(vec->hw_base[RP1VEC_HW_BLOCK_CFG] + (reg ## _OFFSET)) ++ ++void rp1vec_vidout_setup(struct rp1_vec *vec) ++{ ++ /* ++ * We assume DPI and VEC can't be used at the same time (due to ++ * clashing requirements for PLL_VIDEO, and potentially for VDAC). ++ * We therefore leave DPI memories powered down. ++ */ ++ CFG_WRITE(VIDEO_OUT_CFG_MEM_PD, VIDEO_OUT_CFG_MEM_PD_DPI_BITS); ++ CFG_WRITE(VIDEO_OUT_CFG_TEST_OVERRIDE, 0x00000000); ++ ++ /* DPI->Pads; VEC->VDAC */ ++ CFG_WRITE(VIDEO_OUT_CFG_SEL, VIDEO_OUT_CFG_SEL_VDAC_MUX_BITS); ++ ++ /* configure VDAC for 1 channel, bandgap on, 1.28V swing */ ++ CFG_WRITE(VIDEO_OUT_CFG_VDAC_CFG, 0x0019ffff); ++ ++ /* enable VEC interrupt */ ++ CFG_WRITE(VIDEO_OUT_CFG_INTE, VIDEO_OUT_CFG_INTE_VEC_BITS); ++} ++ ++void rp1vec_vidout_poweroff(struct rp1_vec *vec) ++{ ++ /* disable VEC interrupt */ ++ CFG_WRITE(VIDEO_OUT_CFG_INTE, 0); ++ ++ /* Ensure VDAC is turned off; power down DPI,VEC memories */ ++ CFG_WRITE(VIDEO_OUT_CFG_VDAC_CFG, 0); ++ CFG_WRITE(VIDEO_OUT_CFG_MEM_PD, VIDEO_OUT_CFG_MEM_PD_BITS); ++} +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c +@@ -0,0 +1,469 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * DRM Driver for VEC output on Raspberry Pi RP1 ++ * ++ * Copyright (c) 2023 Raspberry Pi Limited. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rp1_vec.h" ++#include "vec_regs.h" ++ ++#define BITS(field, val) (((val) << (field ## _LSB)) & (field ## _BITS)) ++ ++#define VEC_WRITE(reg, val) writel((val), vec->hw_base[RP1VEC_HW_BLOCK_VEC] + (reg ## _OFFSET)) ++#define VEC_READ(reg) readl(vec->hw_base[RP1VEC_HW_BLOCK_VEC] + (reg ## _OFFSET)) ++ ++int rp1vec_hw_busy(struct rp1_vec *vec) ++{ ++ /* Read the undocumented "pline_busy" flag */ ++ return VEC_READ(VEC_STATUS) & 1; ++} ++ ++/* Table of supported input (in-memory/DMA) pixel formats. */ ++struct rp1vec_ipixfmt { ++ u32 format; /* DRM format code */ ++ u32 mask; /* RGB masks (10 bits each, left justified) */ ++ u32 shift; /* RGB MSB positions in the memory word */ ++ u32 rgbsz; /* Shifts used for scaling; also (BPP/8-1) */ ++}; ++ ++#define MASK_RGB(r, g, b) \ ++ (BITS(VEC_IMASK_MASK_R, r) | BITS(VEC_IMASK_MASK_G, g) | BITS(VEC_IMASK_MASK_B, b)) ++#define SHIFT_RGB(r, g, b) \ ++ (BITS(VEC_SHIFT_SHIFT_R, r) | BITS(VEC_SHIFT_SHIFT_G, g) | BITS(VEC_SHIFT_SHIFT_B, b)) ++ ++static const struct rp1vec_ipixfmt my_formats[] = { ++ { ++ .format = DRM_FORMAT_XRGB8888, ++ .mask = MASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = SHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1, 3), ++ }, ++ { ++ .format = DRM_FORMAT_XBGR8888, ++ .mask = MASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = SHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1, 3), ++ }, ++ { ++ .format = DRM_FORMAT_RGB888, ++ .mask = MASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = SHIFT_RGB(23, 15, 7), ++ .rgbsz = BITS(VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1, 2), ++ }, ++ { ++ .format = DRM_FORMAT_BGR888, ++ .mask = MASK_RGB(0x3fc, 0x3fc, 0x3fc), ++ .shift = SHIFT_RGB(7, 15, 23), ++ .rgbsz = BITS(VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1, 2), ++ }, ++ { ++ .format = DRM_FORMAT_RGB565, ++ .mask = MASK_RGB(0x3e0, 0x3f0, 0x3e0), ++ .shift = SHIFT_RGB(15, 10, 4), ++ .rgbsz = BITS(VEC_RGBSZ_SCALE_R, 5) | ++ BITS(VEC_RGBSZ_SCALE_G, 6) | ++ BITS(VEC_RGBSZ_SCALE_B, 5) | ++ BITS(VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1, 1), ++ } ++}; ++ ++/* ++ * Hardware mode descriptions (@ 108 MHz clock rate). ++ * These rely largely on "canned" register settings. ++ * TODO: Port the generating software from FP to integer, ++ * or better factorize the differences between modes. ++ */ ++ ++struct rp1vec_hwmode { ++ u16 total_cols; /* active columns, plus padding for filter context */ ++ u16 rows_per_field; /* active lines per field (including partial ones) */ ++ bool interlaced; /* set for interlaced */ ++ bool first_field_odd; /* set for interlaced and 30fps */ ++ u32 yuv_scaling; /* three 10-bit fields {Y, U, V} in 2.8 format */ ++ u32 back_end_regs[28]; /* All registers 0x80 .. 0xEC */ ++}; ++ ++/* { NTSC, PAL, PAL-M } x { progressive, interlaced } x { 13.5 MHz, 15.428571 MHz } */ ++static const struct rp1vec_hwmode rp1vec_hwmodes[3][2][2] = { ++ { ++ /* NTSC */ ++ { ++ { ++ .total_cols = 724, ++ .rows_per_field = 240, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x1071d0cf, ++ .back_end_regs = { ++ 0x039f1a3f, 0x03e10cc6, 0x0d6801fb, 0x023d034c, ++ 0x00f80b6d, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0106, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170106, 0x00000000, 0x004c020e, ++ 0x00000000, 0x007bffff, 0x38518c9a, 0x11195561, ++ 0x02000200, 0xc1f07c1f, 0x087c1f07, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ec, ++ }, ++ }, { ++ .total_cols = 815, ++ .rows_per_field = 240, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x1c131962, ++ .back_end_regs = { ++ 0x03ce1a17, 0x03e10cc6, 0x0d6801fb, 0x023d034c, ++ 0x00f80b6d, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0106, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170106, 0x00000000, 0x004c020e, ++ 0x00000000, 0x007bffff, 0x38518c9a, 0x11195561, ++ 0x02000200, 0xc1f07c1f, 0x087c1f07, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ac, ++ }, ++ }, ++ }, { ++ { ++ .total_cols = 724, ++ .rows_per_field = 243, ++ .interlaced = true, ++ .first_field_odd = true, ++ .yuv_scaling = 0x1071d0cf, ++ .back_end_regs = { ++ 0x039f1a3f, 0x03e10cc6, 0x0d6801fb, 0x023d034c, ++ 0x00f80b6d, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0107, 0x0111020d, 0x00000000, 0x00000000, ++ 0x011c020d, 0x00150106, 0x0107011b, 0x004c020d, ++ 0x00000000, 0x007bffff, 0x38518c9a, 0x11195561, ++ 0x02000200, 0xc1f07c1f, 0x087c1f07, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x00094dee, ++ }, ++ }, { ++ .total_cols = 815, ++ .rows_per_field = 243, ++ .interlaced = true, ++ .first_field_odd = true, ++ .yuv_scaling = 0x1c131962, ++ .back_end_regs = { ++ 0x03ce1a17, 0x03e10cc6, 0x0d6801fb, 0x023d034c, ++ 0x00f80b6d, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0107, 0x0111020d, 0x00000000, 0x00000000, ++ 0x011c020d, 0x00150106, 0x0107011b, 0x004c020d, ++ 0x00000000, 0x007bffff, 0x38518c9a, 0x11195561, ++ 0x02000200, 0xc1f07c1f, 0x087c1f07, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x00094dae, ++ }, ++ }, ++ }, ++ }, { ++ /* PAL */ ++ { ++ { ++ .total_cols = 724, ++ .rows_per_field = 288, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x11c1f8e0, ++ .back_end_regs = { ++ 0x04061aa6, 0x046e0cee, 0x0d8001fb, 0x025c034f, ++ 0x00fd0b84, 0x026c0270, 0x00000004, 0x00050009, ++ 0x00070135, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170136, 0x00000000, 0x000a0270, ++ 0x00000000, 0x007bffff, 0x3b1389d8, 0x0caf53b5, ++ 0x02000200, 0xcc48c1d1, 0x0a8262b2, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ed, ++ }, ++ }, { ++ .total_cols = 804, ++ .rows_per_field = 288, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x1e635d7f, ++ .back_end_regs = { ++ 0x045b1a57, 0x046e0cee, 0x0d8001fb, 0x025c034f, ++ 0x00fd0b84, 0x026c0270, 0x00000004, 0x00050009, ++ 0x00070135, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170136, 0x00000000, 0x000a0270, ++ 0x00000000, 0x007bffff, 0x3b1389d8, 0x0caf53b5, ++ 0x02000200, 0xcc48c1d1, 0x0a8262b2, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ad, ++ }, ++ }, ++ }, { ++ { ++ .total_cols = 724, ++ .rows_per_field = 288, ++ .interlaced = true, ++ .first_field_odd = false, ++ .yuv_scaling = 0x11c1f8e0, ++ .back_end_regs = { ++ 0x04061aa6, 0x046e0cee, 0x0d8001fb, 0x025c034f, ++ 0x00fd0b84, 0x026c0270, 0x00000004, 0x00050009, ++ 0x00070135, 0x013f026d, 0x00060136, 0x0140026e, ++ 0x0150026e, 0x00180136, 0x026f0017, 0x000a0271, ++ 0x00000000, 0x007bffff, 0x3b1389d8, 0x0caf53b5, ++ 0x02000200, 0xcc48c1d1, 0x0a8262b2, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x0009ddef, ++ }, ++ }, { ++ .total_cols = 804, ++ .rows_per_field = 288, ++ .interlaced = true, ++ .first_field_odd = false, ++ .yuv_scaling = 0x1e635d7f, ++ .back_end_regs = { ++ 0x045b1a57, 0x046e0cee, 0x0d8001fb, 0x025c034f, ++ 0x00fd0b84, 0x026c0270, 0x00000004, 0x00050009, ++ 0x00070135, 0x013f026d, 0x00060136, 0x0140026e, ++ 0x0150026e, 0x00180136, 0x026f0017, 0x000a0271, ++ 0x00000000, 0x007bffff, 0x3b1389d8, 0x0caf53b5, ++ 0x02000200, 0xcc48c1d1, 0x0a8262b2, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x0009ddaf, ++ }, ++ }, ++ }, ++ }, { ++ /* PAL-M */ ++ { ++ { ++ .total_cols = 724, ++ .rows_per_field = 240, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x11c1f8e0, ++ .back_end_regs = { ++ 0x039f1a3f, 0x03e10cc6, 0x0d6801fb, 0x023c034c, ++ 0x00f80b6e, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0106, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170106, 0x00000000, 0x000a020c, ++ 0x00000000, 0x007bffff, 0x385189d8, 0x0d5c53b5, ++ 0x02000200, 0xd6d33ea8, 0x0879bbf8, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ed, ++ }, ++ }, { ++ .total_cols = 815, ++ .rows_per_field = 240, ++ .interlaced = false, ++ .first_field_odd = false, ++ .yuv_scaling = 0x1e635d7f, ++ .back_end_regs = { ++ 0x03ce1a17, 0x03e10cc6, 0x0d6801fb, 0x023c034c, ++ 0x00f80b6e, 0x00000005, 0x0006000b, 0x000c0011, ++ 0x000a0106, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00170106, 0x00000000, 0x000a020c, ++ 0x00000000, 0x007bffff, 0x385189d8, 0x0d5c53b5, ++ 0x02000200, 0xd6d33ea8, 0x0879bbf8, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x000801ad, ++ }, ++ }, ++ }, { ++ { ++ .total_cols = 724, ++ .rows_per_field = 243, ++ .interlaced = true, ++ .first_field_odd = true, ++ .yuv_scaling = 0x11c1f8e0, ++ .back_end_regs = { ++ 0x039f1a3f, 0x03e10cc6, 0x0d6801fb, 0x023c034c, ++ 0x00f80b6e, 0x00140019, 0x00000005, 0x0006000b, ++ 0x00090103, 0x010f0209, 0x00080102, 0x010e020a, ++ 0x0119020a, 0x00120103, 0x01040118, 0x000a020d, ++ 0x00000000, 0x007bffff, 0x385189d8, 0x0d5c53b5, ++ 0x02000200, 0xd6d33ea8, 0x0879bbf8, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x0009ddef, ++ }, ++ }, { ++ .total_cols = 815, ++ .rows_per_field = 243, ++ .interlaced = true, ++ .first_field_odd = true, ++ .yuv_scaling = 0x1e635d7f, ++ .back_end_regs = { ++ 0x03ce1a17, 0x03e10cc6, 0x0d6801fb, 0x023c034c, ++ 0x00f80b6e, 0x00140019, 0x00000005, 0x0006000b, ++ 0x00090103, 0x010f0209, 0x00080102, 0x010e020a, ++ 0x0119020a, 0x00120103, 0x01040118, 0x000a020d, ++ 0x00000000, 0x007bffff, 0x385189d8, 0x0d5c53b5, ++ 0x02000200, 0xd6d33ea8, 0x0879bbf8, 0x00000000, ++ 0x0be20200, 0x20f0f800, 0x265c7f00, 0x0009ddaf, ++ }, ++ }, ++ }, ++ }, ++}; ++ ++void rp1vec_hw_setup(struct rp1_vec *vec, ++ u32 in_format, ++ struct drm_display_mode const *mode, ++ int tvstd) ++{ ++ unsigned int i, mode_family, mode_ilaced, mode_narrow; ++ const struct rp1vec_hwmode *hwm; ++ unsigned int w, h; ++ ++ /* Pick the appropriate "base" mode, which we may modify */ ++ mode_ilaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); ++ if (mode->vtotal > 263 * (1 + mode_ilaced)) ++ mode_family = 1; ++ else ++ mode_family = (tvstd == RP1VEC_TVSTD_PAL_M || tvstd == RP1VEC_TVSTD_PAL60) ? 2 : 0; ++ mode_narrow = (mode->clock >= 14336); ++ hwm = &rp1vec_hwmodes[mode_family][mode_ilaced][mode_narrow]; ++ dev_info(&vec->pdev->dev, ++ "%s: in_fmt=\'%c%c%c%c\' mode=%dx%d%s [%d%d%d] tvstd=%d (%s)", ++ __func__, in_format, in_format >> 8, in_format >> 16, in_format >> 24, ++ mode->hdisplay, mode->vdisplay, (mode_ilaced) ? "i" : "", ++ mode_family, mode_ilaced, mode_narrow, ++ tvstd, rp1vec_tvstd_names[tvstd]); ++ ++ w = mode->hdisplay; ++ h = mode->vdisplay; ++ if (mode_ilaced) ++ h >>= 1; ++ if (w > hwm->total_cols) ++ w = hwm->total_cols; ++ if (h > hwm->rows_per_field) ++ w = hwm->rows_per_field; ++ ++ /* Configure the hardware */ ++ VEC_WRITE(VEC_APB_TIMEOUT, 0x38); ++ VEC_WRITE(VEC_QOS, ++ BITS(VEC_QOS_DQOS, 0x0) | ++ BITS(VEC_QOS_ULEV, 0x8) | ++ BITS(VEC_QOS_UQOS, 0x2) | ++ BITS(VEC_QOS_LLEV, 0x4) | ++ BITS(VEC_QOS_LQOS, 0x7)); ++ VEC_WRITE(VEC_DMA_AREA, ++ BITS(VEC_DMA_AREA_COLS_MINUS1, w - 1) | ++ BITS(VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1, h - 1)); ++ VEC_WRITE(VEC_YUV_SCALING, hwm->yuv_scaling); ++ VEC_WRITE(VEC_BACK_PORCH, ++ BITS(VEC_BACK_PORCH_HBP_MINUS1, (hwm->total_cols - w - 1) >> 1) | ++ BITS(VEC_BACK_PORCH_VBP_MINUS1, (hwm->rows_per_field - h - 1) >> 1)); ++ VEC_WRITE(VEC_FRONT_PORCH, ++ BITS(VEC_FRONT_PORCH_HFP_MINUS1, (hwm->total_cols - w - 2) >> 1) | ++ BITS(VEC_FRONT_PORCH_VFP_MINUS1, (hwm->rows_per_field - h - 2) >> 1)); ++ VEC_WRITE(VEC_MODE, ++ BITS(VEC_MODE_HIGH_WATER, 0xE0) | ++ BITS(VEC_MODE_ALIGN16, !((w | mode->hdisplay) & 15)) | ++ BITS(VEC_MODE_VFP_EN, (hwm->rows_per_field > h + 1)) | ++ BITS(VEC_MODE_VBP_EN, (hwm->rows_per_field > h)) | ++ BITS(VEC_MODE_HFP_EN, (hwm->total_cols > w + 1)) | ++ BITS(VEC_MODE_HBP_EN, (hwm->total_cols > w)) | ++ BITS(VEC_MODE_FIELDS_PER_FRAME_MINUS1, hwm->interlaced) | ++ BITS(VEC_MODE_FIRST_FIELD_ODD, hwm->first_field_odd)); ++ for (i = 0; i < ARRAY_SIZE(hwm->back_end_regs); ++i) { ++ writel(hwm->back_end_regs[i], ++ vec->hw_base[RP1VEC_HW_BLOCK_VEC] + 0x80 + 4 * i); ++ } ++ ++ /* Apply modifications */ ++ if (tvstd == RP1VEC_TVSTD_NTSC_J && mode_family == 0) { ++ /* Reduce pedestal (not quite to zero, for FIR overshoot); increase gain */ ++ VEC_WRITE(VEC_DAC_BC, ++ BITS(VEC_DAC_BC_S11_PEDESTAL, 10) | ++ (hwm->back_end_regs[(0xBC - 0x80) / 4] & ~VEC_DAC_BC_S11_PEDESTAL_BITS)); ++ VEC_WRITE(VEC_DAC_C8, ++ BITS(VEC_DAC_C8_U16_SCALE_LUMA, 0x9400) | ++ (hwm->back_end_regs[(0xC8 - 0x80) / 4] & ++ ~VEC_DAC_C8_U16_SCALE_LUMA_BITS)); ++ } else if ((tvstd == RP1VEC_TVSTD_NTSC_443 || tvstd == RP1VEC_TVSTD_PAL60) && ++ mode_family != 1) { ++ /* Change colour carrier frequency to 4433618.75 Hz; disable hard sync */ ++ VEC_WRITE(VEC_DAC_D4, 0xcc48c1d1); ++ VEC_WRITE(VEC_DAC_D8, 0x0a8262b2); ++ VEC_WRITE(VEC_DAC_EC, ++ hwm->back_end_regs[(0xEC - 0x80) / 4] & ~VEC_DAC_EC_SEQ_EN_BITS); ++ } else if (tvstd == RP1VEC_TVSTD_PAL_N && mode_family == 1) { ++ /* Change colour carrier frequency to 3582056.25 Hz */ ++ VEC_WRITE(VEC_DAC_D4, 0x9ce075f7); ++ VEC_WRITE(VEC_DAC_D8, 0x087da511); ++ } ++ ++ /* Input pixel format conversion */ ++ for (i = 0; i < ARRAY_SIZE(my_formats); ++i) { ++ if (my_formats[i].format == in_format) ++ break; ++ } ++ if (i >= ARRAY_SIZE(my_formats)) { ++ dev_err(&vec->pdev->dev, "%s: bad input format\n", __func__); ++ i = 0; ++ } ++ VEC_WRITE(VEC_IMASK, my_formats[i].mask); ++ VEC_WRITE(VEC_SHIFT, my_formats[i].shift); ++ VEC_WRITE(VEC_RGBSZ, my_formats[i].rgbsz); ++ ++ VEC_WRITE(VEC_IRQ_FLAGS, 0xffffffff); ++ rp1vec_hw_vblank_ctrl(vec, 1); ++ ++ i = rp1vec_hw_busy(vec); ++ if (i) ++ dev_warn(&vec->pdev->dev, ++ "%s: VEC unexpectedly busy at start (0x%08x)", ++ __func__, VEC_READ(VEC_STATUS)); ++ ++ VEC_WRITE(VEC_CONTROL, ++ BITS(VEC_CONTROL_START_ARM, (!i)) | ++ BITS(VEC_CONTROL_AUTO_REPEAT, 1)); ++} ++ ++void rp1vec_hw_update(struct rp1_vec *vec, dma_addr_t addr, u32 offset, u32 stride) ++{ ++ /* ++ * Update STRIDE, DMAH and DMAL only. When called after rp1vec_hw_setup(), ++ * DMA starts immediately; if already running, the buffer will flip at ++ * the next vertical sync event. ++ */ ++ u64 a = addr + offset; ++ ++ VEC_WRITE(VEC_DMA_STRIDE, stride); ++ VEC_WRITE(VEC_DMA_ADDR_H, a >> 32); ++ VEC_WRITE(VEC_DMA_ADDR_L, a & 0xFFFFFFFFu); ++} ++ ++void rp1vec_hw_stop(struct rp1_vec *vec) ++{ ++ /* ++ * Stop DMA by turning off the Auto-Repeat flag, and wait up to 100ms for ++ * the current and any queued frame to end. "Force drain" flags are not used, ++ * as they seem to prevent DMA from re-starting properly; it's safer to wait. ++ */ ++ ++ reinit_completion(&vec->finished); ++ VEC_WRITE(VEC_CONTROL, 0); ++ if (!wait_for_completion_timeout(&vec->finished, HZ / 10)) ++ drm_err(vec->drm, "%s: timed out waiting for idle\n", __func__); ++ VEC_WRITE(VEC_IRQ_ENABLES, 0); ++} ++ ++void rp1vec_hw_vblank_ctrl(struct rp1_vec *vec, int enable) ++{ ++ VEC_WRITE(VEC_IRQ_ENABLES, ++ BITS(VEC_IRQ_ENABLES_DONE, 1) | ++ BITS(VEC_IRQ_ENABLES_DMA, (enable ? 1 : 0)) | ++ BITS(VEC_IRQ_ENABLES_MATCH_ROW, 1023)); ++} ++ ++irqreturn_t rp1vec_hw_isr(int irq, void *dev) ++{ ++ struct rp1_vec *vec = dev; ++ u32 u = VEC_READ(VEC_IRQ_FLAGS); ++ ++ if (u) { ++ VEC_WRITE(VEC_IRQ_FLAGS, u); ++ if (u & VEC_IRQ_FLAGS_DMA_BITS) ++ drm_crtc_handle_vblank(&vec->pipe.crtc); ++ if (u & VEC_IRQ_FLAGS_DONE_BITS) ++ complete(&vec->finished); ++ } ++ return u ? IRQ_HANDLED : IRQ_NONE; ++} +--- /dev/null ++++ b/drivers/gpu/drm/rp1/rp1-vec/vec_regs.h +@@ -0,0 +1,1420 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++// ============================================================================= ++// Copyright Raspberry Pi Ltd. 2023 ++// vrbuild version: 56aac1a23c016cbbd229108f3b6efc1343842156-clean ++// THIS FILE IS GENERATED BY VRBUILD - DO NOT EDIT ++// ============================================================================= ++// Register block : VEC ++// Version : 1 ++// Bus type : apb ++// Description : None ++// ============================================================================= ++#ifndef VEC_REGS_DEFINED ++#define VEC_REGS_DEFINED ++#define VEC_REGS_RWTYPE_MSB 13 ++#define VEC_REGS_RWTYPE_LSB 12 ++// ============================================================================= ++// Register : VEC_CONTROL ++// JTAG access : synchronous ++// Description : None ++#define VEC_CONTROL_OFFSET 0x00000000 ++#define VEC_CONTROL_BITS 0x00000007 ++#define VEC_CONTROL_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_CONTROL_BARS ++// Description : Write '1' to display colour bar test pattern ++#define VEC_CONTROL_BARS_RESET 0x0 ++#define VEC_CONTROL_BARS_BITS 0x00000004 ++#define VEC_CONTROL_BARS_MSB 2 ++#define VEC_CONTROL_BARS_LSB 2 ++#define VEC_CONTROL_BARS_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_CONTROL_AUTO_REPEAT ++// Description : Write '1' to re-display same frame continuously ++#define VEC_CONTROL_AUTO_REPEAT_RESET 0x0 ++#define VEC_CONTROL_AUTO_REPEAT_BITS 0x00000002 ++#define VEC_CONTROL_AUTO_REPEAT_MSB 1 ++#define VEC_CONTROL_AUTO_REPEAT_LSB 1 ++#define VEC_CONTROL_AUTO_REPEAT_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_CONTROL_START_ARM ++// Description : Write '1' before first DMA address is written This bit always ++// reads back as '0' ++#define VEC_CONTROL_START_ARM_RESET 0x0 ++#define VEC_CONTROL_START_ARM_BITS 0x00000001 ++#define VEC_CONTROL_START_ARM_MSB 0 ++#define VEC_CONTROL_START_ARM_LSB 0 ++#define VEC_CONTROL_START_ARM_ACCESS "SC" ++// ============================================================================= ++// Register : VEC_IRQ_ENABLES ++// JTAG access : synchronous ++// Description : None ++#define VEC_IRQ_ENABLES_OFFSET 0x00000004 ++#define VEC_IRQ_ENABLES_BITS 0x03ff003f ++#define VEC_IRQ_ENABLES_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_MATCH_ROW ++// Description : Raster line at which MATCH interrupt is signalled ++#define VEC_IRQ_ENABLES_MATCH_ROW_RESET 0x000 ++#define VEC_IRQ_ENABLES_MATCH_ROW_BITS 0x03ff0000 ++#define VEC_IRQ_ENABLES_MATCH_ROW_MSB 25 ++#define VEC_IRQ_ENABLES_MATCH_ROW_LSB 16 ++#define VEC_IRQ_ENABLES_MATCH_ROW_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_MATCH ++// Description : Output raster == match_row reached ++#define VEC_IRQ_ENABLES_MATCH_RESET 0x0 ++#define VEC_IRQ_ENABLES_MATCH_BITS 0x00000020 ++#define VEC_IRQ_ENABLES_MATCH_MSB 5 ++#define VEC_IRQ_ENABLES_MATCH_LSB 5 ++#define VEC_IRQ_ENABLES_MATCH_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_ERROR ++// Description : DMA address overwritten before it was taken ++#define VEC_IRQ_ENABLES_ERROR_RESET 0x0 ++#define VEC_IRQ_ENABLES_ERROR_BITS 0x00000010 ++#define VEC_IRQ_ENABLES_ERROR_MSB 4 ++#define VEC_IRQ_ENABLES_ERROR_LSB 4 ++#define VEC_IRQ_ENABLES_ERROR_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_DONE ++// Description : Last word sent to DAC after end of video (= all clear) ++#define VEC_IRQ_ENABLES_DONE_RESET 0x0 ++#define VEC_IRQ_ENABLES_DONE_BITS 0x00000008 ++#define VEC_IRQ_ENABLES_DONE_MSB 3 ++#define VEC_IRQ_ENABLES_DONE_LSB 3 ++#define VEC_IRQ_ENABLES_DONE_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_FRAME ++// Description : Start of frame ++#define VEC_IRQ_ENABLES_FRAME_RESET 0x0 ++#define VEC_IRQ_ENABLES_FRAME_BITS 0x00000004 ++#define VEC_IRQ_ENABLES_FRAME_MSB 2 ++#define VEC_IRQ_ENABLES_FRAME_LSB 2 ++#define VEC_IRQ_ENABLES_FRAME_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_UNDERFLOW ++// Description : Underflow has occurred ++#define VEC_IRQ_ENABLES_UNDERFLOW_RESET 0x0 ++#define VEC_IRQ_ENABLES_UNDERFLOW_BITS 0x00000002 ++#define VEC_IRQ_ENABLES_UNDERFLOW_MSB 1 ++#define VEC_IRQ_ENABLES_UNDERFLOW_LSB 1 ++#define VEC_IRQ_ENABLES_UNDERFLOW_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_ENABLES_DMA ++// Description : DMA ready to accept next frame start address ++#define VEC_IRQ_ENABLES_DMA_RESET 0x0 ++#define VEC_IRQ_ENABLES_DMA_BITS 0x00000001 ++#define VEC_IRQ_ENABLES_DMA_MSB 0 ++#define VEC_IRQ_ENABLES_DMA_LSB 0 ++#define VEC_IRQ_ENABLES_DMA_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_IRQ_FLAGS ++// JTAG access : synchronous ++// Description : None ++#define VEC_IRQ_FLAGS_OFFSET 0x00000008 ++#define VEC_IRQ_FLAGS_BITS 0x0000003f ++#define VEC_IRQ_FLAGS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_MATCH ++// Description : Output raster == match_row reached ++#define VEC_IRQ_FLAGS_MATCH_RESET 0x0 ++#define VEC_IRQ_FLAGS_MATCH_BITS 0x00000020 ++#define VEC_IRQ_FLAGS_MATCH_MSB 5 ++#define VEC_IRQ_FLAGS_MATCH_LSB 5 ++#define VEC_IRQ_FLAGS_MATCH_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_ERROR ++// Description : DMA address overwritten before it was taken ++#define VEC_IRQ_FLAGS_ERROR_RESET 0x0 ++#define VEC_IRQ_FLAGS_ERROR_BITS 0x00000010 ++#define VEC_IRQ_FLAGS_ERROR_MSB 4 ++#define VEC_IRQ_FLAGS_ERROR_LSB 4 ++#define VEC_IRQ_FLAGS_ERROR_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_DONE ++// Description : Last word sent to DAC after end of video (= all clear) ++#define VEC_IRQ_FLAGS_DONE_RESET 0x0 ++#define VEC_IRQ_FLAGS_DONE_BITS 0x00000008 ++#define VEC_IRQ_FLAGS_DONE_MSB 3 ++#define VEC_IRQ_FLAGS_DONE_LSB 3 ++#define VEC_IRQ_FLAGS_DONE_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_FRAME ++// Description : Start of frame ++#define VEC_IRQ_FLAGS_FRAME_RESET 0x0 ++#define VEC_IRQ_FLAGS_FRAME_BITS 0x00000004 ++#define VEC_IRQ_FLAGS_FRAME_MSB 2 ++#define VEC_IRQ_FLAGS_FRAME_LSB 2 ++#define VEC_IRQ_FLAGS_FRAME_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_UNDERFLOW ++// Description : Underflow has occurred ++#define VEC_IRQ_FLAGS_UNDERFLOW_RESET 0x0 ++#define VEC_IRQ_FLAGS_UNDERFLOW_BITS 0x00000002 ++#define VEC_IRQ_FLAGS_UNDERFLOW_MSB 1 ++#define VEC_IRQ_FLAGS_UNDERFLOW_LSB 1 ++#define VEC_IRQ_FLAGS_UNDERFLOW_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IRQ_FLAGS_DMA ++// Description : DMA ready to accept next frame start address ++#define VEC_IRQ_FLAGS_DMA_RESET 0x0 ++#define VEC_IRQ_FLAGS_DMA_BITS 0x00000001 ++#define VEC_IRQ_FLAGS_DMA_MSB 0 ++#define VEC_IRQ_FLAGS_DMA_LSB 0 ++#define VEC_IRQ_FLAGS_DMA_ACCESS "WC" ++// ============================================================================= ++// Register : VEC_QOS ++// JTAG access : synchronous ++// Description : This register configures panic levels for the AXI ar_qos ++// quality of service field. Panic status is driven by the number ++// of rows held in the SRAM cache: ++#define VEC_QOS_OFFSET 0x0000000c ++#define VEC_QOS_BITS 0x000fffff ++#define VEC_QOS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_QOS_UQOS ++// Description : Upper AXI QOS ++#define VEC_QOS_UQOS_RESET 0x0 ++#define VEC_QOS_UQOS_BITS 0x000f0000 ++#define VEC_QOS_UQOS_MSB 19 ++#define VEC_QOS_UQOS_LSB 16 ++#define VEC_QOS_UQOS_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_QOS_ULEV ++// Description : Upper trip level (resolution = 1 / 16 of cache size) ++#define VEC_QOS_ULEV_RESET 0x0 ++#define VEC_QOS_ULEV_BITS 0x0000f000 ++#define VEC_QOS_ULEV_MSB 15 ++#define VEC_QOS_ULEV_LSB 12 ++#define VEC_QOS_ULEV_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_QOS_LQOS ++// Description : Lower AXI QOS ++#define VEC_QOS_LQOS_RESET 0x0 ++#define VEC_QOS_LQOS_BITS 0x00000f00 ++#define VEC_QOS_LQOS_MSB 11 ++#define VEC_QOS_LQOS_LSB 8 ++#define VEC_QOS_LQOS_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_QOS_LLEV ++// Description : Lower trip level (resolution = 1 / 16 of cache size) ++#define VEC_QOS_LLEV_RESET 0x0 ++#define VEC_QOS_LLEV_BITS 0x000000f0 ++#define VEC_QOS_LLEV_MSB 7 ++#define VEC_QOS_LLEV_LSB 4 ++#define VEC_QOS_LLEV_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_QOS_DQOS ++// Description : Default QOS ++#define VEC_QOS_DQOS_RESET 0x0 ++#define VEC_QOS_DQOS_BITS 0x0000000f ++#define VEC_QOS_DQOS_MSB 3 ++#define VEC_QOS_DQOS_LSB 0 ++#define VEC_QOS_DQOS_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DMA_ADDR_L ++// JTAG access : synchronous ++// Description : Lower 32-bits ++#define VEC_DMA_ADDR_L_OFFSET 0x00000010 ++#define VEC_DMA_ADDR_L_BITS 0xffffffff ++#define VEC_DMA_ADDR_L_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DMA_ADDR_L_AXI_ADDR ++// Description : Byte address of DMA transfer frame buffer. ++#define VEC_DMA_ADDR_L_AXI_ADDR_RESET 0x00000000 ++#define VEC_DMA_ADDR_L_AXI_ADDR_BITS 0xffffffff ++#define VEC_DMA_ADDR_L_AXI_ADDR_MSB 31 ++#define VEC_DMA_ADDR_L_AXI_ADDR_LSB 0 ++#define VEC_DMA_ADDR_L_AXI_ADDR_ACCESS "RWF" ++// ============================================================================= ++// Register : VEC_DMA_STRIDE ++// JTAG access : synchronous ++// Description : This register sets the line byte stride. ++#define VEC_DMA_STRIDE_OFFSET 0x00000014 ++#define VEC_DMA_STRIDE_BITS 0xffffffff ++#define VEC_DMA_STRIDE_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DMA_STRIDE_STRIDE ++// Description : Byte stride ++#define VEC_DMA_STRIDE_STRIDE_RESET 0x00000000 ++#define VEC_DMA_STRIDE_STRIDE_BITS 0xffffffff ++#define VEC_DMA_STRIDE_STRIDE_MSB 31 ++#define VEC_DMA_STRIDE_STRIDE_LSB 0 ++#define VEC_DMA_STRIDE_STRIDE_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DMA_AREA ++// JTAG access : synchronous ++// Description : Interlaced pixel area. See example driver code. ++#define VEC_DMA_AREA_OFFSET 0x00000018 ++#define VEC_DMA_AREA_BITS 0x03ff03ff ++#define VEC_DMA_AREA_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DMA_AREA_COLS_MINUS1 ++// Description : Width ++#define VEC_DMA_AREA_COLS_MINUS1_RESET 0x000 ++#define VEC_DMA_AREA_COLS_MINUS1_BITS 0x03ff0000 ++#define VEC_DMA_AREA_COLS_MINUS1_MSB 25 ++#define VEC_DMA_AREA_COLS_MINUS1_LSB 16 ++#define VEC_DMA_AREA_COLS_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1 ++// Description : Lines per field = half of lines per interlaced frame ++#define VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1_RESET 0x000 ++#define VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1_BITS 0x000003ff ++#define VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1_MSB 9 ++#define VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1_LSB 0 ++#define VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_YUV_SCALING ++// JTAG access : synchronous ++// Description : None ++#define VEC_YUV_SCALING_OFFSET 0x0000001c ++#define VEC_YUV_SCALING_BITS 0x3fffffff ++#define VEC_YUV_SCALING_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_YUV_SCALING_U10_SCALE_Y ++// Description : Y unsigned scaling factor - 8 binary places ++#define VEC_YUV_SCALING_U10_SCALE_Y_RESET 0x000 ++#define VEC_YUV_SCALING_U10_SCALE_Y_BITS 0x3ff00000 ++#define VEC_YUV_SCALING_U10_SCALE_Y_MSB 29 ++#define VEC_YUV_SCALING_U10_SCALE_Y_LSB 20 ++#define VEC_YUV_SCALING_U10_SCALE_Y_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_YUV_SCALING_S10_SCALE_U ++// Description : U signed scaling factor - 8 binary places ++#define VEC_YUV_SCALING_S10_SCALE_U_RESET 0x000 ++#define VEC_YUV_SCALING_S10_SCALE_U_BITS 0x000ffc00 ++#define VEC_YUV_SCALING_S10_SCALE_U_MSB 19 ++#define VEC_YUV_SCALING_S10_SCALE_U_LSB 10 ++#define VEC_YUV_SCALING_S10_SCALE_U_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_YUV_SCALING_S10_SCALE_V ++// Description : V signed scaling factor - 8 binary please ++#define VEC_YUV_SCALING_S10_SCALE_V_RESET 0x000 ++#define VEC_YUV_SCALING_S10_SCALE_V_BITS 0x000003ff ++#define VEC_YUV_SCALING_S10_SCALE_V_MSB 9 ++#define VEC_YUV_SCALING_S10_SCALE_V_LSB 0 ++#define VEC_YUV_SCALING_S10_SCALE_V_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_BACK_PORCH ++// JTAG access : synchronous ++// Description : None ++#define VEC_BACK_PORCH_OFFSET 0x00000020 ++#define VEC_BACK_PORCH_BITS 0x03ff03ff ++#define VEC_BACK_PORCH_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_BACK_PORCH_HBP_MINUS1 ++// Description : Horizontal back porch ++#define VEC_BACK_PORCH_HBP_MINUS1_RESET 0x000 ++#define VEC_BACK_PORCH_HBP_MINUS1_BITS 0x03ff0000 ++#define VEC_BACK_PORCH_HBP_MINUS1_MSB 25 ++#define VEC_BACK_PORCH_HBP_MINUS1_LSB 16 ++#define VEC_BACK_PORCH_HBP_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_BACK_PORCH_VBP_MINUS1 ++// Description : Vertical back porch ++#define VEC_BACK_PORCH_VBP_MINUS1_RESET 0x000 ++#define VEC_BACK_PORCH_VBP_MINUS1_BITS 0x000003ff ++#define VEC_BACK_PORCH_VBP_MINUS1_MSB 9 ++#define VEC_BACK_PORCH_VBP_MINUS1_LSB 0 ++#define VEC_BACK_PORCH_VBP_MINUS1_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_FRONT_PORCH ++// JTAG access : synchronous ++// Description : None ++#define VEC_FRONT_PORCH_OFFSET 0x00000024 ++#define VEC_FRONT_PORCH_BITS 0x03ff03ff ++#define VEC_FRONT_PORCH_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_FRONT_PORCH_HFP_MINUS1 ++// Description : Horizontal front porch ++#define VEC_FRONT_PORCH_HFP_MINUS1_RESET 0x000 ++#define VEC_FRONT_PORCH_HFP_MINUS1_BITS 0x03ff0000 ++#define VEC_FRONT_PORCH_HFP_MINUS1_MSB 25 ++#define VEC_FRONT_PORCH_HFP_MINUS1_LSB 16 ++#define VEC_FRONT_PORCH_HFP_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_FRONT_PORCH_VFP_MINUS1 ++// Description : Vertical front porch ++#define VEC_FRONT_PORCH_VFP_MINUS1_RESET 0x000 ++#define VEC_FRONT_PORCH_VFP_MINUS1_BITS 0x000003ff ++#define VEC_FRONT_PORCH_VFP_MINUS1_MSB 9 ++#define VEC_FRONT_PORCH_VFP_MINUS1_LSB 0 ++#define VEC_FRONT_PORCH_VFP_MINUS1_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_SHIFT ++// JTAG access : synchronous ++// Description : Positions of R,G,B MS bits in the memory word. Note: due to an ++// unintended red/blue swap, these fields have been renamed since ++// a previous version. There is no functional change. ++#define VEC_SHIFT_OFFSET 0x00000028 ++#define VEC_SHIFT_BITS 0x00007fff ++#define VEC_SHIFT_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_SHIFT_SHIFT_R ++// Description : Red MSB ++#define VEC_SHIFT_SHIFT_R_RESET 0x00 ++#define VEC_SHIFT_SHIFT_R_BITS 0x00007c00 ++#define VEC_SHIFT_SHIFT_R_MSB 14 ++#define VEC_SHIFT_SHIFT_R_LSB 10 ++#define VEC_SHIFT_SHIFT_R_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_SHIFT_SHIFT_G ++// Description : Green MSB ++#define VEC_SHIFT_SHIFT_G_RESET 0x00 ++#define VEC_SHIFT_SHIFT_G_BITS 0x000003e0 ++#define VEC_SHIFT_SHIFT_G_MSB 9 ++#define VEC_SHIFT_SHIFT_G_LSB 5 ++#define VEC_SHIFT_SHIFT_G_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_SHIFT_SHIFT_B ++// Description : Blue MSB ++#define VEC_SHIFT_SHIFT_B_RESET 0x00 ++#define VEC_SHIFT_SHIFT_B_BITS 0x0000001f ++#define VEC_SHIFT_SHIFT_B_MSB 4 ++#define VEC_SHIFT_SHIFT_B_LSB 0 ++#define VEC_SHIFT_SHIFT_B_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_IMASK ++// JTAG access : synchronous ++// Description : Masks for R,G,B significant bits, left-justified within 10-bit ++// fields. ++#define VEC_IMASK_OFFSET 0x0000002c ++#define VEC_IMASK_BITS 0x3fffffff ++#define VEC_IMASK_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_IMASK_MASK_R ++// Description : Red mask ++#define VEC_IMASK_MASK_R_RESET 0x000 ++#define VEC_IMASK_MASK_R_BITS 0x3ff00000 ++#define VEC_IMASK_MASK_R_MSB 29 ++#define VEC_IMASK_MASK_R_LSB 20 ++#define VEC_IMASK_MASK_R_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IMASK_MASK_G ++// Description : Green mask ++#define VEC_IMASK_MASK_G_RESET 0x000 ++#define VEC_IMASK_MASK_G_BITS 0x000ffc00 ++#define VEC_IMASK_MASK_G_MSB 19 ++#define VEC_IMASK_MASK_G_LSB 10 ++#define VEC_IMASK_MASK_G_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_IMASK_MASK_B ++// Description : Blue mask ++#define VEC_IMASK_MASK_B_RESET 0x000 ++#define VEC_IMASK_MASK_B_BITS 0x000003ff ++#define VEC_IMASK_MASK_B_MSB 9 ++#define VEC_IMASK_MASK_B_LSB 0 ++#define VEC_IMASK_MASK_B_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_MODE ++// JTAG access : synchronous ++// Description : None ++#define VEC_MODE_OFFSET 0x00000030 ++#define VEC_MODE_BITS 0x01ff003f ++#define VEC_MODE_RESET 0x01c00000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_HIGH_WATER ++// Description : ALWAYS WRITE 8'hE0 ++#define VEC_MODE_HIGH_WATER_RESET 0xe0 ++#define VEC_MODE_HIGH_WATER_BITS 0x01fe0000 ++#define VEC_MODE_HIGH_WATER_MSB 24 ++#define VEC_MODE_HIGH_WATER_LSB 17 ++#define VEC_MODE_HIGH_WATER_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_ALIGN16 ++// Description : Data: 0=BYTE aligned; 1=BEAT aligned ++#define VEC_MODE_ALIGN16_RESET 0x0 ++#define VEC_MODE_ALIGN16_BITS 0x00010000 ++#define VEC_MODE_ALIGN16_MSB 16 ++#define VEC_MODE_ALIGN16_LSB 16 ++#define VEC_MODE_ALIGN16_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_VFP_EN ++// Description : Enable vertical front porch ++#define VEC_MODE_VFP_EN_RESET 0x0 ++#define VEC_MODE_VFP_EN_BITS 0x00000020 ++#define VEC_MODE_VFP_EN_MSB 5 ++#define VEC_MODE_VFP_EN_LSB 5 ++#define VEC_MODE_VFP_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_VBP_EN ++// Description : Enable vertical back porch ++#define VEC_MODE_VBP_EN_RESET 0x0 ++#define VEC_MODE_VBP_EN_BITS 0x00000010 ++#define VEC_MODE_VBP_EN_MSB 4 ++#define VEC_MODE_VBP_EN_LSB 4 ++#define VEC_MODE_VBP_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_HFP_EN ++// Description : Enable horizontal front porch ++#define VEC_MODE_HFP_EN_RESET 0x0 ++#define VEC_MODE_HFP_EN_BITS 0x00000008 ++#define VEC_MODE_HFP_EN_MSB 3 ++#define VEC_MODE_HFP_EN_LSB 3 ++#define VEC_MODE_HFP_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_HBP_EN ++// Description : Enable horizontal back porch ++#define VEC_MODE_HBP_EN_RESET 0x0 ++#define VEC_MODE_HBP_EN_BITS 0x00000004 ++#define VEC_MODE_HBP_EN_MSB 2 ++#define VEC_MODE_HBP_EN_LSB 2 ++#define VEC_MODE_HBP_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_FIELDS_PER_FRAME_MINUS1 ++// Description : Interlaced / progressive ++#define VEC_MODE_FIELDS_PER_FRAME_MINUS1_RESET 0x0 ++#define VEC_MODE_FIELDS_PER_FRAME_MINUS1_BITS 0x00000002 ++#define VEC_MODE_FIELDS_PER_FRAME_MINUS1_MSB 1 ++#define VEC_MODE_FIELDS_PER_FRAME_MINUS1_LSB 1 ++#define VEC_MODE_FIELDS_PER_FRAME_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_MODE_FIRST_FIELD_ODD ++// Description : Interlacing order: odd/even or even/odd ++#define VEC_MODE_FIRST_FIELD_ODD_RESET 0x0 ++#define VEC_MODE_FIRST_FIELD_ODD_BITS 0x00000001 ++#define VEC_MODE_FIRST_FIELD_ODD_MSB 0 ++#define VEC_MODE_FIRST_FIELD_ODD_LSB 0 ++#define VEC_MODE_FIRST_FIELD_ODD_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_RGBSZ ++// JTAG access : synchronous ++// Description : None ++#define VEC_RGBSZ_OFFSET 0x00000034 ++#define VEC_RGBSZ_BITS 0x00030fff ++#define VEC_RGBSZ_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1 ++// Description : Pixel stride ++#define VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1_RESET 0x0 ++#define VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1_BITS 0x00030000 ++#define VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1_MSB 17 ++#define VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1_LSB 16 ++#define VEC_RGBSZ_BYTES_PER_PIXEL_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_RGBSZ_SCALE_R ++// Description : Red number of bits for shift-and-OR scaling ++#define VEC_RGBSZ_SCALE_R_RESET 0x0 ++#define VEC_RGBSZ_SCALE_R_BITS 0x00000f00 ++#define VEC_RGBSZ_SCALE_R_MSB 11 ++#define VEC_RGBSZ_SCALE_R_LSB 8 ++#define VEC_RGBSZ_SCALE_R_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_RGBSZ_SCALE_G ++// Description : Green number of bits for shift-and-OR scaling ++#define VEC_RGBSZ_SCALE_G_RESET 0x0 ++#define VEC_RGBSZ_SCALE_G_BITS 0x000000f0 ++#define VEC_RGBSZ_SCALE_G_MSB 7 ++#define VEC_RGBSZ_SCALE_G_LSB 4 ++#define VEC_RGBSZ_SCALE_G_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_RGBSZ_SCALE_B ++// Description : Blue number of bits for shift-and-OR scaling ++#define VEC_RGBSZ_SCALE_B_RESET 0x0 ++#define VEC_RGBSZ_SCALE_B_BITS 0x0000000f ++#define VEC_RGBSZ_SCALE_B_MSB 3 ++#define VEC_RGBSZ_SCALE_B_LSB 0 ++#define VEC_RGBSZ_SCALE_B_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_PANICS ++// JTAG access : synchronous ++// Description : None ++#define VEC_PANICS_OFFSET 0x00000038 ++#define VEC_PANICS_BITS 0xffffffff ++#define VEC_PANICS_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_PANICS_UCOUNT ++// Description : Upper panic count ++#define VEC_PANICS_UCOUNT_RESET 0x0000 ++#define VEC_PANICS_UCOUNT_BITS 0xffff0000 ++#define VEC_PANICS_UCOUNT_MSB 31 ++#define VEC_PANICS_UCOUNT_LSB 16 ++#define VEC_PANICS_UCOUNT_ACCESS "WC" ++// ----------------------------------------------------------------------------- ++// Field : VEC_PANICS_LCOUNT ++// Description : Lower panic count ++#define VEC_PANICS_LCOUNT_RESET 0x0000 ++#define VEC_PANICS_LCOUNT_BITS 0x0000ffff ++#define VEC_PANICS_LCOUNT_MSB 15 ++#define VEC_PANICS_LCOUNT_LSB 0 ++#define VEC_PANICS_LCOUNT_ACCESS "WC" ++// ============================================================================= ++// Register : VEC_STATUS ++// JTAG access : synchronous ++// Description : None ++#define VEC_STATUS_OFFSET 0x0000003c ++#define VEC_STATUS_BITS 0xff000000 ++#define VEC_STATUS_RESET 0x0d000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_STATUS_VERSION ++// Description : VEC module version code ++#define VEC_STATUS_VERSION_RESET 0x0d ++#define VEC_STATUS_VERSION_BITS 0xff000000 ++#define VEC_STATUS_VERSION_MSB 31 ++#define VEC_STATUS_VERSION_LSB 24 ++#define VEC_STATUS_VERSION_ACCESS "RO" ++// ============================================================================= ++// Register : VEC_DMA_ADDR_H ++// JTAG access : synchronous ++// Description : Upper 32-bits ++#define VEC_DMA_ADDR_H_OFFSET 0x00000040 ++#define VEC_DMA_ADDR_H_BITS 0xffffffff ++#define VEC_DMA_ADDR_H_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DMA_ADDR_H_AXI_ADDR ++// Description : Byte address of DMA transfer frame buffer. ++#define VEC_DMA_ADDR_H_AXI_ADDR_RESET 0x00000000 ++#define VEC_DMA_ADDR_H_AXI_ADDR_BITS 0xffffffff ++#define VEC_DMA_ADDR_H_AXI_ADDR_MSB 31 ++#define VEC_DMA_ADDR_H_AXI_ADDR_LSB 0 ++#define VEC_DMA_ADDR_H_AXI_ADDR_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_BURST_ADDR_L ++// JTAG access : synchronous ++// Description : None ++#define VEC_BURST_ADDR_L_OFFSET 0x00000044 ++#define VEC_BURST_ADDR_L_BITS 0xffffffff ++#define VEC_BURST_ADDR_L_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_BURST_ADDR_L_BURST_ADDR ++// Description : the lower 32-bits of the most recent read request sent to AXI ++// memory. ++#define VEC_BURST_ADDR_L_BURST_ADDR_RESET 0x00000000 ++#define VEC_BURST_ADDR_L_BURST_ADDR_BITS 0xffffffff ++#define VEC_BURST_ADDR_L_BURST_ADDR_MSB 31 ++#define VEC_BURST_ADDR_L_BURST_ADDR_LSB 0 ++#define VEC_BURST_ADDR_L_BURST_ADDR_ACCESS "RO" ++// ============================================================================= ++// Register : VEC_APB_TIMEOUT ++// JTAG access : synchronous ++// Description : None ++#define VEC_APB_TIMEOUT_OFFSET 0x00000048 ++#define VEC_APB_TIMEOUT_BITS 0x000103ff ++#define VEC_APB_TIMEOUT_RESET 0x00000014 ++// ----------------------------------------------------------------------------- ++// Field : VEC_APB_TIMEOUT_SLVERR_EN ++// Description : 1 = Assert PREADY and PSLVERR on timeout 0 = Assert PREADY only ++#define VEC_APB_TIMEOUT_SLVERR_EN_RESET 0x0 ++#define VEC_APB_TIMEOUT_SLVERR_EN_BITS 0x00010000 ++#define VEC_APB_TIMEOUT_SLVERR_EN_MSB 16 ++#define VEC_APB_TIMEOUT_SLVERR_EN_LSB 16 ++#define VEC_APB_TIMEOUT_SLVERR_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_APB_TIMEOUT_TIMEOUT ++// Description : Maximum AXI clock cycles to wait for responses from DAC clock ++// domain APB block ++#define VEC_APB_TIMEOUT_TIMEOUT_RESET 0x014 ++#define VEC_APB_TIMEOUT_TIMEOUT_BITS 0x000003ff ++#define VEC_APB_TIMEOUT_TIMEOUT_MSB 9 ++#define VEC_APB_TIMEOUT_TIMEOUT_LSB 0 ++#define VEC_APB_TIMEOUT_TIMEOUT_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_80 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_80_OFFSET 0x00000080 ++#define VEC_DAC_80_BITS 0x3fff3fff ++#define VEC_DAC_80_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_80_U14_DE_BGN ++// Description : Beginning of active data enable within each visible line ++#define VEC_DAC_80_U14_DE_BGN_RESET 0x0000 ++#define VEC_DAC_80_U14_DE_BGN_BITS 0x3fff0000 ++#define VEC_DAC_80_U14_DE_BGN_MSB 29 ++#define VEC_DAC_80_U14_DE_BGN_LSB 16 ++#define VEC_DAC_80_U14_DE_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_80_U14_DE_END ++// Description : End of active data enable within each visible line ++#define VEC_DAC_80_U14_DE_END_RESET 0x0000 ++#define VEC_DAC_80_U14_DE_END_BITS 0x00003fff ++#define VEC_DAC_80_U14_DE_END_MSB 13 ++#define VEC_DAC_80_U14_DE_END_LSB 0 ++#define VEC_DAC_80_U14_DE_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_84 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_84_OFFSET 0x00000084 ++#define VEC_DAC_84_BITS 0x1fff1fff ++#define VEC_DAC_84_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_84_U13_ACTIVE_RISE ++// Description : Horizontal blanking interval ++#define VEC_DAC_84_U13_ACTIVE_RISE_RESET 0x0000 ++#define VEC_DAC_84_U13_ACTIVE_RISE_BITS 0x1fff0000 ++#define VEC_DAC_84_U13_ACTIVE_RISE_MSB 28 ++#define VEC_DAC_84_U13_ACTIVE_RISE_LSB 16 ++#define VEC_DAC_84_U13_ACTIVE_RISE_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_84_U13_ACTIVE_FALL ++// Description : Horizontal blanking interval ++#define VEC_DAC_84_U13_ACTIVE_FALL_RESET 0x0000 ++#define VEC_DAC_84_U13_ACTIVE_FALL_BITS 0x00001fff ++#define VEC_DAC_84_U13_ACTIVE_FALL_MSB 12 ++#define VEC_DAC_84_U13_ACTIVE_FALL_LSB 0 ++#define VEC_DAC_84_U13_ACTIVE_FALL_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_88 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_88_OFFSET 0x00000088 ++#define VEC_DAC_88_BITS 0x1fff1fff ++#define VEC_DAC_88_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_88_U13_HALF_LINE_PERIOD ++// Description : Ratio of DAC clock to horizontal line rate, halved ++#define VEC_DAC_88_U13_HALF_LINE_PERIOD_RESET 0x0000 ++#define VEC_DAC_88_U13_HALF_LINE_PERIOD_BITS 0x1fff0000 ++#define VEC_DAC_88_U13_HALF_LINE_PERIOD_MSB 28 ++#define VEC_DAC_88_U13_HALF_LINE_PERIOD_LSB 16 ++#define VEC_DAC_88_U13_HALF_LINE_PERIOD_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_88_U13_HORZ_SYNC ++// Description : Width of horizontal sync pulses ++#define VEC_DAC_88_U13_HORZ_SYNC_RESET 0x0000 ++#define VEC_DAC_88_U13_HORZ_SYNC_BITS 0x00001fff ++#define VEC_DAC_88_U13_HORZ_SYNC_MSB 12 ++#define VEC_DAC_88_U13_HORZ_SYNC_LSB 0 ++#define VEC_DAC_88_U13_HORZ_SYNC_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_8C ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_8C_OFFSET 0x0000008c ++#define VEC_DAC_8C_BITS 0x1fff1fff ++#define VEC_DAC_8C_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_8C_U13_BURST_RISE ++// Description : Start of raised-cosine colour burst envelope ++#define VEC_DAC_8C_U13_BURST_RISE_RESET 0x0000 ++#define VEC_DAC_8C_U13_BURST_RISE_BITS 0x1fff0000 ++#define VEC_DAC_8C_U13_BURST_RISE_MSB 28 ++#define VEC_DAC_8C_U13_BURST_RISE_LSB 16 ++#define VEC_DAC_8C_U13_BURST_RISE_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_8C_U13_BURST_FALL ++// Description : End of raised-cosine colour burst envelope ++#define VEC_DAC_8C_U13_BURST_FALL_RESET 0x0000 ++#define VEC_DAC_8C_U13_BURST_FALL_BITS 0x00001fff ++#define VEC_DAC_8C_U13_BURST_FALL_MSB 12 ++#define VEC_DAC_8C_U13_BURST_FALL_LSB 0 ++#define VEC_DAC_8C_U13_BURST_FALL_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_90 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_90_OFFSET 0x00000090 ++#define VEC_DAC_90_BITS 0x1fff3fff ++#define VEC_DAC_90_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_90_U13_VERT_EQ ++// Description : Width of vertical equalisation pulses (= half line minus ++// serration) ++#define VEC_DAC_90_U13_VERT_EQ_RESET 0x0000 ++#define VEC_DAC_90_U13_VERT_EQ_BITS 0x1fff0000 ++#define VEC_DAC_90_U13_VERT_EQ_MSB 28 ++#define VEC_DAC_90_U13_VERT_EQ_LSB 16 ++#define VEC_DAC_90_U13_VERT_EQ_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_90_U14_VERT_SYNC ++// Description : Width of vertical sync pulses ++#define VEC_DAC_90_U14_VERT_SYNC_RESET 0x0000 ++#define VEC_DAC_90_U14_VERT_SYNC_BITS 0x00003fff ++#define VEC_DAC_90_U14_VERT_SYNC_MSB 13 ++#define VEC_DAC_90_U14_VERT_SYNC_LSB 0 ++#define VEC_DAC_90_U14_VERT_SYNC_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_94 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_94_OFFSET 0x00000094 ++#define VEC_DAC_94_BITS 0x03ff03ff ++#define VEC_DAC_94_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_94_U10_PRE_EQ_BGN ++// Description : Half-lines, inclusive, relative to field datum, where vertical ++// pre-equalisation pulses start ++#define VEC_DAC_94_U10_PRE_EQ_BGN_RESET 0x000 ++#define VEC_DAC_94_U10_PRE_EQ_BGN_BITS 0x03ff0000 ++#define VEC_DAC_94_U10_PRE_EQ_BGN_MSB 25 ++#define VEC_DAC_94_U10_PRE_EQ_BGN_LSB 16 ++#define VEC_DAC_94_U10_PRE_EQ_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_94_U10_PRE_EQ_END ++// Description : Half-lines, inclusive, relative to field datum, where vertical ++// pre-equalisation pulses end ++#define VEC_DAC_94_U10_PRE_EQ_END_RESET 0x000 ++#define VEC_DAC_94_U10_PRE_EQ_END_BITS 0x000003ff ++#define VEC_DAC_94_U10_PRE_EQ_END_MSB 9 ++#define VEC_DAC_94_U10_PRE_EQ_END_LSB 0 ++#define VEC_DAC_94_U10_PRE_EQ_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_98 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_98_OFFSET 0x00000098 ++#define VEC_DAC_98_BITS 0x03ff03ff ++#define VEC_DAC_98_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_98_U10_FIELD_SYNC_BGN ++// Description : Half-lines containing vertical sync pulses (inclusive) ++#define VEC_DAC_98_U10_FIELD_SYNC_BGN_RESET 0x000 ++#define VEC_DAC_98_U10_FIELD_SYNC_BGN_BITS 0x03ff0000 ++#define VEC_DAC_98_U10_FIELD_SYNC_BGN_MSB 25 ++#define VEC_DAC_98_U10_FIELD_SYNC_BGN_LSB 16 ++#define VEC_DAC_98_U10_FIELD_SYNC_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_98_U10_FIELD_SYNC_END ++// Description : Half-lines containing vertical sync pulses (inclusive) ++#define VEC_DAC_98_U10_FIELD_SYNC_END_RESET 0x000 ++#define VEC_DAC_98_U10_FIELD_SYNC_END_BITS 0x000003ff ++#define VEC_DAC_98_U10_FIELD_SYNC_END_MSB 9 ++#define VEC_DAC_98_U10_FIELD_SYNC_END_LSB 0 ++#define VEC_DAC_98_U10_FIELD_SYNC_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_9C ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_9C_OFFSET 0x0000009c ++#define VEC_DAC_9C_BITS 0x03ff03ff ++#define VEC_DAC_9C_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_9C_U10_POST_EQ_BGN ++// Description : Half-lines containing vertical post-equalisation pulses ++#define VEC_DAC_9C_U10_POST_EQ_BGN_RESET 0x000 ++#define VEC_DAC_9C_U10_POST_EQ_BGN_BITS 0x03ff0000 ++#define VEC_DAC_9C_U10_POST_EQ_BGN_MSB 25 ++#define VEC_DAC_9C_U10_POST_EQ_BGN_LSB 16 ++#define VEC_DAC_9C_U10_POST_EQ_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_9C_U10_POST_EQ_END ++// Description : Half-lines containing vertical post-equalisation pulses ++#define VEC_DAC_9C_U10_POST_EQ_END_RESET 0x000 ++#define VEC_DAC_9C_U10_POST_EQ_END_BITS 0x000003ff ++#define VEC_DAC_9C_U10_POST_EQ_END_MSB 9 ++#define VEC_DAC_9C_U10_POST_EQ_END_LSB 0 ++#define VEC_DAC_9C_U10_POST_EQ_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_A0 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_A0_OFFSET 0x000000a0 ++#define VEC_DAC_A0_BITS 0x03ff03ff ++#define VEC_DAC_A0_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A0_U10_FLD1_BURST_BGN ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A0_U10_FLD1_BURST_BGN_RESET 0x000 ++#define VEC_DAC_A0_U10_FLD1_BURST_BGN_BITS 0x03ff0000 ++#define VEC_DAC_A0_U10_FLD1_BURST_BGN_MSB 25 ++#define VEC_DAC_A0_U10_FLD1_BURST_BGN_LSB 16 ++#define VEC_DAC_A0_U10_FLD1_BURST_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A0_U10_FLD1_BURST_END ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A0_U10_FLD1_BURST_END_RESET 0x000 ++#define VEC_DAC_A0_U10_FLD1_BURST_END_BITS 0x000003ff ++#define VEC_DAC_A0_U10_FLD1_BURST_END_MSB 9 ++#define VEC_DAC_A0_U10_FLD1_BURST_END_LSB 0 ++#define VEC_DAC_A0_U10_FLD1_BURST_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_A4 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_A4_OFFSET 0x000000a4 ++#define VEC_DAC_A4_BITS 0x03ff03ff ++#define VEC_DAC_A4_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A4_U10_FLD2_BURST_BGN ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A4_U10_FLD2_BURST_BGN_RESET 0x000 ++#define VEC_DAC_A4_U10_FLD2_BURST_BGN_BITS 0x03ff0000 ++#define VEC_DAC_A4_U10_FLD2_BURST_BGN_MSB 25 ++#define VEC_DAC_A4_U10_FLD2_BURST_BGN_LSB 16 ++#define VEC_DAC_A4_U10_FLD2_BURST_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A4_U10_FLD2_BURST_END ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A4_U10_FLD2_BURST_END_RESET 0x000 ++#define VEC_DAC_A4_U10_FLD2_BURST_END_BITS 0x000003ff ++#define VEC_DAC_A4_U10_FLD2_BURST_END_MSB 9 ++#define VEC_DAC_A4_U10_FLD2_BURST_END_LSB 0 ++#define VEC_DAC_A4_U10_FLD2_BURST_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_A8 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_A8_OFFSET 0x000000a8 ++#define VEC_DAC_A8_BITS 0x03ff03ff ++#define VEC_DAC_A8_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A8_U10_FLD3_BURST_BGN ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A8_U10_FLD3_BURST_BGN_RESET 0x000 ++#define VEC_DAC_A8_U10_FLD3_BURST_BGN_BITS 0x03ff0000 ++#define VEC_DAC_A8_U10_FLD3_BURST_BGN_MSB 25 ++#define VEC_DAC_A8_U10_FLD3_BURST_BGN_LSB 16 ++#define VEC_DAC_A8_U10_FLD3_BURST_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_A8_U10_FLD3_BURST_END ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_A8_U10_FLD3_BURST_END_RESET 0x000 ++#define VEC_DAC_A8_U10_FLD3_BURST_END_BITS 0x000003ff ++#define VEC_DAC_A8_U10_FLD3_BURST_END_MSB 9 ++#define VEC_DAC_A8_U10_FLD3_BURST_END_LSB 0 ++#define VEC_DAC_A8_U10_FLD3_BURST_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_AC ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_AC_OFFSET 0x000000ac ++#define VEC_DAC_AC_BITS 0x03ff03ff ++#define VEC_DAC_AC_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_AC_U10_FLD4_BURST_BGN ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_AC_U10_FLD4_BURST_BGN_RESET 0x000 ++#define VEC_DAC_AC_U10_FLD4_BURST_BGN_BITS 0x03ff0000 ++#define VEC_DAC_AC_U10_FLD4_BURST_BGN_MSB 25 ++#define VEC_DAC_AC_U10_FLD4_BURST_BGN_LSB 16 ++#define VEC_DAC_AC_U10_FLD4_BURST_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_AC_U10_FLD4_BURST_END ++// Description : First and last full frame lines (1-based numbering) within the ++// PAL/NTSC four field sequence which require a colour burst ++#define VEC_DAC_AC_U10_FLD4_BURST_END_RESET 0x000 ++#define VEC_DAC_AC_U10_FLD4_BURST_END_BITS 0x000003ff ++#define VEC_DAC_AC_U10_FLD4_BURST_END_MSB 9 ++#define VEC_DAC_AC_U10_FLD4_BURST_END_LSB 0 ++#define VEC_DAC_AC_U10_FLD4_BURST_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_B0 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_B0_OFFSET 0x000000b0 ++#define VEC_DAC_B0_BITS 0x03ff03ff ++#define VEC_DAC_B0_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN ++// Description : First and last full visible lines (1-based numbering) in the ++// PAL/NTSC four field sequence ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN_RESET 0x000 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN_BITS 0x03ff0000 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN_MSB 25 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN_LSB 16 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B0_U10_FLD24_FULL_LINE_END ++// Description : First and last full visible lines (1-based numbering) in the ++// PAL/NTSC four field sequence ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_END_RESET 0x000 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_END_BITS 0x000003ff ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_END_MSB 9 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_END_LSB 0 ++#define VEC_DAC_B0_U10_FLD24_FULL_LINE_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_B4 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_B4_OFFSET 0x000000b4 ++#define VEC_DAC_B4_BITS 0x03ff03ff ++#define VEC_DAC_B4_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN ++// Description : First and last full visible lines (1-based numbering) in the ++// PAL/NTSC four field sequence ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN_RESET 0x000 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN_BITS 0x03ff0000 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN_MSB 25 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN_LSB 16 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_BGN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B4_U10_FLD13_FULL_LINE_END ++// Description : First and last full visible lines (1-based numbering) in the ++// PAL/NTSC four field sequence ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_END_RESET 0x000 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_END_BITS 0x000003ff ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_END_MSB 9 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_END_LSB 0 ++#define VEC_DAC_B4_U10_FLD13_FULL_LINE_END_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_B8 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_B8_OFFSET 0x000000b8 ++#define VEC_DAC_B8_BITS 0x03ff03ff ++#define VEC_DAC_B8_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B8_U10_BOT_HALF_LINE ++// Description : Top and bottom visible half-lines in 1-based standard full ++// frame numbering, for interlaced modes. Set to zero to disable. ++#define VEC_DAC_B8_U10_BOT_HALF_LINE_RESET 0x000 ++#define VEC_DAC_B8_U10_BOT_HALF_LINE_BITS 0x03ff0000 ++#define VEC_DAC_B8_U10_BOT_HALF_LINE_MSB 25 ++#define VEC_DAC_B8_U10_BOT_HALF_LINE_LSB 16 ++#define VEC_DAC_B8_U10_BOT_HALF_LINE_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_B8_U10_TOP_HALF_LINE ++// Description : Top and bottom visible half-lines in 1-based standard full ++// frame numbering, for interlaced modes. Set to zero to disable. ++#define VEC_DAC_B8_U10_TOP_HALF_LINE_RESET 0x000 ++#define VEC_DAC_B8_U10_TOP_HALF_LINE_BITS 0x000003ff ++#define VEC_DAC_B8_U10_TOP_HALF_LINE_MSB 9 ++#define VEC_DAC_B8_U10_TOP_HALF_LINE_LSB 0 ++#define VEC_DAC_B8_U10_TOP_HALF_LINE_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_BC ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_BC_OFFSET 0x000000bc ++#define VEC_DAC_BC_BITS 0x07ff07ff ++#define VEC_DAC_BC_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_BC_S11_PEDESTAL ++// Description : NTSC pedestal. For 7.5 IRE, this field is 1024 * 7.5/100. For ++// PAL, or Japanese NTSC, this field should be zero. ++#define VEC_DAC_BC_S11_PEDESTAL_RESET 0x000 ++#define VEC_DAC_BC_S11_PEDESTAL_BITS 0x07ff0000 ++#define VEC_DAC_BC_S11_PEDESTAL_MSB 26 ++#define VEC_DAC_BC_S11_PEDESTAL_LSB 16 ++#define VEC_DAC_BC_S11_PEDESTAL_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_BC_U11_HALF_LINES_PER_FIELD ++// Description : Mode = 625 PAL, Lines per field = 312.5, ++// u11_half_lines_per_field = 1+2*312 Mode = 525 NTSC, Lines per ++// field = 262.5, u11_half_lines_per_field = 1+2*262 ++#define VEC_DAC_BC_U11_HALF_LINES_PER_FIELD_RESET 0x000 ++#define VEC_DAC_BC_U11_HALF_LINES_PER_FIELD_BITS 0x000007ff ++#define VEC_DAC_BC_U11_HALF_LINES_PER_FIELD_MSB 10 ++#define VEC_DAC_BC_U11_HALF_LINES_PER_FIELD_LSB 0 ++#define VEC_DAC_BC_U11_HALF_LINES_PER_FIELD_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_C0 ++// JTAG access : synchronous ++// Description : Synopsis DesignWare control ++#define VEC_DAC_C0_OFFSET 0x000000c0 ++#define VEC_DAC_C0_BITS 0x000fffff ++#define VEC_DAC_C0_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_CABLE_ENCTR3 ++// Description : Synopsis test input ++#define VEC_DAC_C0_DWC_CABLE_ENCTR3_RESET 0x0 ++#define VEC_DAC_C0_DWC_CABLE_ENCTR3_BITS 0x00080000 ++#define VEC_DAC_C0_DWC_CABLE_ENCTR3_MSB 19 ++#define VEC_DAC_C0_DWC_CABLE_ENCTR3_LSB 19 ++#define VEC_DAC_C0_DWC_CABLE_ENCTR3_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_CABLE_CABLEOUT ++// Description : cable detect state ++#define VEC_DAC_C0_DWC_CABLE_CABLEOUT_RESET 0x0 ++#define VEC_DAC_C0_DWC_CABLE_CABLEOUT_BITS 0x00070000 ++#define VEC_DAC_C0_DWC_CABLE_CABLEOUT_MSB 18 ++#define VEC_DAC_C0_DWC_CABLE_CABLEOUT_LSB 16 ++#define VEC_DAC_C0_DWC_CABLE_CABLEOUT_ACCESS "RO" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_MUX_2 ++// Description : Select DAC channel 2 output ++#define VEC_DAC_C0_DWC_MUX_2_RESET 0x0 ++#define VEC_DAC_C0_DWC_MUX_2_BITS 0x0000c000 ++#define VEC_DAC_C0_DWC_MUX_2_MSB 15 ++#define VEC_DAC_C0_DWC_MUX_2_LSB 14 ++#define VEC_DAC_C0_DWC_MUX_2_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_MUX_1 ++// Description : Select DAC channel 1 output ++#define VEC_DAC_C0_DWC_MUX_1_RESET 0x0 ++#define VEC_DAC_C0_DWC_MUX_1_BITS 0x00003000 ++#define VEC_DAC_C0_DWC_MUX_1_MSB 13 ++#define VEC_DAC_C0_DWC_MUX_1_LSB 12 ++#define VEC_DAC_C0_DWC_MUX_1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_MUX_0 ++// Description : Select DAC channel 0 output ++#define VEC_DAC_C0_DWC_MUX_0_RESET 0x0 ++#define VEC_DAC_C0_DWC_MUX_0_BITS 0x00000c00 ++#define VEC_DAC_C0_DWC_MUX_0_MSB 11 ++#define VEC_DAC_C0_DWC_MUX_0_LSB 10 ++#define VEC_DAC_C0_DWC_MUX_0_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C0_DWC_TEST ++// Description : Fixed DAC command word ++#define VEC_DAC_C0_DWC_TEST_RESET 0x000 ++#define VEC_DAC_C0_DWC_TEST_BITS 0x000003ff ++#define VEC_DAC_C0_DWC_TEST_MSB 9 ++#define VEC_DAC_C0_DWC_TEST_LSB 0 ++#define VEC_DAC_C0_DWC_TEST_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_C4 ++// JTAG access : synchronous ++// Description : Synopsis DAC control ++#define VEC_DAC_C4_OFFSET 0x000000c4 ++#define VEC_DAC_C4_BITS 0x1fffffff ++#define VEC_DAC_C4_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_ENCTR ++// Description : Always write3'b000 ++#define VEC_DAC_C4_ENCTR_RESET 0x0 ++#define VEC_DAC_C4_ENCTR_BITS 0x1c000000 ++#define VEC_DAC_C4_ENCTR_MSB 28 ++#define VEC_DAC_C4_ENCTR_LSB 26 ++#define VEC_DAC_C4_ENCTR_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_ENSC ++// Description : Enable cable detect - write 3'b000 ++#define VEC_DAC_C4_ENSC_RESET 0x0 ++#define VEC_DAC_C4_ENSC_BITS 0x03800000 ++#define VEC_DAC_C4_ENSC_MSB 25 ++#define VEC_DAC_C4_ENSC_LSB 23 ++#define VEC_DAC_C4_ENSC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_ENDAC ++// Description : Enable DAC channel ++#define VEC_DAC_C4_ENDAC_RESET 0x0 ++#define VEC_DAC_C4_ENDAC_BITS 0x00700000 ++#define VEC_DAC_C4_ENDAC_MSB 22 ++#define VEC_DAC_C4_ENDAC_LSB 20 ++#define VEC_DAC_C4_ENDAC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_ENVBG ++// Description : Enable internal bandgap reference - write '1' ++#define VEC_DAC_C4_ENVBG_RESET 0x0 ++#define VEC_DAC_C4_ENVBG_BITS 0x00080000 ++#define VEC_DAC_C4_ENVBG_MSB 19 ++#define VEC_DAC_C4_ENVBG_LSB 19 ++#define VEC_DAC_C4_ENVBG_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_ENEXTREF ++// Description : Enable external reference - write '0' ++#define VEC_DAC_C4_ENEXTREF_RESET 0x0 ++#define VEC_DAC_C4_ENEXTREF_BITS 0x00040000 ++#define VEC_DAC_C4_ENEXTREF_MSB 18 ++#define VEC_DAC_C4_ENEXTREF_LSB 18 ++#define VEC_DAC_C4_ENEXTREF_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_DAC2GC ++// Description : DAC channel 2 gain control - write 6'd63 ++#define VEC_DAC_C4_DAC2GC_RESET 0x00 ++#define VEC_DAC_C4_DAC2GC_BITS 0x0003f000 ++#define VEC_DAC_C4_DAC2GC_MSB 17 ++#define VEC_DAC_C4_DAC2GC_LSB 12 ++#define VEC_DAC_C4_DAC2GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_DAC1GC ++// Description : DAC channel 1 gain control - write 6'd63 ++#define VEC_DAC_C4_DAC1GC_RESET 0x00 ++#define VEC_DAC_C4_DAC1GC_BITS 0x00000fc0 ++#define VEC_DAC_C4_DAC1GC_MSB 11 ++#define VEC_DAC_C4_DAC1GC_LSB 6 ++#define VEC_DAC_C4_DAC1GC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C4_DAC0GC ++// Description : DAC channel 0 gain control - write 6'd63 ++#define VEC_DAC_C4_DAC0GC_RESET 0x00 ++#define VEC_DAC_C4_DAC0GC_BITS 0x0000003f ++#define VEC_DAC_C4_DAC0GC_MSB 5 ++#define VEC_DAC_C4_DAC0GC_LSB 0 ++#define VEC_DAC_C4_DAC0GC_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_C8 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_C8_OFFSET 0x000000c8 ++#define VEC_DAC_C8_BITS 0xffffffff ++#define VEC_DAC_C8_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C8_U16_SCALE_SYNC ++// Description : Scaling applied prior to final summation to form the DAC ++// command word(s) ++#define VEC_DAC_C8_U16_SCALE_SYNC_RESET 0x0000 ++#define VEC_DAC_C8_U16_SCALE_SYNC_BITS 0xffff0000 ++#define VEC_DAC_C8_U16_SCALE_SYNC_MSB 31 ++#define VEC_DAC_C8_U16_SCALE_SYNC_LSB 16 ++#define VEC_DAC_C8_U16_SCALE_SYNC_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_C8_U16_SCALE_LUMA ++// Description : Scaling applied prior to final summation to form the DAC ++// command word(s) ++#define VEC_DAC_C8_U16_SCALE_LUMA_RESET 0x0000 ++#define VEC_DAC_C8_U16_SCALE_LUMA_BITS 0x0000ffff ++#define VEC_DAC_C8_U16_SCALE_LUMA_MSB 15 ++#define VEC_DAC_C8_U16_SCALE_LUMA_LSB 0 ++#define VEC_DAC_C8_U16_SCALE_LUMA_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_CC ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_CC_OFFSET 0x000000cc ++#define VEC_DAC_CC_BITS 0xffffffff ++#define VEC_DAC_CC_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_CC_S16_SCALE_BURST ++// Description : Scaling applied prior to final summation to form the DAC ++// command word(s) ++#define VEC_DAC_CC_S16_SCALE_BURST_RESET 0x0000 ++#define VEC_DAC_CC_S16_SCALE_BURST_BITS 0xffff0000 ++#define VEC_DAC_CC_S16_SCALE_BURST_MSB 31 ++#define VEC_DAC_CC_S16_SCALE_BURST_LSB 16 ++#define VEC_DAC_CC_S16_SCALE_BURST_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_CC_S16_SCALE_CHROMA ++// Description : Scaling applied prior to final summation to form the DAC ++// command word(s) ++#define VEC_DAC_CC_S16_SCALE_CHROMA_RESET 0x0000 ++#define VEC_DAC_CC_S16_SCALE_CHROMA_BITS 0x0000ffff ++#define VEC_DAC_CC_S16_SCALE_CHROMA_MSB 15 ++#define VEC_DAC_CC_S16_SCALE_CHROMA_LSB 0 ++#define VEC_DAC_CC_S16_SCALE_CHROMA_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_D0 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_D0_OFFSET 0x000000d0 ++#define VEC_DAC_D0_BITS 0xffffffff ++#define VEC_DAC_D0_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_D0_S16_OFFSET_LUMA ++// Description : These offsets are applied to the chroma and luma channels ++// before the final MUX ++#define VEC_DAC_D0_S16_OFFSET_LUMA_RESET 0x0000 ++#define VEC_DAC_D0_S16_OFFSET_LUMA_BITS 0xffff0000 ++#define VEC_DAC_D0_S16_OFFSET_LUMA_MSB 31 ++#define VEC_DAC_D0_S16_OFFSET_LUMA_LSB 16 ++#define VEC_DAC_D0_S16_OFFSET_LUMA_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_D0_S16_OFFSET_CHRO ++// Description : These offsets are applied to the chroma and luma channels ++// before the final MUX ++#define VEC_DAC_D0_S16_OFFSET_CHRO_RESET 0x0000 ++#define VEC_DAC_D0_S16_OFFSET_CHRO_BITS 0x0000ffff ++#define VEC_DAC_D0_S16_OFFSET_CHRO_MSB 15 ++#define VEC_DAC_D0_S16_OFFSET_CHRO_LSB 0 ++#define VEC_DAC_D0_S16_OFFSET_CHRO_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_D4 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_D4_OFFSET 0x000000d4 ++#define VEC_DAC_D4_BITS 0xffffffff ++#define VEC_DAC_D4_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_D4_NCO_FREQ ++// Description : This 64-bit frequency command is applied to the phase ++// accumulator of the NCO (numerically controlled oscillator) ++// which generates the colour sub-carrier. This value is computed ++// as ratio of sub-carrier frequency to DAC clock multiplied by ++// 2^64. ++#define VEC_DAC_D4_NCO_FREQ_RESET 0x00000000 ++#define VEC_DAC_D4_NCO_FREQ_BITS 0xffffffff ++#define VEC_DAC_D4_NCO_FREQ_MSB 31 ++#define VEC_DAC_D4_NCO_FREQ_LSB 0 ++#define VEC_DAC_D4_NCO_FREQ_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_D8 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_D8_OFFSET 0x000000d8 ++#define VEC_DAC_D8_BITS 0xffffffff ++#define VEC_DAC_D8_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_D8_NCO_FREQ ++// Description : This 64-bit frequency command is applied to the phase ++// accumulator of the NCO (numerically controlled oscillator) ++// which generates the colour sub-carrier. This value is computed ++// as ratio of sub-carrier frequency to DAC clock multiplied by ++// 2^64. ++#define VEC_DAC_D8_NCO_FREQ_RESET 0x00000000 ++#define VEC_DAC_D8_NCO_FREQ_BITS 0xffffffff ++#define VEC_DAC_D8_NCO_FREQ_MSB 31 ++#define VEC_DAC_D8_NCO_FREQ_LSB 0 ++#define VEC_DAC_D8_NCO_FREQ_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_DC ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_DC_OFFSET 0x000000dc ++#define VEC_DAC_DC_BITS 0xffffffff ++#define VEC_DAC_DC_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_DC_FIR_COEFF_CHROMA_0_6 ++// Description : FIR filter coefficients ++#define VEC_DAC_DC_FIR_COEFF_CHROMA_0_6_RESET 0x0000 ++#define VEC_DAC_DC_FIR_COEFF_CHROMA_0_6_BITS 0xffff0000 ++#define VEC_DAC_DC_FIR_COEFF_CHROMA_0_6_MSB 31 ++#define VEC_DAC_DC_FIR_COEFF_CHROMA_0_6_LSB 16 ++#define VEC_DAC_DC_FIR_COEFF_CHROMA_0_6_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_DC_FIR_COEFF_LUMA_0_6 ++// Description : FIR filter coefficients ++#define VEC_DAC_DC_FIR_COEFF_LUMA_0_6_RESET 0x0000 ++#define VEC_DAC_DC_FIR_COEFF_LUMA_0_6_BITS 0x0000ffff ++#define VEC_DAC_DC_FIR_COEFF_LUMA_0_6_MSB 15 ++#define VEC_DAC_DC_FIR_COEFF_LUMA_0_6_LSB 0 ++#define VEC_DAC_DC_FIR_COEFF_LUMA_0_6_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_E0 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_E0_OFFSET 0x000000e0 ++#define VEC_DAC_E0_BITS 0xffffffff ++#define VEC_DAC_E0_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E0_FIR_COEFF_CHROMA_1_5 ++// Description : FIR filter coefficients ++#define VEC_DAC_E0_FIR_COEFF_CHROMA_1_5_RESET 0x0000 ++#define VEC_DAC_E0_FIR_COEFF_CHROMA_1_5_BITS 0xffff0000 ++#define VEC_DAC_E0_FIR_COEFF_CHROMA_1_5_MSB 31 ++#define VEC_DAC_E0_FIR_COEFF_CHROMA_1_5_LSB 16 ++#define VEC_DAC_E0_FIR_COEFF_CHROMA_1_5_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E0_FIR_COEFF_LUMA_1_5 ++// Description : FIR filter coefficients ++#define VEC_DAC_E0_FIR_COEFF_LUMA_1_5_RESET 0x0000 ++#define VEC_DAC_E0_FIR_COEFF_LUMA_1_5_BITS 0x0000ffff ++#define VEC_DAC_E0_FIR_COEFF_LUMA_1_5_MSB 15 ++#define VEC_DAC_E0_FIR_COEFF_LUMA_1_5_LSB 0 ++#define VEC_DAC_E0_FIR_COEFF_LUMA_1_5_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_E4 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_E4_OFFSET 0x000000e4 ++#define VEC_DAC_E4_BITS 0xffffffff ++#define VEC_DAC_E4_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E4_FIR_COEFF_CHROMA_2_4 ++// Description : FIR filter coefficients ++#define VEC_DAC_E4_FIR_COEFF_CHROMA_2_4_RESET 0x0000 ++#define VEC_DAC_E4_FIR_COEFF_CHROMA_2_4_BITS 0xffff0000 ++#define VEC_DAC_E4_FIR_COEFF_CHROMA_2_4_MSB 31 ++#define VEC_DAC_E4_FIR_COEFF_CHROMA_2_4_LSB 16 ++#define VEC_DAC_E4_FIR_COEFF_CHROMA_2_4_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E4_FIR_COEFF_LUMA_2_4 ++// Description : FIR filter coefficients ++#define VEC_DAC_E4_FIR_COEFF_LUMA_2_4_RESET 0x0000 ++#define VEC_DAC_E4_FIR_COEFF_LUMA_2_4_BITS 0x0000ffff ++#define VEC_DAC_E4_FIR_COEFF_LUMA_2_4_MSB 15 ++#define VEC_DAC_E4_FIR_COEFF_LUMA_2_4_LSB 0 ++#define VEC_DAC_E4_FIR_COEFF_LUMA_2_4_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_E8 ++// JTAG access : synchronous ++// Description : None ++#define VEC_DAC_E8_OFFSET 0x000000e8 ++#define VEC_DAC_E8_BITS 0xffffffff ++#define VEC_DAC_E8_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E8_FIR_COEFF_CHROMA_3 ++// Description : FIR filter coefficients ++#define VEC_DAC_E8_FIR_COEFF_CHROMA_3_RESET 0x0000 ++#define VEC_DAC_E8_FIR_COEFF_CHROMA_3_BITS 0xffff0000 ++#define VEC_DAC_E8_FIR_COEFF_CHROMA_3_MSB 31 ++#define VEC_DAC_E8_FIR_COEFF_CHROMA_3_LSB 16 ++#define VEC_DAC_E8_FIR_COEFF_CHROMA_3_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_E8_FIR_COEFF_LUMA_3 ++// Description : FIR filter coefficients ++#define VEC_DAC_E8_FIR_COEFF_LUMA_3_RESET 0x0000 ++#define VEC_DAC_E8_FIR_COEFF_LUMA_3_BITS 0x0000ffff ++#define VEC_DAC_E8_FIR_COEFF_LUMA_3_MSB 15 ++#define VEC_DAC_E8_FIR_COEFF_LUMA_3_LSB 0 ++#define VEC_DAC_E8_FIR_COEFF_LUMA_3_ACCESS "RW" ++// ============================================================================= ++// Register : VEC_DAC_EC ++// JTAG access : synchronous ++// Description : Misc. control ++#define VEC_DAC_EC_OFFSET 0x000000ec ++#define VEC_DAC_EC_BITS 0x001fffff ++#define VEC_DAC_EC_RESET 0x00000000 ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_SLOW_CLOCK ++// Description : Doubles the raised-cosine rate ++#define VEC_DAC_EC_SLOW_CLOCK_RESET 0x0 ++#define VEC_DAC_EC_SLOW_CLOCK_BITS 0x00100000 ++#define VEC_DAC_EC_SLOW_CLOCK_MSB 20 ++#define VEC_DAC_EC_SLOW_CLOCK_LSB 20 ++#define VEC_DAC_EC_SLOW_CLOCK_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_FIR_RMINUS1 ++// Description : Select 1, 3, 5 or 7 FIR taps ++#define VEC_DAC_EC_FIR_RMINUS1_RESET 0x0 ++#define VEC_DAC_EC_FIR_RMINUS1_BITS 0x000c0000 ++#define VEC_DAC_EC_FIR_RMINUS1_MSB 19 ++#define VEC_DAC_EC_FIR_RMINUS1_LSB 18 ++#define VEC_DAC_EC_FIR_RMINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_VERT_FULL_NOT_HALF ++// Description : Disable half-line pulses during VBI ++#define VEC_DAC_EC_VERT_FULL_NOT_HALF_RESET 0x0 ++#define VEC_DAC_EC_VERT_FULL_NOT_HALF_BITS 0x00020000 ++#define VEC_DAC_EC_VERT_FULL_NOT_HALF_MSB 17 ++#define VEC_DAC_EC_VERT_FULL_NOT_HALF_LSB 17 ++#define VEC_DAC_EC_VERT_FULL_NOT_HALF_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_SEQ_EN ++// Description : Enable NCO reset ++#define VEC_DAC_EC_SEQ_EN_RESET 0x0 ++#define VEC_DAC_EC_SEQ_EN_BITS 0x00010000 ++#define VEC_DAC_EC_SEQ_EN_MSB 16 ++#define VEC_DAC_EC_SEQ_EN_LSB 16 ++#define VEC_DAC_EC_SEQ_EN_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_U2_FLD_MASK ++// Description : Field sequence ++#define VEC_DAC_EC_U2_FLD_MASK_RESET 0x0 ++#define VEC_DAC_EC_U2_FLD_MASK_BITS 0x0000c000 ++#define VEC_DAC_EC_U2_FLD_MASK_MSB 15 ++#define VEC_DAC_EC_U2_FLD_MASK_LSB 14 ++#define VEC_DAC_EC_U2_FLD_MASK_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_U4_SEQ_MASK ++// Description : NCO reset sequence ++#define VEC_DAC_EC_U4_SEQ_MASK_RESET 0x0 ++#define VEC_DAC_EC_U4_SEQ_MASK_BITS 0x00003c00 ++#define VEC_DAC_EC_U4_SEQ_MASK_MSB 13 ++#define VEC_DAC_EC_U4_SEQ_MASK_LSB 10 ++#define VEC_DAC_EC_U4_SEQ_MASK_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_INTERP_RATE_MINUS1 ++// Description : Interpolation rate 2<=R<=16 ++#define VEC_DAC_EC_INTERP_RATE_MINUS1_RESET 0x0 ++#define VEC_DAC_EC_INTERP_RATE_MINUS1_BITS 0x000003c0 ++#define VEC_DAC_EC_INTERP_RATE_MINUS1_MSB 9 ++#define VEC_DAC_EC_INTERP_RATE_MINUS1_LSB 6 ++#define VEC_DAC_EC_INTERP_RATE_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_INTERP_SHIFT_MINUS1 ++// Description : Power-of-2 scaling after interpolation ++#define VEC_DAC_EC_INTERP_SHIFT_MINUS1_RESET 0x0 ++#define VEC_DAC_EC_INTERP_SHIFT_MINUS1_BITS 0x0000003c ++#define VEC_DAC_EC_INTERP_SHIFT_MINUS1_MSB 5 ++#define VEC_DAC_EC_INTERP_SHIFT_MINUS1_LSB 2 ++#define VEC_DAC_EC_INTERP_SHIFT_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1 ++// Description : Interlaced / progressive ++#define VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1_RESET 0x0 ++#define VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1_BITS 0x00000002 ++#define VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1_MSB 1 ++#define VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1_LSB 1 ++#define VEC_DAC_EC_FIELDS_PER_FRAME_MINUS1_ACCESS "RW" ++// ----------------------------------------------------------------------------- ++// Field : VEC_DAC_EC_PAL_EN ++// Description : Enable phase alternate line (PAL) mode ++#define VEC_DAC_EC_PAL_EN_RESET 0x0 ++#define VEC_DAC_EC_PAL_EN_BITS 0x00000001 ++#define VEC_DAC_EC_PAL_EN_MSB 0 ++#define VEC_DAC_EC_PAL_EN_LSB 0 ++#define VEC_DAC_EC_PAL_EN_ACCESS "RW" ++// ============================================================================= ++#endif // VEC_REGS_DEFINED diff --git a/target/linux/bcm27xx/patches-6.1/950-0888-v4l2-Add-pisp-compression-format-support-to-v4l2.patch b/target/linux/bcm27xx/patches-6.1/950-0888-v4l2-Add-pisp-compression-format-support-to-v4l2.patch new file mode 100644 index 0000000000..cf0b02c64b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0888-v4l2-Add-pisp-compression-format-support-to-v4l2.patch @@ -0,0 +1,75 @@ +From 3a419974ba02d32795a5ecfaf3c020f23173b6a1 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Tue, 14 Feb 2023 20:58:59 +0000 +Subject: [PATCH] v4l2: Add pisp compression format support to v4l2 + +Signed-off-by: Naushir Patuck +--- + 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 */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0889-media-rp1-Add-CFE-Camera-Front-End-support.patch b/target/linux/bcm27xx/patches-6.1/950-0889-media-rp1-Add-CFE-Camera-Front-End-support.patch new file mode 100644 index 0000000000..038633b74e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0889-media-rp1-Add-CFE-Camera-Front-End-support.patch @@ -0,0 +1,4527 @@ +From 8a31623de7f034f6521b348e9a510e78a6e7e493 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Tue, 14 Feb 2023 17:30:12 +0000 +Subject: [PATCH] media: rp1: Add CFE (Camera Front End) support + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/raspberrypi/Kconfig | 1 + + drivers/media/platform/raspberrypi/Makefile | 1 + + .../platform/raspberrypi/rp1_cfe/Kconfig | 14 + + .../platform/raspberrypi/rp1_cfe/Makefile | 6 + + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 2186 +++++++++++++++++ + .../media/platform/raspberrypi/rp1_cfe/cfe.h | 40 + + .../platform/raspberrypi/rp1_cfe/cfe_fmts.h | 294 +++ + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 446 ++++ + .../media/platform/raspberrypi/rp1_cfe/csi2.h | 75 + + .../media/platform/raspberrypi/rp1_cfe/dphy.c | 177 ++ + .../media/platform/raspberrypi/rp1_cfe/dphy.h | 26 + + .../raspberrypi/rp1_cfe/pisp_common.h | 69 + + .../platform/raspberrypi/rp1_cfe/pisp_fe.c | 563 +++++ + .../platform/raspberrypi/rp1_cfe/pisp_fe.h | 53 + + .../raspberrypi/rp1_cfe/pisp_fe_config.h | 272 ++ + .../raspberrypi/rp1_cfe/pisp_statistics.h | 62 + + .../platform/raspberrypi/rp1_cfe/pisp_types.h | 144 ++ + 17 files changed, 4429 insertions(+) + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/Kconfig + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/Makefile + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/cfe.c + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/cfe.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/csi2.c + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/csi2.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/dphy.c + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/dphy.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h + create mode 100644 drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h + +--- a/drivers/media/platform/raspberrypi/Kconfig ++++ b/drivers/media/platform/raspberrypi/Kconfig +@@ -3,3 +3,4 @@ + comment "Raspberry Pi media platform drivers" + + source "drivers/media/platform/raspberrypi/pisp_be/Kconfig" ++source "drivers/media/platform/raspberrypi/rp1_cfe/Kconfig" +--- a/drivers/media/platform/raspberrypi/Makefile ++++ b/drivers/media/platform/raspberrypi/Makefile +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 + + obj-y += pisp_be/ ++obj-y += rp1_cfe/ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/Kconfig +@@ -0,0 +1,14 @@ ++# RP1 V4L2 camera support ++ ++config VIDEO_RP1_CFE ++ tristate "RP1 Camera Frond End (CFE) video capture driver" ++ depends on VIDEO_DEV ++ select VIDEO_V4L2_SUBDEV_API ++ select MEDIA_CONTROLLER ++ select VIDEOBUF2_DMA_CONTIG ++ select V4L2_FWNODE ++ help ++ Say Y here to enable support for the RP1 Camera Front End. ++ ++ To compile this driver as a module, choose M here. The module will be ++ called rp1-cfe. +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for RP1 Camera Front End driver ++# ++rp1-cfe-objs := cfe.o csi2.o pisp_fe.o dphy.o ++obj-$(CONFIG_VIDEO_RP1_CFE) += rp1-cfe.o +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -0,0 +1,2186 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * RP1 Camera Front End Driver ++ * ++ * Copyright (C) 2021-2022 - Raspberry Pi Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "cfe.h" ++#include "cfe_fmts.h" ++#include "csi2.h" ++#include "pisp_fe.h" ++#include "pisp_fe_config.h" ++#include "pisp_statistics.h" ++ ++#define CFE_MODULE_NAME "rp1-cfe" ++#define CFE_VERSION "1.0" ++ ++bool cfe_debug_irq; ++ ++#define cfe_dbg_irq(fmt, arg...) \ ++ do { \ ++ if (cfe_debug_irq) \ ++ dev_dbg(&cfe->pdev->dev, fmt, ##arg); \ ++ } while (0) ++#define cfe_dbg(fmt, arg...) dev_dbg(&cfe->pdev->dev, fmt, ##arg) ++#define cfe_info(fmt, arg...) dev_info(&cfe->pdev->dev, fmt, ##arg) ++#define cfe_err(fmt, arg...) dev_err(&cfe->pdev->dev, fmt, ##arg) ++ ++/* MIPICFG registers */ ++#define MIPICFG_CFG 0x004 ++#define MIPICFG_INTR 0x028 ++#define MIPICFG_INTE 0x02c ++#define MIPICFG_INTF 0x030 ++#define MIPICFG_INTS 0x034 ++ ++#define MIPICFG_CFG_SEL_CSI BIT(0) ++ ++#define MIPICFG_INT_CSI_DMA BIT(0) ++#define MIPICFG_INT_CSI_HOST BIT(2) ++#define MIPICFG_INT_PISP_FE BIT(4) ++ ++#define BPL_ALIGNMENT 16 ++#define MAX_BYTESPERLINE 0xffffff00 ++#define MAX_BUFFER_SIZE 0xffffff00 ++/* ++ * Max width is therefore determined by the max stride divided by the number of ++ * bits per pixel. ++ * ++ * However, to avoid overflow issues let's use a 16k maximum. This lets us ++ * calculate 16k * 16k * 4 with 32bits. If we need higher maximums, a careful ++ * review and adjustment of the code is needed so that it will deal with ++ * overflows correctly. ++ */ ++#define MAX_WIDTH 16384 ++#define MAX_HEIGHT MAX_WIDTH ++/* Define a nominal minimum image size */ ++#define MIN_WIDTH 16 ++#define MIN_HEIGHT 16 ++/* Default size of the embedded buffer */ ++#define DEFAULT_EMBEDDED_SIZE 8192 ++ ++const struct v4l2_mbus_framefmt cfe_default_format = { ++ .width = 640, ++ .height = 480, ++ .code = MEDIA_BUS_FMT_SRGGB10_1X10, ++ .field = V4L2_FIELD_NONE, ++ .colorspace = V4L2_COLORSPACE_RAW, ++ .ycbcr_enc = V4L2_YCBCR_ENC_601, ++ .quantization = V4L2_QUANTIZATION_FULL_RANGE, ++ .xfer_func = V4L2_XFER_FUNC_NONE, ++}; ++ ++const struct v4l2_mbus_framefmt cfe_default_meta_format = { ++ .width = 8192, ++ .height = 1, ++ .code = MEDIA_BUS_FMT_SENSOR_DATA, ++}; ++ ++enum node_ids { ++ /* CSI2 HW output nodes first. */ ++ CSI2_CH0, ++ CSI2_CH1_EMBEDDED, ++ CSI2_CH2, ++ CSI2_CH3, ++ /* FE only nodes from here on. */ ++ FE_OUT0, ++ FE_OUT1, ++ FE_STATS, ++ FE_CONFIG, ++ NUM_NODES ++}; ++ ++struct node_description { ++ unsigned int id; ++ const char *name; ++ enum v4l2_buf_type buf_type; ++ unsigned int cap; ++ unsigned int pad_flags; ++ unsigned int link_pad; ++}; ++ ++/* Must match the ordering of enum ids */ ++static const struct node_description node_desc[NUM_NODES] = { ++ [CSI2_CH0] = { ++ .name = "csi2_ch0", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = CSI2_NUM_CHANNELS + 0 ++ }, ++ /* This node is assigned for the embedded data channel! */ ++ [CSI2_CH1_EMBEDDED] = { ++ .name = "embedded", ++ .buf_type = V4L2_BUF_TYPE_META_CAPTURE, ++ .cap = V4L2_CAP_META_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = CSI2_NUM_CHANNELS + 1 ++ }, ++ [CSI2_CH2] = { ++ .name = "csi2_ch2", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ .cap = V4L2_CAP_META_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = CSI2_NUM_CHANNELS + 2 ++ }, ++ [CSI2_CH3] = { ++ .name = "csi2_ch3", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ .cap = V4L2_CAP_META_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = CSI2_NUM_CHANNELS + 3 ++ }, ++ [FE_OUT0] = { ++ .name = "fe_image0", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = FE_OUTPUT0_PAD ++ }, ++ [FE_OUT1] = { ++ .name = "fe_image1", ++ .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, ++ .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = FE_OUTPUT1_PAD ++ }, ++ [FE_STATS] = { ++ .name = "fe_stats", ++ .buf_type = V4L2_BUF_TYPE_META_CAPTURE, ++ .cap = V4L2_CAP_META_CAPTURE, ++ .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = FE_STATS_PAD ++ }, ++ [FE_CONFIG] = { ++ .name = "fe_config", ++ .buf_type = V4L2_BUF_TYPE_META_OUTPUT, ++ .cap = V4L2_CAP_META_OUTPUT, ++ .pad_flags = MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT, ++ .link_pad = FE_CONFIG_PAD ++ }, ++}; ++ ++#define is_fe_node(node) (((node)->id) >= FE_OUT0) ++#define is_csi2_node(node) (!is_fe_node(node)) ++#define is_image_output_node(node) \ ++ (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ++#define is_meta_output_node(node) \ ++ (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_CAPTURE) ++#define is_meta_input_node(node) \ ++ (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_OUTPUT) ++#define is_meta_node(node) (is_meta_output_node(node) || is_meta_input_node(node)) ++ ++/* To track state across all nodes. */ ++#define NUM_STATES 5 ++#define NODE_REGISTERED BIT(0) ++#define NODE_ENABLED BIT(1) ++#define NODE_STREAMING BIT(2) ++#define FS_INT BIT(3) ++#define FE_INT BIT(4) ++ ++struct cfe_buffer { ++ struct vb2_v4l2_buffer vb; ++ struct list_head list; ++}; ++ ++struct cfe_config_buffer { ++ struct cfe_buffer buf; ++ struct pisp_fe_config config; ++}; ++ ++static inline struct cfe_buffer *to_cfe_buffer(struct vb2_buffer *vb) ++{ ++ return container_of(vb, struct cfe_buffer, vb.vb2_buf); ++} ++ ++static inline ++struct cfe_config_buffer *to_cfe_config_buffer(struct cfe_buffer *buf) ++{ ++ return container_of(buf, struct cfe_config_buffer, buf); ++} ++ ++struct cfe_node { ++ unsigned int id; ++ /* Pointer pointing to current v4l2_buffer */ ++ struct cfe_buffer *cur_frm; ++ /* Pointer pointing to next v4l2_buffer */ ++ struct cfe_buffer *next_frm; ++ /* Used to store current pixel format */ ++ struct v4l2_format fmt; ++ /* Buffer queue used in video-buf */ ++ struct vb2_queue buffer_queue; ++ /* Queue of filled frames */ ++ struct list_head dma_queue; ++ /* lock used to access this structure */ ++ struct mutex lock; ++ /* Identifies video device for this channel */ ++ struct video_device video_dev; ++ /* Pointer to the parent handle */ ++ struct cfe_device *cfe; ++ struct media_pad pad; ++}; ++ ++struct cfe_device { ++ struct dentry *debugfs; ++ struct kref kref; ++ ++ /* V4l2 specific parameters */ ++ struct v4l2_async_subdev asd; ++ ++ /* peripheral base address */ ++ void __iomem *mipi_cfg_base; ++ ++ struct clk *clk; ++ ++ /* V4l2 device */ ++ struct v4l2_device v4l2_dev; ++ struct media_device mdev; ++ struct media_pipeline pipe; ++ ++ /* IRQ lock for node state and DMA queues */ ++ spinlock_t state_lock; ++ bool job_ready; ++ bool job_queued; ++ ++ /* parent device */ ++ struct platform_device *pdev; ++ /* subdevice async Notifier */ ++ struct v4l2_async_notifier notifier; ++ ++ /* ptr to sub device */ ++ struct v4l2_subdev *sensor; ++ ++ struct cfe_node node[NUM_NODES]; ++ DECLARE_BITMAP(node_flags, NUM_STATES * NUM_NODES); ++ ++ struct csi2_device csi2; ++ struct pisp_fe_device fe; ++ ++ bool sensor_embedded_data; ++ int fe_csi2_channel; ++ ++ unsigned int sequence; ++ u64 ts; ++}; ++ ++static inline bool is_fe_enabled(struct cfe_device *cfe) ++{ ++ return cfe->fe_csi2_channel != -1; ++} ++ ++static inline struct cfe_device *to_cfe_device(struct v4l2_device *v4l2_dev) ++{ ++ return container_of(v4l2_dev, struct cfe_device, v4l2_dev); ++} ++ ++static inline u32 cfg_reg_read(struct cfe_device *cfe, u32 offset) ++{ ++ return readl(cfe->mipi_cfg_base + offset); ++} ++ ++static inline void cfg_reg_write(struct cfe_device *cfe, u32 offset, u32 val) ++{ ++ writel(val, cfe->mipi_cfg_base + offset); ++} ++ ++static bool check_state(struct cfe_device *cfe, unsigned long state, ++ unsigned int node_id) ++{ ++ unsigned long bit; ++ ++ for_each_set_bit(bit, &state, sizeof(state)) { ++ if (!test_bit(bit + (node_id * NUM_STATES), cfe->node_flags)) ++ return false; ++ } ++ return true; ++} ++ ++static void set_state(struct cfe_device *cfe, unsigned long state, ++ unsigned int node_id) ++{ ++ unsigned long bit; ++ ++ for_each_set_bit(bit, &state, sizeof(state)) ++ set_bit(bit + (node_id * NUM_STATES), cfe->node_flags); ++} ++ ++static void clear_state(struct cfe_device *cfe, unsigned long state, ++ unsigned int node_id) ++{ ++ unsigned long bit; ++ ++ for_each_set_bit(bit, &state, sizeof(state)) ++ clear_bit(bit + (node_id * NUM_STATES), cfe->node_flags); ++} ++ ++static bool test_any_node(struct cfe_device *cfe, unsigned long cond) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ if (check_state(cfe, cond, i)) ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool test_all_nodes(struct cfe_device *cfe, unsigned long precond, ++ unsigned long cond) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ if (check_state(cfe, precond, i)) { ++ if (!check_state(cfe, cond, i)) ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++static void clear_all_nodes(struct cfe_device *cfe, unsigned long precond, ++ unsigned long state) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ if (check_state(cfe, precond, i)) ++ clear_state(cfe, state, i); ++ } ++} ++ ++static int mipi_cfg_regs_show(struct seq_file *s, void *data) ++{ ++ struct cfe_device *cfe = s->private; ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(&cfe->pdev->dev); ++ if (ret) ++ return ret; ++ ++#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", cfg_reg_read(cfe, reg)) ++ DUMP(MIPICFG_CFG); ++ DUMP(MIPICFG_INTR); ++ DUMP(MIPICFG_INTE); ++ DUMP(MIPICFG_INTF); ++ DUMP(MIPICFG_INTS); ++#undef DUMP ++ ++ pm_runtime_put(&cfe->pdev->dev); ++ ++ return 0; ++} ++ ++static int format_show(struct seq_file *s, void *data) ++{ ++ struct cfe_device *cfe = s->private; ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ unsigned long sb, state = 0; ++ ++ for (sb = 0; sb < NUM_STATES; sb++) { ++ if (check_state(cfe, BIT(sb), i)) ++ state |= BIT(sb); ++ } ++ ++ seq_printf(s, "\nNode %u (%s) state: 0x%lx\n", i, ++ node_desc[i].name, state); ++ ++ if (is_image_output_node(node)) ++ seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\n" ++ "resolution: %ux%u\nbpl: %u\nsize: %u\n", ++ V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat), ++ node->fmt.fmt.pix.pixelformat, ++ node->fmt.fmt.pix.width, ++ node->fmt.fmt.pix.height, ++ node->fmt.fmt.pix.bytesperline, ++ node->fmt.fmt.pix.sizeimage); ++ else ++ seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\nsize: %u\n", ++ V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat), ++ node->fmt.fmt.meta.dataformat, ++ node->fmt.fmt.meta.buffersize); ++ } ++ ++ return 0; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(mipi_cfg_regs); ++DEFINE_SHOW_ATTRIBUTE(format); ++ ++/* Format setup functions */ ++const struct cfe_fmt *find_format_by_code(u32 code) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(formats); i++) { ++ if (formats[i].code == code) ++ return &formats[i]; ++ } ++ ++ return NULL; ++} ++ ++static const struct cfe_fmt *find_format_by_pix(u32 pixelformat) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(formats); i++) { ++ if (formats[i].fourcc == pixelformat) ++ return &formats[i]; ++ } ++ ++ return NULL; ++} ++ ++static int cfe_calc_format_size_bpl(struct cfe_device *cfe, ++ const struct cfe_fmt *fmt, ++ struct v4l2_format *f) ++{ ++ unsigned int min_bytesperline; ++ ++ v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, MAX_WIDTH, 2, ++ &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 0, 0); ++ ++ min_bytesperline = ++ ALIGN((f->fmt.pix.width * fmt->depth) >> 3, BPL_ALIGNMENT); ++ ++ if (f->fmt.pix.bytesperline > min_bytesperline && ++ f->fmt.pix.bytesperline <= MAX_BYTESPERLINE) ++ f->fmt.pix.bytesperline = ++ ALIGN(f->fmt.pix.bytesperline, BPL_ALIGNMENT); ++ else ++ f->fmt.pix.bytesperline = min_bytesperline; ++ ++ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; ++ ++ cfe_dbg("%s: " V4L2_FOURCC_CONV " size: %ux%u bpl:%u img_size:%u\n", ++ __func__, V4L2_FOURCC_CONV_ARGS(f->fmt.pix.pixelformat), ++ f->fmt.pix.width, f->fmt.pix.height, ++ f->fmt.pix.bytesperline, f->fmt.pix.sizeimage); ++ ++ return 0; ++} ++ ++static void cfe_schedule_next_csi2_job(struct cfe_device *cfe) ++{ ++ struct cfe_buffer *buf; ++ unsigned int i; ++ dma_addr_t addr; ++ ++ for (i = 0; i < CSI2_NUM_CHANNELS; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ unsigned int stride, size; ++ ++ if (!check_state(cfe, NODE_STREAMING, i)) ++ continue; ++ ++ buf = list_first_entry(&node->dma_queue, struct cfe_buffer, ++ list); ++ node->next_frm = buf; ++ list_del(&buf->list); ++ ++ cfe_dbg("%s: [%s] buffer:%p\n", ++ __func__, node_desc[node->id].name, &buf->vb.vb2_buf); ++ ++ if (is_meta_node(node)) { ++ size = node->fmt.fmt.meta.buffersize; ++ stride = 0; ++ } else { ++ size = node->fmt.fmt.pix.sizeimage; ++ stride = node->fmt.fmt.pix.bytesperline; ++ } ++ ++ addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); ++ csi2_set_buffer(&cfe->csi2, node->id, addr, stride, size); ++ } ++} ++ ++static void cfe_schedule_next_pisp_job(struct cfe_device *cfe) ++{ ++ struct vb2_buffer *vb2_bufs[FE_NUM_PADS] = { 0 }; ++ struct cfe_config_buffer *config_buf; ++ struct cfe_buffer *buf; ++ unsigned int i; ++ ++ for (i = CSI2_NUM_CHANNELS; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ if (!check_state(cfe, NODE_STREAMING, i)) ++ continue; ++ ++ buf = list_first_entry(&node->dma_queue, struct cfe_buffer, ++ list); ++ ++ cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, &buf->vb.vb2_buf); ++ ++ node->next_frm = buf; ++ vb2_bufs[node_desc[i].link_pad] = &buf->vb.vb2_buf; ++ list_del(&buf->list); ++ } ++ ++ config_buf = to_cfe_config_buffer(cfe->node[FE_CONFIG].next_frm); ++ pisp_fe_submit_job(&cfe->fe, vb2_bufs, &config_buf->config); ++} ++ ++static bool cfe_check_job_ready(struct cfe_device *cfe) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ if (!check_state(cfe, NODE_ENABLED, i)) ++ continue; ++ ++ if (list_empty(&node->dma_queue)) { ++ cfe_dbg_irq("%s: [%s] has no buffer, unable to schedule job\n", ++ __func__, node_desc[i].name); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++static void cfe_prepare_next_job(struct cfe_device *cfe) ++{ ++ cfe->job_queued = true; ++ cfe_schedule_next_csi2_job(cfe); ++ if (is_fe_enabled(cfe)) ++ cfe_schedule_next_pisp_job(cfe); ++ ++ /* Flag if another job is ready after this. */ ++ cfe->job_ready = cfe_check_job_ready(cfe); ++ ++ cfe_dbg_irq("%s: end with scheduled job\n", __func__); ++} ++ ++static void cfe_process_buffer_complete(struct cfe_node *node, ++ unsigned int sequence) ++{ ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, ++ &node->cur_frm->vb.vb2_buf); ++ ++ node->cur_frm->vb.sequence = sequence; ++ vb2_buffer_done(&node->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); ++} ++ ++static void cfe_queue_event_sof(struct cfe_node *node) ++{ ++ struct v4l2_event event = { ++ .type = V4L2_EVENT_FRAME_SYNC, ++ .u.frame_sync.frame_sequence = node->cfe->sequence, ++ }; ++ ++ v4l2_event_queue(&node->video_dev, &event); ++} ++ ++static void cfe_sof_isr_handler(struct cfe_node *node) ++{ ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg_irq("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, ++ cfe->sequence); ++ ++ node->cur_frm = node->next_frm; ++ node->next_frm = NULL; ++ ++ /* ++ * If this is the first node to see a frame start, sample the ++ * timestamp to use for all frames across all channels. ++ */ ++ if (!test_any_node(cfe, NODE_STREAMING | FS_INT)) ++ cfe->ts = ktime_get_ns(); ++ ++ set_state(cfe, FS_INT, node->id); ++ ++ /* If all nodes have seen a frame start, we can queue another job. */ ++ if (test_all_nodes(cfe, NODE_STREAMING, FS_INT)) ++ cfe->job_queued = false; ++ ++ if (node->cur_frm) ++ node->cur_frm->vb.vb2_buf.timestamp = cfe->ts; ++ ++ if (is_image_output_node(node)) ++ cfe_queue_event_sof(node); ++} ++ ++static void cfe_eof_isr_handler(struct cfe_node *node) ++{ ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg_irq("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, ++ cfe->sequence); ++ ++ if (node->cur_frm) ++ cfe_process_buffer_complete(node, cfe->sequence); ++ ++ node->cur_frm = NULL; ++ set_state(cfe, FE_INT, node->id); ++ ++ /* ++ * If all nodes have seen a frame end, we can increment ++ * the sequence counter now. ++ */ ++ if (test_all_nodes(cfe, NODE_STREAMING, FE_INT)) { ++ cfe->sequence++; ++ clear_all_nodes(cfe, NODE_STREAMING, FE_INT | FS_INT); ++ } ++} ++ ++static irqreturn_t cfe_isr(int irq, void *dev) ++{ ++ struct cfe_device *cfe = dev; ++ unsigned int i; ++ bool sof[NUM_NODES] = {0}, eof[NUM_NODES] = {0}, lci[NUM_NODES] = {0}; ++ u32 sts; ++ ++ sts = cfg_reg_read(cfe, MIPICFG_INTS); ++ ++ if (sts & MIPICFG_INT_CSI_DMA) ++ csi2_isr(&cfe->csi2, sof, eof, lci); ++ ++ if (sts & MIPICFG_INT_PISP_FE) ++ pisp_fe_isr(&cfe->fe, sof + CSI2_NUM_CHANNELS, ++ eof + CSI2_NUM_CHANNELS); ++ ++ spin_lock(&cfe->state_lock); ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ /* ++ * The check_state(NODE_STREAMING) is to ensure we do not loop ++ * over the CSI2_CHx nodes when the FE is active since they ++ * generate interrupts even though the node is not streaming. ++ */ ++ if (!check_state(cfe, NODE_STREAMING, i) || ++ !(sof[i] || eof[i] || lci[i])) ++ continue; ++ ++ /* ++ * There are 3 cases where we could get FS + FE_ACK at ++ * the same time: ++ * 1) FE of the current frame, and FS of the next frame. ++ * 2) FS + FE of the same frame. ++ * 3) FE of the current frame, and FS + FE of the next ++ * frame. To handle this, see the sof handler below. ++ * ++ * (1) is handled implicitly by the ordering of the FE and FS ++ * handlers below. ++ */ ++ if (eof[i]) { ++ /* ++ * The condition below tests for (2). Run the FS handler ++ * first before the FE handler, both for the current ++ * frame. ++ */ ++ if (sof[i] && !check_state(cfe, FS_INT, i)) { ++ cfe_sof_isr_handler(node); ++ sof[i] = false; ++ } ++ ++ cfe_eof_isr_handler(node); ++ } ++ ++ if (sof[i]) { ++ /* ++ * The condition below tests for (3). In such cases, we ++ * come in here with FS flag set in the node state from ++ * the previous frame since it only gets cleared in ++ * eof_isr_handler(). Handle the FE for the previous ++ * frame first before the FS handler for the current ++ * frame. ++ */ ++ if (check_state(cfe, FS_INT, node->id)) { ++ cfe_dbg("%s: [%s] Handling missing previous FE interrupt\n", ++ __func__, node_desc[node->id].name); ++ cfe_eof_isr_handler(node); ++ } ++ ++ cfe_sof_isr_handler(node); ++ } ++ ++ if (!cfe->job_queued && cfe->job_ready) ++ cfe_prepare_next_job(cfe); ++ } ++ ++ spin_unlock(&cfe->state_lock); ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * Stream helpers ++ */ ++ ++static void cfe_start_channel(struct cfe_node *node) ++{ ++ struct cfe_device *cfe = node->cfe; ++ struct v4l2_subdev_state *state; ++ struct v4l2_mbus_framefmt *source_fmt; ++ const struct cfe_fmt *fmt; ++ unsigned long flags; ++ unsigned int width = 0, height = 0; ++ bool start_fe = is_fe_enabled(cfe) && ++ test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING); ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (start_fe || is_image_output_node(node)) { ++ width = node->fmt.fmt.pix.width; ++ height = node->fmt.fmt.pix.height; ++ } ++ ++ state = v4l2_subdev_lock_and_get_active_state(&cfe->csi2.sd); ++ ++ if (start_fe) { ++ WARN_ON(!is_fe_enabled(cfe)); ++ cfe_dbg("%s: %s using csi2 channel %d\n", ++ __func__, node_desc[FE_OUT0].name, ++ cfe->fe_csi2_channel); ++ ++ source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, cfe->fe_csi2_channel); ++ fmt = find_format_by_code(source_fmt->code); ++ ++ /* ++ * Start the associated CSI2 Channel as well. ++ * ++ * Must write to the ADDR register to latch the ctrl values ++ * even if we are connected to the front end. Once running, ++ * this is handled by the CSI2 AUTO_ARM mode. ++ */ ++ csi2_start_channel(&cfe->csi2, cfe->fe_csi2_channel, ++ fmt->csi_dt, CSI2_MODE_FE_STREAMING, ++ true, false, width, height); ++ csi2_set_buffer(&cfe->csi2, cfe->fe_csi2_channel, 0, 0, -1); ++ pisp_fe_start(&cfe->fe); ++ } ++ ++ if (is_csi2_node(node)) { ++ u32 mode = CSI2_MODE_NORMAL; ++ ++ source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, ++ node_desc[node->id].link_pad - CSI2_NUM_CHANNELS); ++ fmt = find_format_by_code(source_fmt->code); ++ ++ if (is_image_output_node(node)) { ++ if (node->fmt.fmt.pix.pixelformat == ++ fmt->remap[CFE_REMAP_16BIT]) ++ mode = CSI2_MODE_REMAP; ++ else if (node->fmt.fmt.pix.pixelformat == ++ fmt->remap[CFE_REMAP_COMPRESSED]) { ++ mode = CSI2_MODE_COMPRESSED; ++ csi2_set_compression(&cfe->csi2, node->id, ++ CSI2_COMPRESSION_DELTA, 0, ++ 0); ++ } ++ } ++ /* Unconditionally start this CSI2 channel. */ ++ csi2_start_channel(&cfe->csi2, node->id, fmt->csi_dt, ++ mode, ++ /* Auto arm */ ++ false, ++ /* Pack bytes */ ++ node->id == CSI2_CH1_EMBEDDED ? true : false, ++ width, height); ++ } ++ ++ v4l2_subdev_unlock_state(state); ++ ++ spin_lock_irqsave(&cfe->state_lock, flags); ++ if (cfe->job_ready && test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) ++ cfe_prepare_next_job(cfe); ++ spin_unlock_irqrestore(&cfe->state_lock, flags); ++} ++ ++static void cfe_stop_channel(struct cfe_node *node, bool fe_stop) ++{ ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s] fe_stop %u\n", __func__, ++ node_desc[node->id].name, fe_stop); ++ ++ if (fe_stop) { ++ csi2_stop_channel(&cfe->csi2, cfe->fe_csi2_channel); ++ pisp_fe_stop(&cfe->fe); ++ } ++ ++ if (is_csi2_node(node)) ++ csi2_stop_channel(&cfe->csi2, node->id); ++} ++ ++static void cfe_return_buffers(struct cfe_node *node, ++ enum vb2_buffer_state state) ++{ ++ struct cfe_device *cfe = node->cfe; ++ struct cfe_buffer *buf, *tmp; ++ unsigned long flags; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ spin_lock_irqsave(&cfe->state_lock, flags); ++ list_for_each_entry_safe(buf, tmp, &node->dma_queue, list) { ++ list_del(&buf->list); ++ vb2_buffer_done(&buf->vb.vb2_buf, state); ++ } ++ ++ if (node->cur_frm) ++ vb2_buffer_done(&node->cur_frm->vb.vb2_buf, state); ++ if (node->next_frm && node->cur_frm != node->next_frm) ++ vb2_buffer_done(&node->next_frm->vb.vb2_buf, state); ++ ++ node->cur_frm = NULL; ++ node->next_frm = NULL; ++ spin_unlock_irqrestore(&cfe->state_lock, flags); ++} ++ ++/* ++ * vb2 ops ++ */ ++ ++static int cfe_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, ++ unsigned int *nplanes, unsigned int sizes[], ++ struct device *alloc_devs[]) ++{ ++ struct cfe_node *node = vb2_get_drv_priv(vq); ++ struct cfe_device *cfe = node->cfe; ++ unsigned int size = is_image_output_node(node) ? ++ node->fmt.fmt.pix.sizeimage : ++ node->fmt.fmt.meta.buffersize; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (vq->num_buffers + *nbuffers < 3) ++ *nbuffers = 3 - vq->num_buffers; ++ ++ if (*nplanes) { ++ if (sizes[0] < size) { ++ cfe_err("sizes[0] %i < size %u\n", sizes[0], size); ++ return -EINVAL; ++ } ++ size = sizes[0]; ++ } ++ ++ *nplanes = 1; ++ sizes[0] = size; ++ ++ return 0; ++} ++ ++static int cfe_buffer_prepare(struct vb2_buffer *vb) ++{ ++ struct cfe_node *node = vb2_get_drv_priv(vb->vb2_queue); ++ struct cfe_device *cfe = node->cfe; ++ struct cfe_buffer *buf = to_cfe_buffer(vb); ++ unsigned long size; ++ ++ cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, ++ vb); ++ ++ size = is_image_output_node(node) ? node->fmt.fmt.pix.sizeimage : ++ node->fmt.fmt.meta.buffersize; ++ if (vb2_plane_size(vb, 0) < size) { ++ cfe_err("data will not fit into plane (%lu < %lu)\n", ++ vb2_plane_size(vb, 0), size); ++ return -EINVAL; ++ } ++ ++ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); ++ ++ if (node->id == FE_CONFIG) { ++ struct cfe_config_buffer *b = to_cfe_config_buffer(buf); ++ void *addr = vb2_plane_vaddr(vb, 0); ++ ++ memcpy(&b->config, addr, sizeof(struct pisp_fe_config)); ++ return pisp_fe_validate_config(&cfe->fe, &b->config, ++ &cfe->node[FE_OUT0].fmt, ++ &cfe->node[FE_OUT1].fmt); ++ } ++ ++ return 0; ++} ++ ++static void cfe_buffer_queue(struct vb2_buffer *vb) ++{ ++ struct cfe_node *node = vb2_get_drv_priv(vb->vb2_queue); ++ struct cfe_device *cfe = node->cfe; ++ struct cfe_buffer *buf = to_cfe_buffer(vb); ++ unsigned long flags; ++ ++ cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, ++ vb); ++ ++ spin_lock_irqsave(&cfe->state_lock, flags); ++ ++ list_add_tail(&buf->list, &node->dma_queue); ++ ++ if (!cfe->job_ready) ++ cfe->job_ready = cfe_check_job_ready(cfe); ++ ++ if (!cfe->job_queued && cfe->job_ready && ++ test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) { ++ cfe_dbg("Preparing job immediately for channel %u\n", ++ node->id); ++ cfe_prepare_next_job(cfe); ++ } ++ ++ spin_unlock_irqrestore(&cfe->state_lock, flags); ++} ++ ++static int cfe_start_streaming(struct vb2_queue *vq, unsigned int count) ++{ ++ struct v4l2_mbus_config mbus_config = { 0 }; ++ struct cfe_node *node = vb2_get_drv_priv(vq); ++ struct cfe_device *cfe = node->cfe; ++ int ret; ++ ++ cfe_dbg("%s: [%s] begin.\n", __func__, node_desc[node->id].name); ++ ++ if (!check_state(cfe, NODE_ENABLED, node->id)) { ++ cfe_err("%s node link is not enabled.\n", ++ node_desc[node->id].name); ++ return -EINVAL; ++ } ++ ++ ret = pm_runtime_resume_and_get(&cfe->pdev->dev); ++ if (ret < 0) { ++ cfe_err("pm_runtime_resume_and_get failed\n"); ++ goto err_streaming; ++ } ++ ++ ret = media_pipeline_start(&node->pad, &cfe->pipe); ++ if (ret < 0) { ++ cfe_err("Failed to start media pipeline: %d\n", ret); ++ goto err_pm_put; ++ } ++ ++ clear_state(cfe, FS_INT | FE_INT, node->id); ++ set_state(cfe, NODE_STREAMING, node->id); ++ cfe_start_channel(node); ++ ++ if (!test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) { ++ cfe_dbg("Not all nodes are set to streaming yet!\n"); ++ return 0; ++ } ++ ++ cfg_reg_write(cfe, MIPICFG_CFG, MIPICFG_CFG_SEL_CSI); ++ cfg_reg_write(cfe, MIPICFG_INTE, MIPICFG_INT_CSI_DMA | MIPICFG_INT_PISP_FE); ++ ++ cfe->csi2.active_data_lanes = cfe->csi2.dphy.num_lanes; ++ cfe_dbg("Running with %u data lanes\n", cfe->csi2.active_data_lanes); ++ ++ ret = v4l2_subdev_call(cfe->sensor, pad, get_mbus_config, 0, ++ &mbus_config); ++ if (ret < 0 && ret != -ENOIOCTLCMD) { ++ cfe_err("g_mbus_config failed\n"); ++ goto err_pm_put; ++ } ++ ++ cfe->csi2.active_data_lanes = mbus_config.bus.mipi_csi2.num_data_lanes; ++ if (!cfe->csi2.active_data_lanes) ++ cfe->csi2.active_data_lanes = cfe->csi2.dphy.num_lanes; ++ if (cfe->csi2.active_data_lanes > cfe->csi2.dphy.num_lanes) { ++ cfe_err("Device has requested %u data lanes, which is >%u configured in DT\n", ++ cfe->csi2.active_data_lanes, cfe->csi2.dphy.num_lanes); ++ ret = -EINVAL; ++ goto err_disable_cfe; ++ } ++ ++ cfe_dbg("Starting sensor streaming\n"); ++ ++ csi2_open_rx(&cfe->csi2); ++ ++ cfe->sequence = 0; ++ ret = v4l2_subdev_call(cfe->sensor, video, s_stream, 1); ++ if (ret < 0) { ++ cfe_err("stream on failed in subdev\n"); ++ goto err_disable_cfe; ++ } ++ ++ cfe_dbg("%s: [%s] end.\n", __func__, node_desc[node->id].name); ++ ++ return 0; ++ ++err_disable_cfe: ++ csi2_close_rx(&cfe->csi2); ++ cfe_stop_channel(node, true); ++ media_pipeline_stop(&node->pad); ++err_pm_put: ++ pm_runtime_put(&cfe->pdev->dev); ++err_streaming: ++ cfe_return_buffers(node, VB2_BUF_STATE_QUEUED); ++ clear_state(cfe, NODE_STREAMING, node->id); ++ ++ return ret; ++} ++ ++static void cfe_stop_streaming(struct vb2_queue *vq) ++{ ++ struct cfe_node *node = vb2_get_drv_priv(vq); ++ struct cfe_device *cfe = node->cfe; ++ unsigned long flags; ++ bool fe_stop; ++ ++ cfe_dbg("%s: [%s] begin.\n", __func__, node_desc[node->id].name); ++ ++ spin_lock_irqsave(&cfe->state_lock, flags); ++ fe_stop = is_fe_enabled(cfe) && ++ test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING); ++ ++ cfe->job_ready = false; ++ clear_state(cfe, NODE_STREAMING, node->id); ++ spin_unlock_irqrestore(&cfe->state_lock, flags); ++ ++ cfe_stop_channel(node, fe_stop); ++ ++ if (!test_any_node(cfe, NODE_STREAMING)) { ++ /* Stop streaming the sensor and disable the peripheral. */ ++ if (v4l2_subdev_call(cfe->sensor, video, s_stream, 0) < 0) ++ cfe_err("stream off failed in subdev\n"); ++ ++ csi2_close_rx(&cfe->csi2); ++ ++ cfg_reg_write(cfe, MIPICFG_INTE, 0); ++ } ++ ++ media_pipeline_stop(&node->pad); ++ ++ /* Clear all queued buffers for the node */ ++ cfe_return_buffers(node, VB2_BUF_STATE_ERROR); ++ ++ pm_runtime_put(&cfe->pdev->dev); ++ ++ cfe_dbg("%s: [%s] end.\n", __func__, node_desc[node->id].name); ++} ++ ++static const struct vb2_ops cfe_video_qops = { ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++ .queue_setup = cfe_queue_setup, ++ .buf_prepare = cfe_buffer_prepare, ++ .buf_queue = cfe_buffer_queue, ++ .start_streaming = cfe_start_streaming, ++ .stop_streaming = cfe_stop_streaming, ++}; ++ ++/* ++ * v4l2 ioctl ops ++ */ ++ ++static int cfe_querycap(struct file *file, void *priv, ++ struct v4l2_capability *cap) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ strscpy(cap->driver, CFE_MODULE_NAME, sizeof(cap->driver)); ++ strscpy(cap->card, CFE_MODULE_NAME, sizeof(cap->card)); ++ ++ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", ++ dev_name(&cfe->pdev->dev)); ++ ++ cap->capabilities |= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE | ++ V4L2_CAP_META_OUTPUT; ++ ++ return 0; ++} ++ ++static int cfe_enum_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ unsigned int i, j; ++ ++ if (!is_image_output_node(node)) ++ return -EINVAL; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ for (i = 0, j = 0; i < ARRAY_SIZE(formats); i++) { ++ if (f->mbus_code && formats[i].code != f->mbus_code) ++ continue; ++ ++ if (formats[i].flags & CFE_FORMAT_FLAG_META_OUT || ++ formats[i].flags & CFE_FORMAT_FLAG_META_CAP) ++ continue; ++ ++ if (is_fe_node(node) && ++ !(formats[i].flags & CFE_FORMAT_FLAG_FE_OUT)) ++ continue; ++ ++ if (j == f->index) { ++ f->pixelformat = formats[i].fourcc; ++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ return 0; ++ } ++ j++; ++ } ++ ++ return -EINVAL; ++} ++ ++static int cfe_g_fmt(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (f->type != node->buffer_queue.type) ++ return -EINVAL; ++ ++ *f = node->fmt; ++ ++ return 0; ++} ++ ++static int try_fmt_vid_cap(struct cfe_node *node, struct v4l2_format *f) ++{ ++ struct cfe_device *cfe = node->cfe; ++ const struct cfe_fmt *fmt; ++ ++ cfe_dbg("%s: [%s] %ux%u, V4L2 pix " V4L2_FOURCC_CONV "\n", ++ __func__, node_desc[node->id].name, ++ f->fmt.pix.width, f->fmt.pix.height, ++ V4L2_FOURCC_CONV_ARGS(f->fmt.pix.pixelformat)); ++ ++ if (!is_image_output_node(node)) ++ return -EINVAL; ++ ++ /* ++ * Default to a format that works for both CSI2 and FE. ++ */ ++ fmt = find_format_by_pix(f->fmt.pix.pixelformat); ++ if (!fmt) ++ fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10); ++ ++ f->fmt.pix.pixelformat = fmt->fourcc; ++ ++ if (is_fe_node(node) && fmt->remap[CFE_REMAP_16BIT]) { ++ f->fmt.pix.pixelformat = fmt->remap[CFE_REMAP_16BIT]; ++ fmt = find_format_by_pix(f->fmt.pix.pixelformat); ++ } ++ ++ f->fmt.pix.field = V4L2_FIELD_NONE; ++ ++ cfe_calc_format_size_bpl(cfe, fmt, f); ++ ++ return 0; ++} ++ ++static int cfe_s_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ struct vb2_queue *q = &node->buffer_queue; ++ int ret; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (vb2_is_busy(q)) ++ return -EBUSY; ++ ++ ret = try_fmt_vid_cap(node, f); ++ if (ret) ++ return ret; ++ ++ node->fmt = *f; ++ ++ cfe_dbg("%s: Set %ux%u, V4L2 pix " V4L2_FOURCC_CONV "\n", __func__, ++ node->fmt.fmt.pix.width, node->fmt.fmt.pix.height, ++ V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat)); ++ ++ return 0; ++} ++ ++static int cfe_try_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ return try_fmt_vid_cap(node, f); ++} ++ ++static int cfe_enum_fmt_meta(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (!is_meta_node(node) || f->index != 0) ++ return -EINVAL; ++ ++ switch (node->id) { ++ case CSI2_CH1_EMBEDDED: ++ f->pixelformat = V4L2_META_FMT_SENSOR_DATA; ++ return 0; ++ case FE_STATS: ++ f->pixelformat = V4L2_META_FMT_RPI_FE_STATS; ++ return 0; ++ case FE_CONFIG: ++ f->pixelformat = V4L2_META_FMT_RPI_FE_CFG; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static int try_fmt_meta(struct cfe_node *node, struct v4l2_format *f) ++{ ++ switch (node->id) { ++ case CSI2_CH1_EMBEDDED: ++ f->fmt.meta.dataformat = V4L2_META_FMT_SENSOR_DATA; ++ if (!f->fmt.meta.buffersize) ++ f->fmt.meta.buffersize = DEFAULT_EMBEDDED_SIZE; ++ f->fmt.meta.buffersize = ++ min_t(u32, f->fmt.meta.buffersize, MAX_BUFFER_SIZE); ++ f->fmt.meta.buffersize = ++ ALIGN(f->fmt.meta.buffersize, BPL_ALIGNMENT); ++ return 0; ++ case FE_STATS: ++ f->fmt.meta.dataformat = V4L2_META_FMT_RPI_FE_STATS; ++ f->fmt.meta.buffersize = sizeof(struct pisp_statistics); ++ return 0; ++ case FE_CONFIG: ++ f->fmt.meta.dataformat = V4L2_META_FMT_RPI_FE_CFG; ++ f->fmt.meta.buffersize = sizeof(struct pisp_fe_config); ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static int cfe_s_fmt_meta(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ struct vb2_queue *q = &node->buffer_queue; ++ int ret; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (vb2_is_busy(q)) ++ return -EBUSY; ++ ++ if (f->type != node->buffer_queue.type) ++ return -EINVAL; ++ ++ ret = try_fmt_meta(node, f); ++ if (ret) ++ return ret; ++ ++ node->fmt = *f; ++ ++ cfe_dbg("%s: Set " V4L2_FOURCC_CONV "\n", __func__, ++ V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat)); ++ ++ return 0; ++} ++ ++static int cfe_try_fmt_meta(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ return try_fmt_meta(node, f); ++} ++ ++static int cfe_enum_framesizes(struct file *file, void *priv, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ const struct cfe_fmt *fmt; ++ ++ cfe_dbg("%s [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (fsize->index > 0) ++ return -EINVAL; ++ ++ /* check for valid format */ ++ fmt = find_format_by_pix(fsize->pixel_format); ++ if (!fmt) { ++ cfe_dbg("Invalid pixel code: %x\n", fsize->pixel_format); ++ return -EINVAL; ++ } ++ ++ /* TODO: Do we have limits on the step_width? */ ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; ++ fsize->stepwise.min_width = MIN_WIDTH; ++ fsize->stepwise.max_width = MAX_WIDTH; ++ fsize->stepwise.step_width = 2; ++ fsize->stepwise.min_height = MIN_HEIGHT; ++ fsize->stepwise.max_height = MAX_HEIGHT; ++ fsize->stepwise.step_height = 1; ++ ++ return 0; ++} ++ ++static int cfe_subscribe_event(struct v4l2_fh *fh, ++ const struct v4l2_event_subscription *sub) ++{ ++ struct cfe_node *node = video_get_drvdata(fh->vdev); ++ ++ switch (sub->type) { ++ case V4L2_EVENT_FRAME_SYNC: ++ if (!is_image_output_node(node)) ++ break; ++ ++ return v4l2_event_subscribe(fh, sub, 2, NULL); ++ case V4L2_EVENT_SOURCE_CHANGE: ++ if (is_meta_input_node(node)) ++ break; ++ ++ return v4l2_event_subscribe(fh, sub, 4, NULL); ++ } ++ ++ return v4l2_ctrl_subscribe_event(fh, sub); ++} ++ ++static const struct v4l2_ioctl_ops cfe_ioctl_ops = { ++ .vidioc_querycap = cfe_querycap, ++ .vidioc_enum_fmt_vid_cap = cfe_enum_fmt_vid_cap, ++ .vidioc_g_fmt_vid_cap = cfe_g_fmt, ++ .vidioc_s_fmt_vid_cap = cfe_s_fmt_vid_cap, ++ .vidioc_try_fmt_vid_cap = cfe_try_fmt_vid_cap, ++ ++ .vidioc_enum_fmt_meta_cap = cfe_enum_fmt_meta, ++ .vidioc_g_fmt_meta_cap = cfe_g_fmt, ++ .vidioc_s_fmt_meta_cap = cfe_s_fmt_meta, ++ .vidioc_try_fmt_meta_cap = cfe_try_fmt_meta, ++ ++ .vidioc_enum_fmt_meta_out = cfe_enum_fmt_meta, ++ .vidioc_g_fmt_meta_out = cfe_g_fmt, ++ .vidioc_s_fmt_meta_out = cfe_s_fmt_meta, ++ .vidioc_try_fmt_meta_out = cfe_try_fmt_meta, ++ ++ .vidioc_enum_framesizes = cfe_enum_framesizes, ++ ++ .vidioc_reqbufs = vb2_ioctl_reqbufs, ++ .vidioc_create_bufs = vb2_ioctl_create_bufs, ++ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, ++ .vidioc_querybuf = vb2_ioctl_querybuf, ++ .vidioc_qbuf = vb2_ioctl_qbuf, ++ .vidioc_dqbuf = vb2_ioctl_dqbuf, ++ .vidioc_expbuf = vb2_ioctl_expbuf, ++ .vidioc_streamon = vb2_ioctl_streamon, ++ .vidioc_streamoff = vb2_ioctl_streamoff, ++ ++ .vidioc_subscribe_event = cfe_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++static void cfe_notify(struct v4l2_subdev *sd, unsigned int notification, ++ void *arg) ++{ ++ struct cfe_device *cfe = to_cfe_device(sd->v4l2_dev); ++ unsigned int i; ++ ++ switch (notification) { ++ case V4L2_DEVICE_NOTIFY_EVENT: ++ for (i = 0; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ if (check_state(cfe, NODE_REGISTERED, i)) ++ continue; ++ ++ v4l2_event_queue(&node->video_dev, arg); ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++/* cfe capture driver file operations */ ++static const struct v4l2_file_operations cfe_fops = { ++ .owner = THIS_MODULE, ++ .open = v4l2_fh_open, ++ .release = vb2_fop_release, ++ .poll = vb2_fop_poll, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = vb2_fop_mmap, ++}; ++ ++static int cfe_video_link_validate(struct media_link *link) ++{ ++ struct video_device *vd = container_of(link->sink->entity, ++ struct video_device, entity); ++ struct cfe_node *node = container_of(vd, struct cfe_node, video_dev); ++ struct cfe_device *cfe = node->cfe; ++ struct v4l2_mbus_framefmt *source_fmt; ++ struct v4l2_subdev_state *state; ++ struct v4l2_subdev *source_sd; ++ int ret = 0; ++ ++ cfe_dbg("%s: [%s] link \"%s\":%u -> \"%s\":%u\n", __func__, ++ node_desc[node->id].name, ++ link->source->entity->name, link->source->index, ++ link->sink->entity->name, link->sink->index); ++ ++ if (!media_entity_remote_source_pad_unique(link->sink->entity)) { ++ cfe_err("video node %s pad not connected\n", vd->name); ++ return -ENOTCONN; ++ } ++ ++ source_sd = media_entity_to_v4l2_subdev(link->source->entity); ++ ++ state = v4l2_subdev_lock_and_get_active_state(source_sd); ++ ++ source_fmt = v4l2_subdev_get_pad_format(source_sd, state, ++ link->source->index); ++ if (!source_fmt) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (is_image_output_node(node)) { ++ struct v4l2_pix_format *pix_fmt = &node->fmt.fmt.pix; ++ const struct cfe_fmt *fmt; ++ ++ if (source_fmt->width != pix_fmt->width || ++ source_fmt->height != pix_fmt->height) { ++ cfe_err("Wrong width or height %ux%u (remote pad set to %ux%u)\n", ++ pix_fmt->width, pix_fmt->height, ++ source_fmt->width, ++ source_fmt->height); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ fmt = find_format_by_code(source_fmt->code); ++ if (!fmt || fmt->fourcc != pix_fmt->pixelformat) { ++ cfe_err("Format mismatch!\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ } else if (node->id == CSI2_CH1_EMBEDDED) { ++ struct v4l2_meta_format *meta_fmt = &node->fmt.fmt.meta; ++ ++ if (source_fmt->width * source_fmt->height != ++ meta_fmt->buffersize || ++ source_fmt->code != MEDIA_BUS_FMT_SENSOR_DATA) { ++ cfe_err("WARNING: Wrong metadata width/height/code %ux%u %08x (remote pad set to %ux%u %08x)\n", ++ meta_fmt->buffersize, 1, ++ MEDIA_BUS_FMT_SENSOR_DATA, ++ source_fmt->width, ++ source_fmt->height, ++ source_fmt->code); ++ /* TODO: this should throw an error eventually */ ++ } ++ } ++ ++out: ++ v4l2_subdev_unlock_state(state); ++ ++ return ret; ++} ++ ++static const struct media_entity_operations cfe_media_entity_ops = { ++ .link_validate = cfe_video_link_validate, ++}; ++ ++static int cfe_video_link_notify(struct media_link *link, u32 flags, ++ unsigned int notification) ++{ ++ struct media_device *mdev = link->graph_obj.mdev; ++ struct cfe_device *cfe = container_of(mdev, struct cfe_device, mdev); ++ struct media_entity *fe = &cfe->fe.sd.entity; ++ struct media_entity *csi2 = &cfe->csi2.sd.entity; ++ unsigned long lock_flags; ++ unsigned int i; ++ ++ if (notification != MEDIA_DEV_NOTIFY_POST_LINK_CH) ++ return 0; ++ ++ cfe_dbg("%s: %s[%u] -> %s[%u] 0x%x", __func__, ++ link->source->entity->name, link->source->index, ++ link->sink->entity->name, link->sink->index, flags); ++ ++ spin_lock_irqsave(&cfe->state_lock, lock_flags); ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ if (link->sink->entity != &cfe->node[i].video_dev.entity && ++ link->source->entity != &cfe->node[i].video_dev.entity) ++ continue; ++ ++ if (link->flags & MEDIA_LNK_FL_ENABLED) ++ set_state(cfe, NODE_ENABLED, i); ++ else ++ clear_state(cfe, NODE_ENABLED, i); ++ ++ break; ++ } ++ ++ spin_unlock_irqrestore(&cfe->state_lock, lock_flags); ++ ++ if (link->source->entity != csi2) ++ return 0; ++ if (link->sink->index != 0) ++ return 0; ++ if (link->source->index == node_desc[CSI2_CH1_EMBEDDED].link_pad) ++ return 0; ++ ++ cfe->fe_csi2_channel = -1; ++ if (link->sink->entity == fe && (link->flags & MEDIA_LNK_FL_ENABLED)) { ++ if (link->source->index == node_desc[CSI2_CH0].link_pad) ++ cfe->fe_csi2_channel = CSI2_CH0; ++ else if (link->source->index == node_desc[CSI2_CH2].link_pad) ++ cfe->fe_csi2_channel = CSI2_CH2; ++ else if (link->source->index == node_desc[CSI2_CH3].link_pad) ++ cfe->fe_csi2_channel = CSI2_CH3; ++ } ++ ++ if (is_fe_enabled(cfe)) ++ cfe_dbg("%s: Found CSI2:%d -> FE:0 link\n", __func__, ++ cfe->fe_csi2_channel); ++ else ++ cfe_dbg("%s: Unable to find CSI2:x -> FE:0 link\n", __func__); ++ ++ return 0; ++} ++ ++static const struct media_device_ops cfe_media_device_ops = { ++ .link_notify = cfe_video_link_notify, ++}; ++ ++static void cfe_release(struct kref *kref) ++{ ++ struct cfe_device *cfe = container_of(kref, struct cfe_device, kref); ++ ++ media_device_cleanup(&cfe->mdev); ++ ++ kfree(cfe); ++} ++ ++static void cfe_put(struct cfe_device *cfe) ++{ ++ kref_put(&cfe->kref, cfe_release); ++} ++ ++static void cfe_get(struct cfe_device *cfe) ++{ ++ kref_get(&cfe->kref); ++} ++ ++static void cfe_node_release(struct video_device *vdev) ++{ ++ struct cfe_node *node = video_get_drvdata(vdev); ++ ++ cfe_put(node->cfe); ++} ++ ++static int cfe_register_node(struct cfe_device *cfe, int id) ++{ ++ struct video_device *vdev; ++ const struct cfe_fmt *fmt; ++ struct vb2_queue *q; ++ struct cfe_node *node = &cfe->node[id]; ++ int ret; ++ ++ node->cfe = cfe; ++ node->id = id; ++ ++ if (is_image_output_node(node)) { ++ fmt = find_format_by_code(cfe_default_format.code); ++ if (!fmt) { ++ cfe_err("Failed to find format code\n"); ++ return -EINVAL; ++ } ++ ++ node->fmt.fmt.pix.pixelformat = fmt->fourcc; ++ v4l2_fill_pix_format(&node->fmt.fmt.pix, &cfe_default_format); ++ ++ ret = try_fmt_vid_cap(node, &node->fmt); ++ if (ret) ++ return ret; ++ } else { ++ ret = try_fmt_meta(node, &node->fmt); ++ if (ret) ++ return ret; ++ } ++ node->fmt.type = node_desc[id].buf_type; ++ ++ mutex_init(&node->lock); ++ ++ q = &node->buffer_queue; ++ q->type = node_desc[id].buf_type; ++ q->io_modes = VB2_MMAP | VB2_DMABUF; ++ q->drv_priv = node; ++ q->ops = &cfe_video_qops; ++ q->mem_ops = &vb2_dma_contig_memops; ++ q->buf_struct_size = id == FE_CONFIG ? sizeof(struct cfe_config_buffer) ++ : sizeof(struct cfe_buffer); ++ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ q->lock = &node->lock; ++ q->min_buffers_needed = 1; ++ q->dev = &cfe->pdev->dev; ++ ++ ret = vb2_queue_init(q); ++ if (ret) { ++ cfe_err("vb2_queue_init() failed\n"); ++ return ret; ++ } ++ ++ INIT_LIST_HEAD(&node->dma_queue); ++ ++ vdev = &node->video_dev; ++ vdev->release = cfe_node_release; ++ vdev->fops = &cfe_fops; ++ vdev->ioctl_ops = &cfe_ioctl_ops; ++ vdev->entity.ops = &cfe_media_entity_ops; ++ vdev->v4l2_dev = &cfe->v4l2_dev; ++ vdev->vfl_dir = (is_image_output_node(node) || is_meta_output_node(node)) ++ ? VFL_DIR_RX : VFL_DIR_TX; ++ vdev->queue = q; ++ vdev->lock = &node->lock; ++ vdev->device_caps = node_desc[id].cap; ++ vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_IO_MC; ++ ++ /* Define the device names */ ++ snprintf(vdev->name, sizeof(vdev->name), "%s-%s", CFE_MODULE_NAME, ++ node_desc[id].name); ++ ++ video_set_drvdata(vdev, node); ++ if (node->id == FE_OUT0) ++ vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT; ++ node->pad.flags = node_desc[id].pad_flags; ++ media_entity_pads_init(&vdev->entity, 1, &node->pad); ++ ++ if (is_meta_node(node)) { ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_ENUM_FRAMEINTERVALS); ++ v4l2_disable_ioctl(&node->video_dev, ++ VIDIOC_ENUM_FRAMESIZES); ++ } ++ ++ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); ++ if (ret) { ++ cfe_err("Unable to register video device %s\n", vdev->name); ++ return ret; ++ } ++ ++ cfe_info("Registered [%s] node id %d successfully as /dev/video%u\n", ++ vdev->name, id, vdev->num); ++ ++ /* ++ * Acquire a reference to cfe, which will be released when the video ++ * device will be unregistered and userspace will have closed all open ++ * file handles. ++ */ ++ cfe_get(cfe); ++ set_state(cfe, NODE_REGISTERED, id); ++ ++ return 0; ++} ++ ++static void cfe_unregister_nodes(struct cfe_device *cfe) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ if (check_state(cfe, NODE_REGISTERED, i)) { ++ clear_state(cfe, NODE_REGISTERED, i); ++ video_unregister_device(&node->video_dev); ++ } ++ } ++} ++ ++static int cfe_link_node_pads(struct cfe_device *cfe) ++{ ++ unsigned int i; ++ int ret; ++ ++ for (i = 0; i < CSI2_NUM_CHANNELS; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ ++ if (!check_state(cfe, NODE_REGISTERED, i)) ++ continue; ++ ++ if (i < cfe->sensor->entity.num_pads) { ++ /* Sensor -> CSI2 */ ++ ret = media_create_pad_link(&cfe->sensor->entity, i, ++ &cfe->csi2.sd.entity, i, ++ MEDIA_LNK_FL_IMMUTABLE | ++ MEDIA_LNK_FL_ENABLED); ++ if (ret) ++ return ret; ++ } ++ ++ /* CSI2 channel # -> /dev/video# */ ++ ret = media_create_pad_link(&cfe->csi2.sd.entity, ++ node_desc[i].link_pad, ++ &node->video_dev.entity, 0, 0); ++ if (ret) ++ return ret; ++ ++ if (node->id != CSI2_CH1_EMBEDDED) { ++ /* CSI2 channel # -> FE Input */ ++ ret = media_create_pad_link(&cfe->csi2.sd.entity, ++ node_desc[i].link_pad, ++ &cfe->fe.sd.entity, ++ FE_STREAM_PAD, 0); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ for (; i < NUM_NODES; i++) { ++ struct cfe_node *node = &cfe->node[i]; ++ struct media_entity *src, *dst; ++ unsigned int src_pad, dst_pad; ++ ++ if (node_desc[i].pad_flags & MEDIA_PAD_FL_SINK) { ++ /* FE -> /dev/video# */ ++ src = &cfe->fe.sd.entity; ++ src_pad = node_desc[i].link_pad; ++ dst = &node->video_dev.entity; ++ dst_pad = 0; ++ } else { ++ /* /dev/video# -> FE */ ++ dst = &cfe->fe.sd.entity; ++ dst_pad = node_desc[i].link_pad; ++ src = &node->video_dev.entity; ++ src_pad = 0; ++ } ++ ++ ret = media_create_pad_link(src, src_pad, dst, dst_pad, 0); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int cfe_probe_complete(struct cfe_device *cfe) ++{ ++ unsigned int i; ++ int ret; ++ ++ cfe->v4l2_dev.notify = cfe_notify; ++ ++ cfe->sensor_embedded_data = (cfe->sensor->entity.num_pads >= 2); ++ ++ for (i = 0; i < NUM_NODES; i++) { ++ ret = cfe_register_node(cfe, i); ++ if (ret) { ++ cfe_err("Unable to register video node %u.\n", i); ++ goto unregister; ++ } ++ } ++ ++ ret = cfe_link_node_pads(cfe); ++ if (ret) { ++ cfe_err("Unable to link node pads.\n"); ++ goto unregister; ++ } ++ ++ ret = v4l2_device_register_subdev_nodes(&cfe->v4l2_dev); ++ if (ret) { ++ cfe_err("Unable to register subdev nodes.\n"); ++ goto unregister; ++ } ++ ++ /* ++ * Release the initial reference, all references are now owned by the ++ * video devices. ++ */ ++ cfe_put(cfe); ++ return 0; ++ ++unregister: ++ cfe_unregister_nodes(cfe); ++ cfe_put(cfe); ++ ++ return ret; ++} ++ ++static int cfe_async_bound(struct v4l2_async_notifier *notifier, ++ struct v4l2_subdev *subdev, ++ struct v4l2_async_subdev *asd) ++{ ++ struct cfe_device *cfe = to_cfe_device(notifier->v4l2_dev); ++ ++ if (cfe->sensor) { ++ cfe_info("Rejecting subdev %s (Already set!!)", subdev->name); ++ return 0; ++ } ++ ++ cfe->sensor = subdev; ++ cfe_info("Using sensor %s for capture\n", subdev->name); ++ ++ return 0; ++} ++ ++static int cfe_async_complete(struct v4l2_async_notifier *notifier) ++{ ++ struct cfe_device *cfe = to_cfe_device(notifier->v4l2_dev); ++ ++ return cfe_probe_complete(cfe); ++} ++ ++static const struct v4l2_async_notifier_operations cfe_async_ops = { ++ .bound = cfe_async_bound, ++ .complete = cfe_async_complete, ++}; ++ ++static int of_cfe_connect_subdevs(struct cfe_device *cfe) ++{ ++ struct platform_device *pdev = cfe->pdev; ++ struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY }; ++ struct device_node *node = pdev->dev.of_node; ++ struct device_node *ep_node; ++ struct device_node *sensor_node; ++ unsigned int lane; ++ int ret = -EINVAL; ++ ++ /* Get the local endpoint and remote device. */ ++ ep_node = of_graph_get_next_endpoint(node, NULL); ++ if (!ep_node) { ++ cfe_err("can't get next endpoint\n"); ++ return -EINVAL; ++ } ++ ++ cfe_dbg("ep_node is %pOF\n", ep_node); ++ ++ sensor_node = of_graph_get_remote_port_parent(ep_node); ++ if (!sensor_node) { ++ cfe_err("can't get remote parent\n"); ++ goto cleanup_exit; ++ } ++ ++ cfe_info("found subdevice %pOF\n", sensor_node); ++ ++ /* Parse the local endpoint and validate its configuration. */ ++ v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), &ep); ++ ++ cfe->csi2.multipacket_line = ++ fwnode_property_present(of_fwnode_handle(ep_node), ++ "multipacket-line"); ++ ++ if (ep.bus_type != V4L2_MBUS_CSI2_DPHY) { ++ cfe_err("endpoint node type != CSI2\n"); ++ return -EINVAL; ++ } ++ ++ for (lane = 0; lane < ep.bus.mipi_csi2.num_data_lanes; lane++) { ++ if (ep.bus.mipi_csi2.data_lanes[lane] != lane + 1) { ++ cfe_err("subdevice %pOF: data lanes reordering not supported\n", ++ sensor_node); ++ goto cleanup_exit; ++ } ++ } ++ ++ /* TODO: Get the frequency from devicetree */ ++ cfe->csi2.dphy.dphy_freq = 999; ++ cfe->csi2.dphy.num_lanes = ep.bus.mipi_csi2.num_data_lanes; ++ cfe->csi2.bus_flags = ep.bus.mipi_csi2.flags; ++ ++ cfe_dbg("subdevice %pOF: %u data lanes, flags=0x%08x, multipacket_line=%u\n", ++ sensor_node, cfe->csi2.dphy.num_lanes, cfe->csi2.bus_flags, ++ cfe->csi2.multipacket_line); ++ ++ /* Initialize and register the async notifier. */ ++ v4l2_async_nf_init(&cfe->notifier); ++ cfe->notifier.ops = &cfe_async_ops; ++ ++ cfe->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; ++ cfe->asd.match.fwnode = of_fwnode_handle(sensor_node); ++ ret = __v4l2_async_nf_add_subdev(&cfe->notifier, &cfe->asd); ++ if (ret) { ++ cfe_err("Error adding subdevice: %d\n", ret); ++ goto cleanup_exit; ++ } ++ ++ ret = v4l2_async_nf_register(&cfe->v4l2_dev, &cfe->notifier); ++ if (ret) { ++ cfe_err("Error registering async notifier: %d\n", ret); ++ ret = -EINVAL; ++ } ++ ++cleanup_exit: ++ of_node_put(sensor_node); ++ of_node_put(ep_node); ++ ++ return ret; ++} ++ ++static int cfe_probe(struct platform_device *pdev) ++{ ++ struct cfe_device *cfe; ++ char debugfs_name[32]; ++ int ret; ++ ++ cfe = kzalloc(sizeof(*cfe), GFP_KERNEL); ++ if (!cfe) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, cfe); ++ ++ kref_init(&cfe->kref); ++ cfe->pdev = pdev; ++ cfe->fe_csi2_channel = -1; ++ spin_lock_init(&cfe->state_lock); ++ ++ cfe->csi2.base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(cfe->csi2.base)) { ++ dev_err(&pdev->dev, "Failed to get dma io block\n"); ++ ret = PTR_ERR(cfe->csi2.base); ++ goto err_cfe_put; ++ } ++ ++ cfe->csi2.dphy.base = devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(cfe->csi2.dphy.base)) { ++ dev_err(&pdev->dev, "Failed to get host io block\n"); ++ ret = PTR_ERR(cfe->csi2.dphy.base); ++ goto err_cfe_put; ++ } ++ ++ cfe->mipi_cfg_base = devm_platform_ioremap_resource(pdev, 2); ++ if (IS_ERR(cfe->mipi_cfg_base)) { ++ dev_err(&pdev->dev, "Failed to get mipi cfg io block\n"); ++ ret = PTR_ERR(cfe->mipi_cfg_base); ++ goto err_cfe_put; ++ } ++ ++ cfe->fe.base = devm_platform_ioremap_resource(pdev, 3); ++ if (IS_ERR(cfe->fe.base)) { ++ dev_err(&pdev->dev, "Failed to get pisp fe io block\n"); ++ ret = PTR_ERR(cfe->fe.base); ++ goto err_cfe_put; ++ } ++ ++ ret = platform_get_irq(pdev, 0); ++ if (ret <= 0) { ++ dev_err(&pdev->dev, "No IRQ resource\n"); ++ ret = -EINVAL; ++ goto err_cfe_put; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, ret, cfe_isr, 0, "rp1-cfe", cfe); ++ if (ret) { ++ dev_err(&pdev->dev, "Unable to request interrupt\n"); ++ ret = -EINVAL; ++ goto err_cfe_put; ++ } ++ ++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); ++ if (ret) { ++ dev_err(&pdev->dev, "DMA enable failed\n"); ++ goto err_cfe_put; ++ } ++ ++ /* TODO: Enable clock only when running. */ ++ cfe->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(cfe->clk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(cfe->clk), ++ "clock not found\n"); ++ ++ cfe->mdev.dev = &pdev->dev; ++ cfe->mdev.ops = &cfe_media_device_ops; ++ strscpy(cfe->mdev.model, CFE_MODULE_NAME, sizeof(cfe->mdev.model)); ++ strscpy(cfe->mdev.serial, "", sizeof(cfe->mdev.serial)); ++ snprintf(cfe->mdev.bus_info, sizeof(cfe->mdev.bus_info), "platform:%s", ++ dev_name(&pdev->dev)); ++ ++ media_device_init(&cfe->mdev); ++ ++ cfe->v4l2_dev.mdev = &cfe->mdev; ++ ++ ret = v4l2_device_register(&pdev->dev, &cfe->v4l2_dev); ++ if (ret) { ++ cfe_err("Unable to register v4l2 device.\n"); ++ goto err_cfe_put; ++ } ++ ++ snprintf(debugfs_name, sizeof(debugfs_name), "rp1-cfe:%s", ++ dev_name(&pdev->dev)); ++ cfe->debugfs = debugfs_create_dir(debugfs_name, NULL); ++ debugfs_create_file("format", 0444, cfe->debugfs, cfe, &format_fops); ++ debugfs_create_file("regs", 0444, cfe->debugfs, cfe, ++ &mipi_cfg_regs_fops); ++ ++ /* Enable the block power domain */ ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = pm_runtime_resume_and_get(&cfe->pdev->dev); ++ if (ret) ++ goto err_runtime_disable; ++ ++ cfe->csi2.v4l2_dev = &cfe->v4l2_dev; ++ ret = csi2_init(&cfe->csi2, cfe->debugfs); ++ if (ret) { ++ cfe_err("Failed to init csi2 (%d)\n", ret); ++ goto err_runtime_put; ++ } ++ ++ cfe->fe.v4l2_dev = &cfe->v4l2_dev; ++ ret = pisp_fe_init(&cfe->fe, cfe->debugfs); ++ if (ret) { ++ cfe_err("Failed to init pisp fe (%d)\n", ret); ++ goto err_csi2_uninit; ++ } ++ ++ cfe->mdev.hw_revision = cfe->fe.hw_revision; ++ ret = media_device_register(&cfe->mdev); ++ if (ret < 0) { ++ cfe_err("Unable to register media-controller device.\n"); ++ goto err_pisp_fe_uninit; ++ } ++ ++ ret = of_cfe_connect_subdevs(cfe); ++ if (ret) { ++ cfe_err("Failed to connect subdevs\n"); ++ goto err_media_unregister; ++ } ++ ++ pm_runtime_put(&cfe->pdev->dev); ++ ++ return 0; ++ ++err_media_unregister: ++ media_device_unregister(&cfe->mdev); ++err_pisp_fe_uninit: ++ pisp_fe_uninit(&cfe->fe); ++err_csi2_uninit: ++ csi2_uninit(&cfe->csi2); ++err_runtime_put: ++ pm_runtime_put(&cfe->pdev->dev); ++err_runtime_disable: ++ pm_runtime_disable(&pdev->dev); ++ debugfs_remove(cfe->debugfs); ++ v4l2_device_unregister(&cfe->v4l2_dev); ++err_cfe_put: ++ cfe_put(cfe); ++ ++ return ret; ++} ++ ++static int cfe_remove(struct platform_device *pdev) ++{ ++ struct cfe_device *cfe = platform_get_drvdata(pdev); ++ ++ debugfs_remove(cfe->debugfs); ++ ++ v4l2_async_nf_unregister(&cfe->notifier); ++ media_device_unregister(&cfe->mdev); ++ cfe_unregister_nodes(cfe); ++ ++ pisp_fe_uninit(&cfe->fe); ++ csi2_uninit(&cfe->csi2); ++ ++ pm_runtime_disable(&pdev->dev); ++ ++ v4l2_device_unregister(&cfe->v4l2_dev); ++ ++ return 0; ++} ++ ++static int cfe_runtime_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct cfe_device *cfe = platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(cfe->clk); ++ ++ return 0; ++} ++ ++static int cfe_runtime_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct cfe_device *cfe = platform_get_drvdata(pdev); ++ int ret; ++ ++ ret = clk_prepare_enable(cfe->clk); ++ if (ret) { ++ dev_err(dev, "Unable to enable clock\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops cfe_pm_ops = { ++ SET_RUNTIME_PM_OPS(cfe_runtime_suspend, cfe_runtime_resume, NULL) ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) ++}; ++ ++static const struct of_device_id cfe_of_match[] = { ++ { .compatible = "raspberrypi,rp1-cfe" }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, cfe_of_match); ++ ++static struct platform_driver cfe_driver = { ++ .probe = cfe_probe, ++ .remove = cfe_remove, ++ .driver = { ++ .name = CFE_MODULE_NAME, ++ .of_match_table = cfe_of_match, ++ .pm = &cfe_pm_ops, ++ }, ++}; ++ ++module_platform_driver(cfe_driver); ++ ++MODULE_AUTHOR("Naushir Patuck "); ++MODULE_DESCRIPTION("RP1 Camera Front End driver"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(CFE_VERSION); +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h +@@ -0,0 +1,40 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 CFE driver. ++ * Copyright (c) 2021 Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _RP1_CFE_ ++#define _RP1_CFE_ ++ ++#include ++#include ++#include ++ ++extern bool cfe_debug_irq; ++ ++enum cfe_remap_types { ++ CFE_REMAP_16BIT, ++ CFE_REMAP_COMPRESSED, ++ CFE_NUM_REMAP, ++}; ++ ++#define CFE_FORMAT_FLAG_META_OUT BIT(0) ++#define CFE_FORMAT_FLAG_META_CAP BIT(1) ++#define CFE_FORMAT_FLAG_FE_OUT BIT(2) ++ ++struct cfe_fmt { ++ u32 fourcc; ++ u32 code; ++ u8 depth; ++ u8 csi_dt; ++ u32 remap[CFE_NUM_REMAP]; ++ u32 flags; ++}; ++ ++extern const struct v4l2_mbus_framefmt cfe_default_format; ++extern const struct v4l2_mbus_framefmt cfe_default_meta_format; ++ ++const struct cfe_fmt *find_format_by_code(u32 code); ++ ++#endif +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h +@@ -0,0 +1,294 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 Camera Front End formats definition ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _CFE_FMTS_H_ ++#define _CFE_FMTS_H_ ++ ++#include "cfe.h" ++ ++static const struct cfe_fmt formats[] = { ++ /* YUV Formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .code = MEDIA_BUS_FMT_YUYV8_1X16, ++ .depth = 16, ++ .csi_dt = 0x1e, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_UYVY, ++ .code = MEDIA_BUS_FMT_UYVY8_1X16, ++ .depth = 16, ++ .csi_dt = 0x1e, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YVYU, ++ .code = MEDIA_BUS_FMT_YVYU8_1X16, ++ .depth = 16, ++ .csi_dt = 0x1e, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_VYUY, ++ .code = MEDIA_BUS_FMT_VYUY8_1X16, ++ .depth = 16, ++ .csi_dt = 0x1e, ++ }, ++ { ++ /* RGB Formats */ ++ .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */ ++ .code = MEDIA_BUS_FMT_RGB565_2X8_LE, ++ .depth = 16, ++ .csi_dt = 0x22, ++ }, ++ { .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ ++ .code = MEDIA_BUS_FMT_RGB565_2X8_BE, ++ .depth = 16, ++ .csi_dt = 0x22 ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */ ++ .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, ++ .depth = 16, ++ .csi_dt = 0x21, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */ ++ .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, ++ .depth = 16, ++ .csi_dt = 0x21, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ ++ .code = MEDIA_BUS_FMT_RGB888_1X24, ++ .depth = 24, ++ .csi_dt = 0x24, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ ++ .code = MEDIA_BUS_FMT_BGR888_1X24, ++ .depth = 24, ++ .csi_dt = 0x24, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB32, /* argb */ ++ .code = MEDIA_BUS_FMT_ARGB8888_1X32, ++ .depth = 32, ++ .csi_dt = 0x0, ++ }, ++ ++ /* Bayer Formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR8, ++ .code = MEDIA_BUS_FMT_SBGGR8_1X8, ++ .depth = 8, ++ .csi_dt = 0x2a, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG8, ++ .code = MEDIA_BUS_FMT_SGBRG8_1X8, ++ .depth = 8, ++ .csi_dt = 0x2a, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG8, ++ .code = MEDIA_BUS_FMT_SGRBG8_1X8, ++ .depth = 8, ++ .csi_dt = 0x2a, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB8, ++ .code = MEDIA_BUS_FMT_SRGGB8_1X8, ++ .depth = 8, ++ .csi_dt = 0x2a, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR10P, ++ .code = MEDIA_BUS_FMT_SBGGR10_1X10, ++ .depth = 10, ++ .csi_dt = 0x2b, ++ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG10P, ++ .code = MEDIA_BUS_FMT_SGBRG10_1X10, ++ .depth = 10, ++ .csi_dt = 0x2b, ++ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG10P, ++ .code = MEDIA_BUS_FMT_SGRBG10_1X10, ++ .depth = 10, ++ .csi_dt = 0x2b, ++ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB10P, ++ .code = MEDIA_BUS_FMT_SRGGB10_1X10, ++ .depth = 10, ++ .csi_dt = 0x2b, ++ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR12P, ++ .code = MEDIA_BUS_FMT_SBGGR12_1X12, ++ .depth = 12, ++ .csi_dt = 0x2c, ++ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG12P, ++ .code = MEDIA_BUS_FMT_SGBRG12_1X12, ++ .depth = 12, ++ .csi_dt = 0x2c, ++ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG12P, ++ .code = MEDIA_BUS_FMT_SGRBG12_1X12, ++ .depth = 12, ++ .csi_dt = 0x2c, ++ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB12P, ++ .code = MEDIA_BUS_FMT_SRGGB12_1X12, ++ .depth = 12, ++ .csi_dt = 0x2c, ++ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR14P, ++ .code = MEDIA_BUS_FMT_SBGGR14_1X14, ++ .depth = 14, ++ .csi_dt = 0x2d, ++ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG14P, ++ .code = MEDIA_BUS_FMT_SGBRG14_1X14, ++ .depth = 14, ++ .csi_dt = 0x2d, ++ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG14P, ++ .code = MEDIA_BUS_FMT_SGRBG14_1X14, ++ .depth = 14, ++ .csi_dt = 0x2d, ++ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB14P, ++ .code = MEDIA_BUS_FMT_SRGGB14_1X14, ++ .depth = 14, ++ .csi_dt = 0x2d, ++ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR16, ++ .code = MEDIA_BUS_FMT_SBGGR16_1X16, ++ .depth = 16, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGBRG16, ++ .code = MEDIA_BUS_FMT_SGBRG16_1X16, ++ .depth = 16, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SGRBG16, ++ .code = MEDIA_BUS_FMT_SGRBG16_1X16, ++ .depth = 16, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SRGGB16, ++ .code = MEDIA_BUS_FMT_SRGGB16_1X16, ++ .depth = 16, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ /* PiSP Compressed Mode 1 */ ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_RGGB, ++ .code = MEDIA_BUS_FMT_PISP_COMP1_RGGB, ++ .depth = 8, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_BGGR, ++ .code = MEDIA_BUS_FMT_PISP_COMP1_BGGR, ++ .depth = 8, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_GBRG, ++ .code = MEDIA_BUS_FMT_PISP_COMP1_GBRG, ++ .depth = 8, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_GRBG, ++ .code = MEDIA_BUS_FMT_PISP_COMP1_GRBG, ++ .depth = 8, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ /* Greyscale format */ ++ { ++ .fourcc = V4L2_PIX_FMT_GREY, ++ .code = MEDIA_BUS_FMT_Y8_1X8, ++ .depth = 8, ++ .csi_dt = 0x2a, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_Y10P, ++ .code = MEDIA_BUS_FMT_Y10_1X10, ++ .depth = 10, ++ .csi_dt = 0x2b, ++ .remap = { V4L2_PIX_FMT_Y16 }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_Y12P, ++ .code = MEDIA_BUS_FMT_Y12_1X12, ++ .depth = 12, ++ .csi_dt = 0x2c, ++ .remap = { V4L2_PIX_FMT_Y16 }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_Y14P, ++ .code = MEDIA_BUS_FMT_Y14_1X14, ++ .depth = 14, ++ .csi_dt = 0x2d, ++ .remap = { V4L2_PIX_FMT_Y16 }, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_Y16, ++ .depth = 16, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, ++ ++ /* Embedded data format */ ++ { ++ .fourcc = V4L2_META_FMT_SENSOR_DATA, ++ .code = MEDIA_BUS_FMT_SENSOR_DATA, ++ .depth = 8, ++ .csi_dt = 0x12, ++ .flags = CFE_FORMAT_FLAG_META_CAP, ++ }, ++ ++ /* Frontend formats */ ++ { ++ .fourcc = V4L2_META_FMT_RPI_FE_CFG, ++ .flags = CFE_FORMAT_FLAG_META_OUT, ++ }, ++ { ++ .fourcc = V4L2_META_FMT_RPI_FE_STATS, ++ .flags = CFE_FORMAT_FLAG_META_CAP, ++ }, ++}; ++ ++#endif /* _CFE_FMTS_H_ */ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -0,0 +1,446 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * RP1 CSI-2 Driver ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "csi2.h" ++#include "cfe.h" ++ ++#define csi2_dbg_irq(fmt, arg...) \ ++ do { \ ++ if (cfe_debug_irq) \ ++ dev_dbg(csi2->v4l2_dev->dev, fmt, ##arg); \ ++ } while (0) ++#define csi2_dbg(fmt, arg...) dev_dbg(csi2->v4l2_dev->dev, fmt, ##arg) ++#define csi2_info(fmt, arg...) dev_info(csi2->v4l2_dev->dev, fmt, ##arg) ++#define csi2_err(fmt, arg...) dev_err(csi2->v4l2_dev->dev, fmt, ##arg) ++ ++/* CSI2-DMA registers */ ++#define CSI2_STATUS 0x000 ++#define CSI2_QOS 0x004 ++#define CSI2_DISCARDS_OVERFLOW 0x008 ++#define CSI2_DISCARDS_INACTIVE 0x00c ++#define CSI2_DISCARDS_UNMATCHED 0x010 ++#define CSI2_DISCARDS_LEN_LIMIT 0x014 ++#define CSI2_LLEV_PANICS 0x018 ++#define CSI2_ULEV_PANICS 0x01c ++#define CSI2_IRQ_MASK 0x020 ++#define CSI2_CTRL 0x024 ++#define CSI2_CH_CTRL(x) ((x) * 0x40 + 0x28) ++#define CSI2_CH_ADDR0(x) ((x) * 0x40 + 0x2c) ++#define CSI2_CH_ADDR1(x) ((x) * 0x40 + 0x3c) ++#define CSI2_CH_STRIDE(x) ((x) * 0x40 + 0x30) ++#define CSI2_CH_LENGTH(x) ((x) * 0x40 + 0x34) ++#define CSI2_CH_DEBUG(x) ((x) * 0x40 + 0x38) ++#define CSI2_CH_FRAME_SIZE(x) ((x) * 0x40 + 0x40) ++#define CSI2_CH_COMP_CTRL(x) ((x) * 0x40 + 0x44) ++#define CSI2_CH_FE_FRAME_ID(x) ((x) * 0x40 + 0x48) ++ ++/* CSI2_STATUS */ ++#define IRQ_FS(x) (BIT(0) << (x)) ++#define IRQ_FE(x) (BIT(4) << (x)) ++#define IRQ_FE_ACK(x) (BIT(8) << (x)) ++#define IRQ_LE(x) (BIT(12) << (x)) ++#define IRQ_LE_ACK(x) (BIT(16) << (x)) ++#define IRQ_CH_MASK(x) (IRQ_FS(x) | IRQ_FE(x) | IRQ_FE_ACK(x) | IRQ_LE(x) | IRQ_LE_ACK(x)) ++#define IRQ_OVERFLOW BIT(20) ++#define IRQ_DISCARD_OVERFLOW BIT(21) ++#define IRQ_DISCARD_LEN_LIMIT BIT(22) ++#define IRQ_DISCARD_UNMATCHED BIT(23) ++#define IRQ_DISCARD_INACTIVE BIT(24) ++ ++/* CSI2_CTRL */ ++#define EOP_IS_EOL BIT(0) ++ ++/* CSI2_CH_CTRL */ ++#define DMA_EN BIT(0) ++#define FORCE BIT(3) ++#define AUTO_ARM BIT(4) ++#define IRQ_EN_FS BIT(13) ++#define IRQ_EN_FE BIT(14) ++#define IRQ_EN_FE_ACK BIT(15) ++#define IRQ_EN_LE BIT(16) ++#define IRQ_EN_LE_ACK BIT(17) ++#define FLUSH_FE BIT(28) ++#define PACK_LINE BIT(29) ++#define PACK_BYTES BIT(30) ++#define CH_MODE_MASK GENMASK(2, 1) ++#define VC_MASK GENMASK(6, 5) ++#define DT_MASK GENMASK(12, 7) ++#define LC_MASK GENMASK(27, 18) ++ ++/* CHx_COMPRESSION_CONTROL */ ++#define COMP_OFFSET_MASK GENMASK(15, 0) ++#define COMP_SHIFT_MASK GENMASK(19, 16) ++#define COMP_MODE_MASK GENMASK(25, 24) ++ ++static inline u32 csi2_reg_read(struct csi2_device *csi2, u32 offset) ++{ ++ return readl(csi2->base + offset); ++} ++ ++static inline void csi2_reg_write(struct csi2_device *csi2, u32 offset, u32 val) ++{ ++ writel(val, csi2->base + offset); ++} ++ ++static inline void set_field(u32 *valp, u32 field, u32 mask) ++{ ++ u32 val = *valp; ++ ++ val &= ~mask; ++ val |= (field << __ffs(mask)) & mask; ++ *valp = val; ++} ++ ++static int csi2_regs_show(struct seq_file *s, void *data) ++{ ++ struct csi2_device *csi2 = s->private; ++ unsigned int i; ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(csi2->v4l2_dev->dev); ++ if (ret) ++ return ret; ++ ++#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", csi2_reg_read(csi2, reg)) ++#define DUMP_CH(idx, reg) seq_printf(s, #reg "(%u) \t0x%08x\n", idx, csi2_reg_read(csi2, reg(idx))) ++ ++ DUMP(CSI2_STATUS); ++ DUMP(CSI2_DISCARDS_OVERFLOW); ++ DUMP(CSI2_DISCARDS_INACTIVE); ++ DUMP(CSI2_DISCARDS_UNMATCHED); ++ DUMP(CSI2_DISCARDS_LEN_LIMIT); ++ DUMP(CSI2_LLEV_PANICS); ++ DUMP(CSI2_ULEV_PANICS); ++ DUMP(CSI2_IRQ_MASK); ++ DUMP(CSI2_CTRL); ++ ++ for (i = 0; i < CSI2_NUM_CHANNELS; ++i) { ++ DUMP_CH(i, CSI2_CH_CTRL); ++ DUMP_CH(i, CSI2_CH_ADDR0); ++ DUMP_CH(i, CSI2_CH_ADDR1); ++ DUMP_CH(i, CSI2_CH_STRIDE); ++ DUMP_CH(i, CSI2_CH_LENGTH); ++ DUMP_CH(i, CSI2_CH_DEBUG); ++ DUMP_CH(i, CSI2_CH_FRAME_SIZE); ++ DUMP_CH(i, CSI2_CH_COMP_CTRL); ++ DUMP_CH(i, CSI2_CH_FE_FRAME_ID); ++ } ++ ++#undef DUMP ++#undef DUMP_CH ++ ++ pm_runtime_put(csi2->v4l2_dev->dev); ++ ++ return 0; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(csi2_regs); ++ ++void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci) ++{ ++ unsigned int i; ++ u32 status; ++ ++ status = csi2_reg_read(csi2, CSI2_STATUS); ++ csi2_dbg_irq("ISR: STA: 0x%x\n", status); ++ ++ /* Write value back to clear the interrupts */ ++ csi2_reg_write(csi2, CSI2_STATUS, status); ++ ++ for (i = 0; i < CSI2_NUM_CHANNELS; i++) { ++ u32 dbg; ++ ++ if ((status & IRQ_CH_MASK(i)) == 0) ++ continue; ++ ++ dbg = csi2_reg_read(csi2, CSI2_CH_DEBUG(i)); ++ ++ csi2_dbg_irq("ISR: [%u], %s%s%s%s%s frame: %u line: %u\n", i, ++ (status & IRQ_FS(i)) ? "FS " : "", ++ (status & IRQ_FE(i)) ? "FE " : "", ++ (status & IRQ_FE_ACK(i)) ? "FE_ACK " : "", ++ (status & IRQ_LE(i)) ? "LE " : "", ++ (status & IRQ_LE_ACK(i)) ? "LE_ACK " : "", ++ dbg >> 16, ++ csi2->num_lines[i] ? ++ ((dbg & 0xffff) % csi2->num_lines[i]) : ++ 0); ++ ++ sof[i] = !!(status & IRQ_FS(i)); ++ eof[i] = !!(status & IRQ_FE_ACK(i)); ++ lci[i] = !!(status & IRQ_LE_ACK(i)); ++ } ++} ++ ++void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel, ++ dma_addr_t dmaaddr, unsigned int stride, unsigned int size) ++{ ++ u64 addr = dmaaddr; ++ /* ++ * ADDRESS0 must be written last as it triggers the double buffering ++ * mechanism for all buffer registers within the hardware. ++ */ ++ addr >>= 4; ++ csi2_reg_write(csi2, CSI2_CH_LENGTH(channel), size >> 4); ++ csi2_reg_write(csi2, CSI2_CH_STRIDE(channel), stride >> 4); ++ csi2_reg_write(csi2, CSI2_CH_ADDR1(channel), addr >> 32); ++ csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), addr & 0xffffffff); ++} ++ ++void csi2_set_compression(struct csi2_device *csi2, unsigned int channel, ++ enum csi2_compression_mode mode, unsigned int shift, ++ unsigned int offset) ++{ ++ u32 compression = 0; ++ ++ set_field(&compression, COMP_OFFSET_MASK, offset); ++ set_field(&compression, COMP_SHIFT_MASK, shift); ++ set_field(&compression, COMP_MODE_MASK, mode); ++ csi2_reg_write(csi2, CSI2_CH_COMP_CTRL(channel), compression); ++} ++ ++void csi2_start_channel(struct csi2_device *csi2, unsigned int channel, ++ u16 dt, enum csi2_mode mode, bool auto_arm, ++ bool pack_bytes, unsigned int width, ++ unsigned int height) ++{ ++ u32 ctrl; ++ ++ csi2_dbg("%s [%u]\n", __func__, channel); ++ ++ /* ++ * Disable the channel, but ensure N != 0! Otherwise we end up with a ++ * spurious LE + LE_ACK interrupt when re-enabling the channel. ++ */ ++ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), 0x100 << __ffs(LC_MASK)); ++ csi2_reg_write(csi2, CSI2_CH_DEBUG(channel), 0); ++ csi2_reg_write(csi2, CSI2_STATUS, IRQ_CH_MASK(channel)); ++ ++ /* Enable channel and FS/FE/LE interrupts. */ ++ ctrl = DMA_EN | IRQ_EN_FS | IRQ_EN_FE_ACK | IRQ_EN_LE_ACK | PACK_LINE; ++ /* PACK_BYTES ensures no striding for embedded data. */ ++ if (pack_bytes) ++ ctrl |= PACK_BYTES; ++ ++ if (auto_arm) ++ ctrl |= AUTO_ARM; ++ ++ if (width && height) { ++ int line_int_freq = height >> 2; ++ ++ line_int_freq = min(max(0x80, line_int_freq), 0x3ff); ++ set_field(&ctrl, line_int_freq, LC_MASK); ++ set_field(&ctrl, mode, CH_MODE_MASK); ++ csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), ++ (height << 16) | width); ++ } else { ++ /* ++ * Do not disable line interrupts for the embedded data channel, ++ * set it to the maximum value. This avoids spamming the ISR ++ * with spurious line interrupts. ++ */ ++ set_field(&ctrl, 0x3ff, LC_MASK); ++ set_field(&ctrl, 0x00, CH_MODE_MASK); ++ } ++ ++ set_field(&ctrl, dt, DT_MASK); ++ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), ctrl); ++ csi2->num_lines[channel] = height; ++} ++ ++void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel) ++{ ++ csi2_dbg("%s [%u]\n", __func__, channel); ++ ++ /* Channel disable. Use FORCE to allow stopping mid-frame. */ ++ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), ++ (0x100 << __ffs(LC_MASK)) | FORCE); ++ /* Latch the above change by writing to the ADDR0 register. */ ++ csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), 0); ++ /* Write this again, the HW needs it! */ ++ csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), 0); ++} ++ ++void csi2_open_rx(struct csi2_device *csi2) ++{ ++ dphy_start(&csi2->dphy); ++ ++ if (!csi2->multipacket_line) ++ csi2_reg_write(csi2, CSI2_CTRL, EOP_IS_EOL); ++} ++ ++void csi2_close_rx(struct csi2_device *csi2) ++{ ++ dphy_stop(&csi2->dphy); ++} ++ ++static struct csi2_device *to_csi2_device(struct v4l2_subdev *subdev) ++{ ++ return container_of(subdev, struct csi2_device, sd); ++} ++ ++static int csi2_init_cfg(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state) ++{ ++ struct v4l2_mbus_framefmt *fmt; ++ ++ for (unsigned int i = 0; i < CSI2_NUM_CHANNELS; ++i) { ++ const struct v4l2_mbus_framefmt *def_fmt; ++ ++ /* CSI2_CH1_EMBEDDED */ ++ if (i == 1) ++ def_fmt = &cfe_default_meta_format; ++ else ++ def_fmt = &cfe_default_format; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, i); ++ *fmt = *def_fmt; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, i + CSI2_NUM_CHANNELS); ++ *fmt = *def_fmt; ++ } ++ ++ return 0; ++} ++ ++static int csi2_pad_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *fmt; ++ const struct cfe_fmt *cfe_fmt; ++ ++ /* TODO: format validation */ ++ ++ cfe_fmt = find_format_by_code(format->format.code); ++ if (!cfe_fmt) ++ cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10); ++ ++ format->format.code = cfe_fmt->code; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); ++ *fmt = format->format; ++ ++ if (format->pad < CSI2_NUM_CHANNELS) { ++ /* Propagate to the source pad */ ++ fmt = v4l2_subdev_get_pad_format(sd, state, ++ format->pad + CSI2_NUM_CHANNELS); ++ *fmt = format->format; ++ } ++ ++ return 0; ++} ++ ++static int csi2_link_validate(struct v4l2_subdev *sd, struct media_link *link, ++ struct v4l2_subdev_format *source_fmt, ++ struct v4l2_subdev_format *sink_fmt) ++{ ++ struct csi2_device *csi2 = to_csi2_device(sd); ++ ++ csi2_dbg("%s: link \"%s\":%u -> \"%s\":%u\n", __func__, ++ link->source->entity->name, link->source->index, ++ link->sink->entity->name, link->sink->index); ++ ++ if ((link->source->entity == &csi2->sd.entity && ++ link->source->index == 1) || ++ (link->sink->entity == &csi2->sd.entity && ++ link->sink->index == 1)) { ++ csi2_dbg("Ignore metadata pad for now\n"); ++ return 0; ++ } ++ ++ /* The width, height and code must match. */ ++ if (source_fmt->format.width != sink_fmt->format.width || ++ source_fmt->format.width != sink_fmt->format.width || ++ source_fmt->format.code != sink_fmt->format.code) { ++ csi2_err("%s: format does not match (source %ux%u 0x%x, sink %ux%u 0x%x)\n", ++ __func__, ++ source_fmt->format.width, source_fmt->format.height, ++ source_fmt->format.code, ++ sink_fmt->format.width, sink_fmt->format.height, ++ sink_fmt->format.code); ++ return -EPIPE; ++ } ++ ++ return 0; ++} ++ ++static const struct v4l2_subdev_pad_ops csi2_subdev_pad_ops = { ++ .init_cfg = csi2_init_cfg, ++ .get_fmt = v4l2_subdev_get_fmt, ++ .set_fmt = csi2_pad_set_fmt, ++ .link_validate = csi2_link_validate, ++}; ++ ++static const struct media_entity_operations csi2_entity_ops = { ++ .link_validate = v4l2_subdev_link_validate, ++}; ++ ++static const struct v4l2_subdev_ops csi2_subdev_ops = { ++ .pad = &csi2_subdev_pad_ops, ++}; ++ ++int csi2_init(struct csi2_device *csi2, struct dentry *debugfs) ++{ ++ unsigned int i, ret; ++ ++ csi2->dphy.dev = csi2->v4l2_dev->dev; ++ dphy_probe(&csi2->dphy); ++ ++ debugfs_create_file("csi2_regs", 0444, debugfs, csi2, &csi2_regs_fops); ++ ++ for (i = 0; i < CSI2_NUM_CHANNELS * 2; i++) ++ csi2->pad[i].flags = i < CSI2_NUM_CHANNELS ? ++ MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; ++ ++ ret = media_entity_pads_init(&csi2->sd.entity, ARRAY_SIZE(csi2->pad), ++ csi2->pad); ++ if (ret) ++ return ret; ++ ++ /* Initialize subdev */ ++ v4l2_subdev_init(&csi2->sd, &csi2_subdev_ops); ++ csi2->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; ++ csi2->sd.entity.ops = &csi2_entity_ops; ++ csi2->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ csi2->sd.owner = THIS_MODULE; ++ snprintf(csi2->sd.name, sizeof(csi2->sd.name), "csi2"); ++ ++ ret = v4l2_subdev_init_finalize(&csi2->sd); ++ if (ret) ++ goto err_entity_cleanup; ++ ++ ret = v4l2_device_register_subdev(csi2->v4l2_dev, &csi2->sd); ++ if (ret) { ++ csi2_err("Failed register csi2 subdev (%d)\n", ret); ++ goto err_subdev_cleanup; ++ } ++ ++ return 0; ++ ++err_subdev_cleanup: ++ v4l2_subdev_cleanup(&csi2->sd); ++err_entity_cleanup: ++ media_entity_cleanup(&csi2->sd.entity); ++ ++ return ret; ++} ++ ++void csi2_uninit(struct csi2_device *csi2) ++{ ++ v4l2_device_unregister_subdev(&csi2->sd); ++ v4l2_subdev_cleanup(&csi2->sd); ++ media_entity_cleanup(&csi2->sd.entity); ++} +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h +@@ -0,0 +1,75 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 CSI-2 driver. ++ * Copyright (c) 2021 Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _RP1_CSI2_ ++#define _RP1_CSI2_ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "dphy.h" ++ ++#define CSI2_NUM_CHANNELS 4 ++ ++enum csi2_mode { ++ CSI2_MODE_NORMAL, ++ CSI2_MODE_REMAP, ++ CSI2_MODE_COMPRESSED, ++ CSI2_MODE_FE_STREAMING ++}; ++ ++enum csi2_compression_mode { ++ CSI2_COMPRESSION_DELTA = 1, ++ CSI2_COMPRESSION_SIMPLE = 2, ++ CSI2_COMPRESSION_COMBINED = 3, ++}; ++ ++struct csi2_cfg { ++ u16 width; ++ u16 height; ++ u32 stride; ++ u32 buffer_size; ++}; ++ ++struct csi2_device { ++ /* Parent V4l2 device */ ++ struct v4l2_device *v4l2_dev; ++ ++ void __iomem *base; ++ ++ struct dphy_data dphy; ++ ++ enum v4l2_mbus_type bus_type; ++ unsigned int bus_flags; ++ u32 active_data_lanes; ++ bool multipacket_line; ++ unsigned int num_lines[CSI2_NUM_CHANNELS]; ++ ++ struct media_pad pad[CSI2_NUM_CHANNELS * 2]; ++ struct v4l2_subdev sd; ++}; ++ ++void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci); ++void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel, ++ dma_addr_t dmaaddr, unsigned int stride, ++ unsigned int size); ++void csi2_set_compression(struct csi2_device *csi2, unsigned int channel, ++ enum csi2_compression_mode mode, unsigned int shift, ++ unsigned int offset); ++void csi2_start_channel(struct csi2_device *csi2, unsigned int channel, ++ u16 dt, enum csi2_mode mode, bool auto_arm, ++ bool pack_bytes, unsigned int width, ++ unsigned int height); ++void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel); ++void csi2_open_rx(struct csi2_device *csi2); ++void csi2_close_rx(struct csi2_device *csi2); ++int csi2_init(struct csi2_device *csi2, struct dentry *debugfs); ++void csi2_uninit(struct csi2_device *csi2); ++ ++#endif +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.c +@@ -0,0 +1,177 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * RP1 CSI-2 Driver ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include "dphy.h" ++ ++#define dphy_dbg(fmt, arg...) dev_dbg(dphy->dev, fmt, ##arg) ++#define dphy_info(fmt, arg...) dev_info(dphy->dev, fmt, ##arg) ++#define dphy_err(fmt, arg...) dev_err(dphy->dev, fmt, ##arg) ++ ++/* DW dphy Host registers */ ++#define VERSION 0x000 ++#define N_LANES 0x004 ++#define RESETN 0x008 ++#define PHY_SHUTDOWNZ 0x040 ++#define PHY_RSTZ 0x044 ++#define PHY_RX 0x048 ++#define PHY_STOPSTATE 0x04c ++#define PHY_TST_CTRL0 0x050 ++#define PHY_TST_CTRL1 0x054 ++#define PHY2_TST_CTRL0 0x058 ++#define PHY2_TST_CTRL1 0x05c ++ ++/* DW dphy Host Transactions */ ++#define DPHY_HS_RX_CTRL_LANE0_OFFSET 0x44 ++#define DPHY_PLL_INPUT_DIV_OFFSET 0x17 ++#define DPHY_PLL_LOOP_DIV_OFFSET 0x18 ++#define DPHY_PLL_DIV_CTRL_OFFSET 0x19 ++ ++static u32 dw_csi2_host_read(struct dphy_data *dphy, u32 offset) ++{ ++ return readl(dphy->base + offset); ++} ++ ++static void dw_csi2_host_write(struct dphy_data *dphy, u32 offset, u32 data) ++{ ++ writel(data, dphy->base + offset); ++} ++ ++static void set_tstclr(struct dphy_data *dphy, u32 val) ++{ ++ u32 ctrl0 = dw_csi2_host_read(dphy, PHY_TST_CTRL0); ++ ++ dw_csi2_host_write(dphy, PHY_TST_CTRL0, (ctrl0 & ~1) | val); ++} ++ ++static void set_tstclk(struct dphy_data *dphy, u32 val) ++{ ++ u32 ctrl0 = dw_csi2_host_read(dphy, PHY_TST_CTRL0); ++ ++ dw_csi2_host_write(dphy, PHY_TST_CTRL0, (ctrl0 & ~2) | (val << 1)); ++} ++ ++static uint8_t get_tstdout(struct dphy_data *dphy) ++{ ++ u32 ctrl1 = dw_csi2_host_read(dphy, PHY_TST_CTRL1); ++ ++ return ((ctrl1 >> 8) & 0xff); ++} ++ ++static void set_testen(struct dphy_data *dphy, u32 val) ++{ ++ u32 ctrl1 = dw_csi2_host_read(dphy, PHY_TST_CTRL1); ++ ++ dw_csi2_host_write(dphy, PHY_TST_CTRL1, ++ (ctrl1 & ~(1 << 16)) | (val << 16)); ++} ++ ++static void set_testdin(struct dphy_data *dphy, u32 val) ++{ ++ u32 ctrl1 = dw_csi2_host_read(dphy, PHY_TST_CTRL1); ++ ++ dw_csi2_host_write(dphy, PHY_TST_CTRL1, (ctrl1 & ~0xff) | val); ++} ++ ++static uint8_t dphy_transaction(struct dphy_data *dphy, u8 test_code, ++ uint8_t test_data) ++{ ++ /* See page 101 of the MIPI DPHY databook. */ ++ set_tstclk(dphy, 1); ++ set_testen(dphy, 0); ++ set_testdin(dphy, test_code); ++ set_testen(dphy, 1); ++ set_tstclk(dphy, 0); ++ set_testen(dphy, 0); ++ set_testdin(dphy, test_data); ++ set_tstclk(dphy, 1); ++ return get_tstdout(dphy); ++} ++ ++static void dphy_set_hsfreqrange(struct dphy_data *dphy, uint32_t freq_mhz) ++{ ++ /* See Table 5-1 on page 65 of dphy databook */ ++ static const u16 hsfreqrange_table[][2] = { ++ { 89, 0b000000 }, { 99, 0b010000 }, { 109, 0b100000 }, ++ { 129, 0b000001 }, { 139, 0b010001 }, { 149, 0b100001 }, ++ { 169, 0b000010 }, { 179, 0b010010 }, { 199, 0b100010 }, ++ { 219, 0b000011 }, { 239, 0b010011 }, { 249, 0b100011 }, ++ { 269, 0b000100 }, { 299, 0b010100 }, { 329, 0b000101 }, ++ { 359, 0b010101 }, { 399, 0b100101 }, { 449, 0b000110 }, ++ { 499, 0b010110 }, { 549, 0b000111 }, { 599, 0b010111 }, ++ { 649, 0b001000 }, { 699, 0b011000 }, { 749, 0b001001 }, ++ { 799, 0b011001 }, { 849, 0b101001 }, { 899, 0b111001 }, ++ { 949, 0b001010 }, { 999, 0b011010 }, { 1049, 0b101010 }, ++ { 1099, 0b111010 }, { 1149, 0b001011 }, { 1199, 0b011011 }, ++ { 1249, 0b101011 }, { 1299, 0b111011 }, { 1349, 0b001100 }, ++ { 1399, 0b011100 }, { 1449, 0b101100 }, { 1500, 0b111100 }, ++ }; ++ unsigned int i; ++ ++ if (freq_mhz < 80 || freq_mhz > 1500) ++ dphy_err("DPHY: Frequency %u MHz out of range\n", freq_mhz); ++ ++ for (i = 0; i < ARRAY_SIZE(hsfreqrange_table) - 1; i++) { ++ if (freq_mhz <= hsfreqrange_table[i][0]) ++ break; ++ } ++ ++ dphy_transaction(dphy, DPHY_HS_RX_CTRL_LANE0_OFFSET, ++ hsfreqrange_table[i][1] << 1); ++} ++ ++static void dphy_init(struct dphy_data *dphy) ++{ ++ dw_csi2_host_write(dphy, PHY_RSTZ, 0); ++ dw_csi2_host_write(dphy, PHY_SHUTDOWNZ, 0); ++ set_tstclk(dphy, 1); ++ set_testen(dphy, 0); ++ set_tstclr(dphy, 1); ++ usleep_range(15, 20); ++ set_tstclr(dphy, 0); ++ usleep_range(15, 20); ++ ++ dphy_set_hsfreqrange(dphy, dphy->dphy_freq); ++ ++ usleep_range(5, 10); ++ dw_csi2_host_write(dphy, PHY_SHUTDOWNZ, 1); ++ usleep_range(5, 10); ++ dw_csi2_host_write(dphy, PHY_RSTZ, 1); ++} ++ ++void dphy_start(struct dphy_data *dphy) ++{ ++ dw_csi2_host_write(dphy, N_LANES, (dphy->num_lanes - 1)); ++ dphy_init(dphy); ++ dw_csi2_host_write(dphy, RESETN, 0xffffffff); ++ usleep_range(10, 50); ++} ++ ++void dphy_stop(struct dphy_data *dphy) ++{ ++ /* Set only one lane (lane 0) as active (ON) */ ++ dw_csi2_host_write(dphy, N_LANES, 0); ++ dw_csi2_host_write(dphy, RESETN, 0); ++} ++ ++void dphy_probe(struct dphy_data *dphy) ++{ ++ u32 host_ver; ++ u8 host_ver_major, host_ver_minor; ++ ++ host_ver = dw_csi2_host_read(dphy, VERSION); ++ host_ver_major = (u8)((host_ver >> 24) - '0'); ++ host_ver_minor = (u8)((host_ver >> 16) - '0'); ++ host_ver_minor = host_ver_minor * 10; ++ host_ver_minor += (u8)((host_ver >> 8) - '0'); ++ ++ dphy_info("DW dphy Host HW v%u.%u\n", host_ver_major, host_ver_minor); ++} +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.h +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (c) 2021 Raspberry Pi Ltd. ++ * ++ */ ++ ++#ifndef _RP1_DPHY_ ++#define _RP1_DPHY_ ++ ++#include ++#include ++ ++struct dphy_data { ++ struct device *dev; ++ ++ void __iomem *base; ++ ++ u32 dphy_freq; ++ u32 num_lanes; ++}; ++ ++void dphy_probe(struct dphy_data *dphy); ++void dphy_start(struct dphy_data *dphy); ++void dphy_stop(struct dphy_data *dphy); ++ ++#endif +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h +@@ -0,0 +1,69 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 PiSP common definitions. ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _PISP_COMMON_H_ ++#define _PISP_COMMON_H_ ++ ++#include "pisp_types.h" ++ ++struct pisp_bla_config { ++ u16 black_level_r; ++ u16 black_level_gr; ++ u16 black_level_gb; ++ u16 black_level_b; ++ u16 output_black_level; ++ u8 pad[2]; ++}; ++ ++struct pisp_wbg_config { ++ u16 gain_r; ++ u16 gain_g; ++ u16 gain_b; ++ u8 pad[2]; ++}; ++ ++struct pisp_compress_config { ++ /* value subtracted from incoming data */ ++ u16 offset; ++ u8 pad; ++ /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */ ++ u8 mode; ++}; ++ ++struct pisp_decompress_config { ++ /* value added to reconstructed data */ ++ u16 offset; ++ u8 pad; ++ /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */ ++ u8 mode; ++}; ++ ++enum pisp_axi_flags { ++ /* ++ * round down bursts to end at a 32-byte boundary, to align following ++ * bursts ++ */ ++ PISP_AXI_FLAG_ALIGN = 128, ++ /* for FE writer: force WSTRB high, to pad output to 16-byte boundary */ ++ PISP_AXI_FLAG_PAD = 64, ++ /* for FE writer: Use Output FIFO level to trigger "panic" */ ++ PISP_AXI_FLAG_PANIC = 32, ++}; ++ ++struct pisp_axi_config { ++ /* ++ * burst length minus one, which must be in the range 0:15; OR'd with ++ * flags ++ */ ++ u8 maxlen_flags; ++ /* { prot[2:0], cache[3:0] } fields, echoed on AXI bus */ ++ u8 cache_prot; ++ /* QoS field(s) (4x4 bits for FE writer; 4 bits for other masters) */ ++ u16 qos; ++}; ++ ++#endif /* _PISP_COMMON_H_ */ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -0,0 +1,563 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * PiSP Front End driver. ++ * Copyright (c) 2021 Raspberry Pi Ltd. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "pisp_fe.h" ++#include "cfe.h" ++ ++#define FE_VERSION 0x000 ++#define FE_CONTROL 0x004 ++#define FE_STATUS 0x008 ++#define FE_FRAME_STATUS 0x00c ++#define FE_ERROR_STATUS 0x010 ++#define FE_OUTPUT_STATUS 0x014 ++#define FE_INT_EN 0x018 ++#define FE_INT_STATUS 0x01c ++ ++/* CONTROL */ ++#define FE_CONTROL_QUEUE BIT(0) ++#define FE_CONTROL_ABORT BIT(1) ++#define FE_CONTROL_RESET BIT(2) ++#define FE_CONTROL_LATCH_REGS BIT(3) ++ ++/* INT_EN / INT_STATUS */ ++#define FE_INT_EOF BIT(0) ++#define FE_INT_SOF BIT(1) ++#define FE_INT_LINES0 BIT(8) ++#define FE_INT_LINES1 BIT(9) ++#define FE_INT_STATS BIT(16) ++#define FE_INT_QREADY BIT(24) ++ ++/* STATUS */ ++#define FE_STATUS_QUEUED BIT(0) ++#define FE_STATUS_WAITING BIT(1) ++#define FE_STATUS_ACTIVE BIT(2) ++ ++#define PISP_FE_CONFIG_BASE_OFFSET 0x0040 ++ ++#define PISP_FE_ENABLE_STATS_CLUSTER \ ++ (PISP_FE_ENABLE_STATS_CROP | PISP_FE_ENABLE_DECIMATE | \ ++ PISP_FE_ENABLE_BLC | PISP_FE_ENABLE_CDAF_STATS | \ ++ PISP_FE_ENABLE_AWB_STATS | PISP_FE_ENABLE_RGBY | \ ++ PISP_FE_ENABLE_LSC | PISP_FE_ENABLE_AGC_STATS) ++ ++#define PISP_FE_ENABLE_OUTPUT_CLUSTER(i) \ ++ ((PISP_FE_ENABLE_CROP0 | PISP_FE_ENABLE_DOWNSCALE0 | \ ++ PISP_FE_ENABLE_COMPRESS0 | PISP_FE_ENABLE_OUTPUT0) << (4 * (i))) ++ ++struct pisp_fe_config_param { ++ u32 dirty_flags; ++ u32 dirty_flags_extra; ++ size_t offset; ++ size_t size; ++}; ++ ++static const struct pisp_fe_config_param pisp_fe_config_map[] = { ++ /* *_dirty_flag_extra types */ ++ { 0, PISP_FE_DIRTY_GLOBAL, offsetof(struct pisp_fe_config, global), ++ sizeof(struct pisp_fe_global_config) }, ++ { 0, PISP_FE_DIRTY_FLOATING, offsetof(struct pisp_fe_config, floating_stats), ++ sizeof(struct pisp_fe_floating_stats_config) }, ++ { 0, PISP_FE_DIRTY_OUTPUT_AXI, offsetof(struct pisp_fe_config, output_axi), ++ sizeof(struct pisp_fe_output_axi_config) }, ++ /* *_dirty_flag types */ ++ { PISP_FE_ENABLE_INPUT, 0, offsetof(struct pisp_fe_config, input), ++ sizeof(struct pisp_fe_input_config) }, ++ { PISP_FE_ENABLE_DECOMPRESS, 0, offsetof(struct pisp_fe_config, decompress), ++ sizeof(struct pisp_decompress_config) }, ++ { PISP_FE_ENABLE_DECOMPAND, 0, offsetof(struct pisp_fe_config, decompand), ++ sizeof(struct pisp_fe_decompand_config) }, ++ { PISP_FE_ENABLE_BLA, 0, offsetof(struct pisp_fe_config, bla), ++ sizeof(struct pisp_bla_config) }, ++ { PISP_FE_ENABLE_DPC, 0, offsetof(struct pisp_fe_config, dpc), ++ sizeof(struct pisp_fe_dpc_config) }, ++ { PISP_FE_ENABLE_STATS_CROP, 0, offsetof(struct pisp_fe_config, stats_crop), ++ sizeof(struct pisp_fe_crop_config) }, ++ { PISP_FE_ENABLE_BLC, 0, offsetof(struct pisp_fe_config, blc), ++ sizeof(struct pisp_bla_config) }, ++ { PISP_FE_ENABLE_CDAF_STATS, 0, offsetof(struct pisp_fe_config, cdaf_stats), ++ sizeof(struct pisp_fe_cdaf_stats_config) }, ++ { PISP_FE_ENABLE_AWB_STATS, 0, offsetof(struct pisp_fe_config, awb_stats), ++ sizeof(struct pisp_fe_awb_stats_config) }, ++ { PISP_FE_ENABLE_RGBY, 0, offsetof(struct pisp_fe_config, rgby), ++ sizeof(struct pisp_fe_rgby_config) }, ++ { PISP_FE_ENABLE_LSC, 0, offsetof(struct pisp_fe_config, lsc), ++ sizeof(struct pisp_fe_lsc_config) }, ++ { PISP_FE_ENABLE_AGC_STATS, 0, offsetof(struct pisp_fe_config, agc_stats), ++ sizeof(struct pisp_agc_statistics) }, ++ { PISP_FE_ENABLE_CROP0, 0, offsetof(struct pisp_fe_config, ch[0].crop), ++ sizeof(struct pisp_fe_crop_config) }, ++ { PISP_FE_ENABLE_DOWNSCALE0, 0, offsetof(struct pisp_fe_config, ch[0].downscale), ++ sizeof(struct pisp_fe_downscale_config) }, ++ { PISP_FE_ENABLE_COMPRESS0, 0, offsetof(struct pisp_fe_config, ch[0].compress), ++ sizeof(struct pisp_compress_config) }, ++ { PISP_FE_ENABLE_OUTPUT0, 0, offsetof(struct pisp_fe_config, ch[0].output), ++ sizeof(struct pisp_fe_output_config) }, ++ { PISP_FE_ENABLE_CROP1, 0, offsetof(struct pisp_fe_config, ch[1].crop), ++ sizeof(struct pisp_fe_crop_config) }, ++ { PISP_FE_ENABLE_DOWNSCALE1, 0, offsetof(struct pisp_fe_config, ch[1].downscale), ++ sizeof(struct pisp_fe_downscale_config) }, ++ { PISP_FE_ENABLE_COMPRESS1, 0, offsetof(struct pisp_fe_config, ch[1].compress), ++ sizeof(struct pisp_compress_config) }, ++ { PISP_FE_ENABLE_OUTPUT1, 0, offsetof(struct pisp_fe_config, ch[1].output), ++ sizeof(struct pisp_fe_output_config) }, ++}; ++ ++#define pisp_fe_dbg_irq(fmt, arg...) \ ++ do { \ ++ if (cfe_debug_irq) \ ++ dev_dbg(fe->v4l2_dev->dev, fmt, ##arg); \ ++ } while (0) ++#define pisp_fe_dbg(fmt, arg...) dev_dbg(fe->v4l2_dev->dev, fmt, ##arg) ++#define pisp_fe_info(fmt, arg...) dev_info(fe->v4l2_dev->dev, fmt, ##arg) ++#define pisp_fe_err(fmt, arg...) dev_err(fe->v4l2_dev->dev, fmt, ##arg) ++ ++static inline u32 pisp_fe_reg_read(struct pisp_fe_device *fe, u32 offset) ++{ ++ return readl(fe->base + offset); ++} ++ ++static inline void pisp_fe_reg_write(struct pisp_fe_device *fe, u32 offset, ++ u32 val) ++{ ++ writel(val, fe->base + offset); ++} ++ ++static inline void pisp_fe_reg_write_relaxed(struct pisp_fe_device *fe, u32 offset, ++ u32 val) ++{ ++ writel_relaxed(val, fe->base + offset); ++} ++ ++static int pisp_regs_show(struct seq_file *s, void *data) ++{ ++ struct pisp_fe_device *fe = s->private; ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(fe->v4l2_dev->dev); ++ if (ret) ++ return ret; ++ ++ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_LATCH_REGS); ++ ++#define DUMP(reg) seq_printf(s, #reg " \t0x%08x\n", pisp_fe_reg_read(fe, reg)) ++ DUMP(FE_VERSION); ++ DUMP(FE_CONTROL); ++ DUMP(FE_STATUS); ++ DUMP(FE_FRAME_STATUS); ++ DUMP(FE_ERROR_STATUS); ++ DUMP(FE_OUTPUT_STATUS); ++ DUMP(FE_INT_EN); ++ DUMP(FE_INT_STATUS); ++#undef DUMP ++ ++ pm_runtime_put(fe->v4l2_dev->dev); ++ ++ return 0; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(pisp_regs); ++ ++static void pisp_config_write(struct pisp_fe_device *fe, ++ struct pisp_fe_config *config, ++ unsigned int start_offset, ++ unsigned int size) ++{ ++ const unsigned int max_offset = ++ offsetof(struct pisp_fe_config, ch[PISP_FE_NUM_OUTPUTS]); ++ unsigned int i, end_offset; ++ u32 *cfg = (u32 *)config; ++ ++ start_offset = min(start_offset, max_offset); ++ end_offset = min(start_offset + size, max_offset); ++ ++ cfg += start_offset >> 2; ++ for (i = start_offset; i < end_offset; i += 4, cfg++) ++ pisp_fe_reg_write_relaxed(fe, PISP_FE_CONFIG_BASE_OFFSET + i, ++ *cfg); ++} ++ ++void pisp_fe_isr(struct pisp_fe_device *fe, bool *sof, bool *eof) ++{ ++ u32 status, int_status, out_status, frame_status, error_status; ++ unsigned int i; ++ ++ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_LATCH_REGS); ++ status = pisp_fe_reg_read(fe, FE_STATUS); ++ out_status = pisp_fe_reg_read(fe, FE_OUTPUT_STATUS); ++ frame_status = pisp_fe_reg_read(fe, FE_FRAME_STATUS); ++ error_status = pisp_fe_reg_read(fe, FE_ERROR_STATUS); ++ ++ int_status = pisp_fe_reg_read(fe, FE_INT_STATUS); ++ pisp_fe_reg_write(fe, FE_INT_STATUS, int_status); ++ ++ pisp_fe_dbg_irq("%s: status 0x%x out 0x%x frame 0x%x error 0x%x int 0x%x\n", ++ __func__, status, out_status, frame_status, error_status, ++ int_status); ++ ++ /* We do not report interrupts for the input/stream pad. */ ++ for (i = 0; i < FE_NUM_PADS - 1; i++) { ++ sof[i] = !!(int_status & FE_INT_SOF); ++ eof[i] = !!(int_status & FE_INT_EOF); ++ } ++} ++ ++static bool pisp_fe_validate_output(struct pisp_fe_config const *cfg, ++ unsigned int c, struct v4l2_format const *f) ++{ ++ unsigned int wbytes; ++ ++ wbytes = cfg->ch[c].output.format.width; ++ if (cfg->ch[c].output.format.format & PISP_IMAGE_FORMAT_BPS_MASK) ++ wbytes *= 2; ++ ++ /* Check output image dimensions are nonzero and not too big */ ++ if (cfg->ch[c].output.format.width < 2 || ++ cfg->ch[c].output.format.height < 2 || ++ cfg->ch[c].output.format.height > f->fmt.pix.height || ++ cfg->ch[c].output.format.stride > f->fmt.pix.bytesperline || ++ wbytes > f->fmt.pix.bytesperline) ++ return false; ++ ++ /* Check for zero-sized crops, which could cause lockup */ ++ if ((cfg->global.enables & PISP_FE_ENABLE_CROP(c)) && ++ ((cfg->ch[c].crop.offset_x >= (cfg->input.format.width & ~1) || ++ cfg->ch[c].crop.offset_y >= cfg->input.format.height || ++ cfg->ch[c].crop.width < 2 || ++ cfg->ch[c].crop.height < 2))) ++ return false; ++ ++ if ((cfg->global.enables & PISP_FE_ENABLE_DOWNSCALE(c)) && ++ (cfg->ch[c].downscale.output_width < 2 || ++ cfg->ch[c].downscale.output_height < 2)) ++ return false; ++ ++ return true; ++} ++ ++static bool pisp_fe_validate_stats(struct pisp_fe_config const *cfg) ++{ ++ /* Check for zero-sized crop, which could cause lockup */ ++ return (!(cfg->global.enables & PISP_FE_ENABLE_STATS_CROP) || ++ (cfg->stats_crop.offset_x < (cfg->input.format.width & ~1) && ++ cfg->stats_crop.offset_y < cfg->input.format.height && ++ cfg->stats_crop.width >= 2 && ++ cfg->stats_crop.height >= 2)); ++} ++ ++int pisp_fe_validate_config(struct pisp_fe_device *fe, ++ struct pisp_fe_config *cfg, ++ struct v4l2_format const *f0, ++ struct v4l2_format const *f1) ++{ ++ unsigned int i; ++ ++ /* ++ * Check the input is enabled, streaming and has nonzero size; ++ * to avoid cases where the hardware might lock up or try to ++ * read inputs from memory (which this driver doesn't support). ++ */ ++ if (!(cfg->global.enables & PISP_FE_ENABLE_INPUT) || ++ cfg->input.streaming != 1 || cfg->input.format.width < 2 || ++ cfg->input.format.height < 2) { ++ pisp_fe_err("%s: Input config not valid", __func__); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < PISP_FE_NUM_OUTPUTS; i++) { ++ if (!(cfg->global.enables & PISP_FE_ENABLE_OUTPUT(i))) { ++ if (cfg->global.enables & ++ PISP_FE_ENABLE_OUTPUT_CLUSTER(i)) { ++ pisp_fe_err("%s: Output %u not valid", ++ __func__, i); ++ return -EINVAL; ++ } ++ continue; ++ } ++ ++ if (!pisp_fe_validate_output(cfg, i, i ? f1 : f0)) ++ return -EINVAL; ++ } ++ ++ if ((cfg->global.enables & PISP_FE_ENABLE_STATS_CLUSTER) && ++ !pisp_fe_validate_stats(cfg)) { ++ pisp_fe_err("%s: Stats config not valid", __func__); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++void pisp_fe_submit_job(struct pisp_fe_device *fe, struct vb2_buffer **vb2_bufs, ++ struct pisp_fe_config *cfg) ++{ ++ unsigned int i; ++ u64 addr; ++ u32 status; ++ ++ /* ++ * Check output buffers exist and outputs are correctly configured. ++ * If valid, set the buffer's DMA address; otherwise disable. ++ */ ++ for (i = 0; i < PISP_FE_NUM_OUTPUTS; i++) { ++ struct vb2_buffer *buf = vb2_bufs[FE_OUTPUT0_PAD + i]; ++ ++ if (!(cfg->global.enables & PISP_FE_ENABLE_OUTPUT(i))) ++ continue; ++ ++ addr = vb2_dma_contig_plane_dma_addr(buf, 0); ++ cfg->output_buffer[i].addr_lo = addr & 0xffffffff; ++ cfg->output_buffer[i].addr_hi = addr >> 32; ++ } ++ ++ if (vb2_bufs[FE_STATS_PAD]) { ++ addr = vb2_dma_contig_plane_dma_addr(vb2_bufs[FE_STATS_PAD], 0); ++ cfg->stats_buffer.addr_lo = addr & 0xffffffff; ++ cfg->stats_buffer.addr_hi = addr >> 32; ++ } ++ ++ /* Set up ILINES interrupts 3/4 of the way down each output */ ++ cfg->ch[0].output.ilines = ++ max(0x80u, (3u * cfg->ch[0].output.format.height) >> 2); ++ cfg->ch[1].output.ilines = ++ max(0x80u, (3u * cfg->ch[1].output.format.height) >> 2); ++ ++ /* ++ * The hardware must have consumed the previous config by now. ++ * This read of status also serves as a memory barrier before the ++ * sequence of relaxed writes which follow. ++ */ ++ status = pisp_fe_reg_read(fe, FE_STATUS); ++ pisp_fe_dbg_irq("%s: status = 0x%x\n", __func__, status); ++ if (WARN_ON(status & FE_STATUS_QUEUED)) ++ return; ++ ++ /* ++ * Unconditionally write buffers, global and input parameters. ++ * Write cropping and output parameters whenever they are enabled. ++ * Selectively write other parameters that have been marked as ++ * changed through the dirty flags. ++ */ ++ pisp_config_write(fe, cfg, 0, ++ offsetof(struct pisp_fe_config, decompress)); ++ cfg->dirty_flags_extra &= ~PISP_FE_DIRTY_GLOBAL; ++ cfg->dirty_flags &= ~PISP_FE_ENABLE_INPUT; ++ cfg->dirty_flags |= (cfg->global.enables & ++ (PISP_FE_ENABLE_STATS_CROP | ++ PISP_FE_ENABLE_OUTPUT_CLUSTER(0) | ++ PISP_FE_ENABLE_OUTPUT_CLUSTER(1))); ++ for (i = 0; i < ARRAY_SIZE(pisp_fe_config_map); i++) { ++ const struct pisp_fe_config_param *p = &pisp_fe_config_map[i]; ++ ++ if (cfg->dirty_flags & p->dirty_flags || ++ cfg->dirty_flags_extra & p->dirty_flags_extra) ++ pisp_config_write(fe, cfg, p->offset, p->size); ++ } ++ ++ /* This final non-relaxed write serves as a memory barrier */ ++ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_QUEUE); ++} ++ ++void pisp_fe_start(struct pisp_fe_device *fe) ++{ ++ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_RESET); ++ pisp_fe_reg_write(fe, FE_INT_STATUS, -1); ++ pisp_fe_reg_write(fe, FE_INT_EN, FE_INT_EOF | FE_INT_SOF | FE_INT_LINES0 | FE_INT_LINES1); ++ fe->inframe_count = 0; ++} ++ ++void pisp_fe_stop(struct pisp_fe_device *fe) ++{ ++ pisp_fe_reg_write(fe, FE_INT_EN, 0); ++ pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_ABORT); ++ usleep_range(1000, 2000); ++ WARN_ON(pisp_fe_reg_read(fe, FE_STATUS)); ++ pisp_fe_reg_write(fe, FE_INT_STATUS, -1); ++} ++ ++static struct pisp_fe_device *to_pisp_fe_device(struct v4l2_subdev *subdev) ++{ ++ return container_of(subdev, struct pisp_fe_device, sd); ++} ++ ++static int pisp_fe_init_cfg(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state) ++{ ++ struct v4l2_mbus_framefmt *fmt; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_STREAM_PAD); ++ *fmt = cfe_default_format; ++ fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_CONFIG_PAD); ++ *fmt = cfe_default_meta_format; ++ fmt->code = MEDIA_BUS_FMT_PISP_FE_CONFIG; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT0_PAD); ++ *fmt = cfe_default_format; ++ fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT1_PAD); ++ *fmt = cfe_default_format; ++ fmt->code = MEDIA_BUS_FMT_SRGGB16_1X16; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_STATS_PAD); ++ *fmt = cfe_default_meta_format; ++ fmt->code = MEDIA_BUS_FMT_PISP_FE_STATS; ++ ++ return 0; ++} ++ ++static int pisp_fe_pad_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *fmt; ++ const struct cfe_fmt *cfe_fmt; ++ ++ /* TODO: format propagation to source pads */ ++ /* TODO: format validation */ ++ ++ switch (format->pad) { ++ case FE_STREAM_PAD: ++ case FE_OUTPUT0_PAD: ++ case FE_OUTPUT1_PAD: ++ cfe_fmt = find_format_by_code(format->format.code); ++ if (!cfe_fmt || !(cfe_fmt->flags & CFE_FORMAT_FLAG_FE_OUT)) ++ cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10); ++ ++ format->format.code = cfe_fmt->code; ++ ++ break; ++ ++ case FE_CONFIG_PAD: ++ format->format.code = MEDIA_BUS_FMT_PISP_FE_CONFIG; ++ break; ++ ++ case FE_STATS_PAD: ++ format->format.code = MEDIA_BUS_FMT_PISP_FE_STATS; ++ break; ++ } ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); ++ *fmt = format->format; ++ ++ return 0; ++} ++ ++static int pisp_fe_link_validate(struct v4l2_subdev *sd, ++ struct media_link *link, ++ struct v4l2_subdev_format *source_fmt, ++ struct v4l2_subdev_format *sink_fmt) ++{ ++ struct pisp_fe_device *fe = to_pisp_fe_device(sd); ++ ++ pisp_fe_dbg("%s: link \"%s\":%u -> \"%s\":%u\n", __func__, ++ link->source->entity->name, link->source->index, ++ link->sink->entity->name, link->sink->index); ++ ++ /* The width, height and code must match. */ ++ if (source_fmt->format.width != sink_fmt->format.width || ++ source_fmt->format.width != sink_fmt->format.width || ++ source_fmt->format.code != sink_fmt->format.code) { ++ pisp_fe_err("%s: format does not match (source %ux%u 0x%x, sink %ux%u 0x%x)\n", ++ __func__, ++ source_fmt->format.width, ++ source_fmt->format.height, ++ source_fmt->format.code, ++ sink_fmt->format.width, ++ sink_fmt->format.height, ++ sink_fmt->format.code); ++ return -EPIPE; ++ } ++ ++ return 0; ++} ++ ++static const struct v4l2_subdev_pad_ops pisp_fe_subdev_pad_ops = { ++ .init_cfg = pisp_fe_init_cfg, ++ .get_fmt = v4l2_subdev_get_fmt, ++ .set_fmt = pisp_fe_pad_set_fmt, ++ .link_validate = pisp_fe_link_validate, ++}; ++ ++static const struct media_entity_operations pisp_fe_entity_ops = { ++ .link_validate = v4l2_subdev_link_validate, ++}; ++ ++static const struct v4l2_subdev_ops pisp_fe_subdev_ops = { ++ .pad = &pisp_fe_subdev_pad_ops, ++}; ++ ++int pisp_fe_init(struct pisp_fe_device *fe, struct dentry *debugfs) ++{ ++ int ret; ++ ++ debugfs_create_file("pisp_regs", 0444, debugfs, fe, &pisp_regs_fops); ++ ++ fe->hw_revision = pisp_fe_reg_read(fe, FE_VERSION); ++ pisp_fe_info("PiSP FE HW v%u.%u\n", ++ (fe->hw_revision >> 24) & 0xff, ++ (fe->hw_revision >> 20) & 0x0f); ++ ++ fe->pad[FE_STREAM_PAD].flags = ++ MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; ++ fe->pad[FE_CONFIG_PAD].flags = MEDIA_PAD_FL_SINK; ++ fe->pad[FE_OUTPUT0_PAD].flags = MEDIA_PAD_FL_SOURCE; ++ fe->pad[FE_OUTPUT1_PAD].flags = MEDIA_PAD_FL_SOURCE; ++ fe->pad[FE_STATS_PAD].flags = MEDIA_PAD_FL_SOURCE; ++ ++ ret = media_entity_pads_init(&fe->sd.entity, ARRAY_SIZE(fe->pad), ++ fe->pad); ++ if (ret) ++ return ret; ++ ++ /* Initialize subdev */ ++ v4l2_subdev_init(&fe->sd, &pisp_fe_subdev_ops); ++ fe->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER; ++ fe->sd.entity.ops = &pisp_fe_entity_ops; ++ fe->sd.entity.name = "pisp-fe"; ++ fe->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ fe->sd.owner = THIS_MODULE; ++ snprintf(fe->sd.name, sizeof(fe->sd.name), "pisp-fe"); ++ ++ ret = v4l2_subdev_init_finalize(&fe->sd); ++ if (ret) ++ goto err_entity_cleanup; ++ ++ ret = v4l2_device_register_subdev(fe->v4l2_dev, &fe->sd); ++ if (ret) { ++ pisp_fe_err("Failed register pisp fe subdev (%d)\n", ret); ++ goto err_subdev_cleanup; ++ } ++ ++ /* Must be in IDLE state (STATUS == 0) here. */ ++ WARN_ON(pisp_fe_reg_read(fe, FE_STATUS)); ++ ++ return 0; ++ ++err_subdev_cleanup: ++ v4l2_subdev_cleanup(&fe->sd); ++err_entity_cleanup: ++ media_entity_cleanup(&fe->sd.entity); ++ ++ return ret; ++} ++ ++void pisp_fe_uninit(struct pisp_fe_device *fe) ++{ ++ v4l2_device_unregister_subdev(&fe->sd); ++ v4l2_subdev_cleanup(&fe->sd); ++ media_entity_cleanup(&fe->sd.entity); ++} +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.h +@@ -0,0 +1,53 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * PiSP Front End driver. ++ * Copyright (c) 2021 Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _PISP_FE_H_ ++#define _PISP_FE_H_ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "pisp_fe_config.h" ++ ++enum pisp_fe_pads { ++ FE_STREAM_PAD, ++ FE_CONFIG_PAD, ++ FE_OUTPUT0_PAD, ++ FE_OUTPUT1_PAD, ++ FE_STATS_PAD, ++ FE_NUM_PADS ++}; ++ ++struct pisp_fe_device { ++ /* Parent V4l2 device */ ++ struct v4l2_device *v4l2_dev; ++ void __iomem *base; ++ u32 hw_revision; ++ ++ u16 inframe_count; ++ struct media_pad pad[FE_NUM_PADS]; ++ struct v4l2_subdev sd; ++}; ++ ++void pisp_fe_isr(struct pisp_fe_device *fe, bool *sof, bool *eof); ++int pisp_fe_validate_config(struct pisp_fe_device *fe, ++ struct pisp_fe_config *cfg, ++ struct v4l2_format const *f0, ++ struct v4l2_format const *f1); ++void pisp_fe_submit_job(struct pisp_fe_device *fe, struct vb2_buffer **vb2_bufs, ++ struct pisp_fe_config *cfg); ++void pisp_fe_start(struct pisp_fe_device *fe); ++void pisp_fe_stop(struct pisp_fe_device *fe); ++int pisp_fe_init(struct pisp_fe_device *fe, struct dentry *debugfs); ++void pisp_fe_uninit(struct pisp_fe_device *fe); ++ ++#endif +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h +@@ -0,0 +1,272 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 PiSP Front End Driver Configuration structures ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _PISP_FE_CONFIG_ ++#define _PISP_FE_CONFIG_ ++ ++#include ++ ++#include "pisp_statistics.h" ++ ++#define PISP_FE_NUM_OUTPUTS 2 ++ ++enum pisp_fe_enable { ++ PISP_FE_ENABLE_INPUT = 0x000001, ++ PISP_FE_ENABLE_DECOMPRESS = 0x000002, ++ PISP_FE_ENABLE_DECOMPAND = 0x000004, ++ PISP_FE_ENABLE_BLA = 0x000008, ++ PISP_FE_ENABLE_DPC = 0x000010, ++ PISP_FE_ENABLE_STATS_CROP = 0x000020, ++ PISP_FE_ENABLE_DECIMATE = 0x000040, ++ PISP_FE_ENABLE_BLC = 0x000080, ++ PISP_FE_ENABLE_CDAF_STATS = 0x000100, ++ PISP_FE_ENABLE_AWB_STATS = 0x000200, ++ PISP_FE_ENABLE_RGBY = 0x000400, ++ PISP_FE_ENABLE_LSC = 0x000800, ++ PISP_FE_ENABLE_AGC_STATS = 0x001000, ++ PISP_FE_ENABLE_CROP0 = 0x010000, ++ PISP_FE_ENABLE_DOWNSCALE0 = 0x020000, ++ PISP_FE_ENABLE_COMPRESS0 = 0x040000, ++ PISP_FE_ENABLE_OUTPUT0 = 0x080000, ++ PISP_FE_ENABLE_CROP1 = 0x100000, ++ PISP_FE_ENABLE_DOWNSCALE1 = 0x200000, ++ PISP_FE_ENABLE_COMPRESS1 = 0x400000, ++ PISP_FE_ENABLE_OUTPUT1 = 0x800000 ++}; ++ ++#define PISP_FE_ENABLE_CROP(i) (PISP_FE_ENABLE_CROP0 << (4 * (i))) ++#define PISP_FE_ENABLE_DOWNSCALE(i) (PISP_FE_ENABLE_DOWNSCALE0 << (4 * (i))) ++#define PISP_FE_ENABLE_COMPRESS(i) (PISP_FE_ENABLE_COMPRESS0 << (4 * (i))) ++#define PISP_FE_ENABLE_OUTPUT(i) (PISP_FE_ENABLE_OUTPUT0 << (4 * (i))) ++ ++/* ++ * We use the enable flags to show when blocks are "dirty", but we need some ++ * extra ones too. ++ */ ++enum pisp_fe_dirty { ++ PISP_FE_DIRTY_GLOBAL = 0x0001, ++ PISP_FE_DIRTY_FLOATING = 0x0002, ++ PISP_FE_DIRTY_OUTPUT_AXI = 0x0004 ++}; ++ ++struct pisp_fe_global_config { ++ u32 enables; ++ u8 bayer_order; ++ u8 pad[3]; ++}; ++ ++struct pisp_fe_input_axi_config { ++ /* burst length minus one, in the range 0..15; OR'd with flags */ ++ u8 maxlen_flags; ++ /* { prot[2:0], cache[3:0] } fields */ ++ u8 cache_prot; ++ /* QoS (only 4 LS bits are used) */ ++ u16 qos; ++}; ++ ++struct pisp_fe_output_axi_config { ++ /* burst length minus one, in the range 0..15; OR'd with flags */ ++ u8 maxlen_flags; ++ /* { prot[2:0], cache[3:0] } fields */ ++ u8 cache_prot; ++ /* QoS (4 bitfields of 4 bits each for different panic levels) */ ++ u16 qos; ++ /* For Panic mode: Output FIFO panic threshold */ ++ u16 thresh; ++ /* For Panic mode: Output FIFO statistics throttle threshold */ ++ u16 throttle; ++}; ++ ++struct pisp_fe_input_config { ++ u8 streaming; ++ u8 pad[3]; ++ struct pisp_image_format_config format; ++ struct pisp_fe_input_axi_config axi; ++ /* Extra cycles delay before issuing each burst request */ ++ u8 holdoff; ++ u8 pad2[3]; ++}; ++ ++struct pisp_fe_output_config { ++ struct pisp_image_format_config format; ++ u16 ilines; ++ u8 pad[2]; ++}; ++ ++struct pisp_fe_input_buffer_config { ++ u32 addr_lo; ++ u32 addr_hi; ++ u16 frame_id; ++ u16 pad; ++}; ++ ++#define PISP_FE_DECOMPAND_LUT_SIZE 65 ++ ++struct pisp_fe_decompand_config { ++ u16 lut[PISP_FE_DECOMPAND_LUT_SIZE]; ++ u16 pad; ++}; ++ ++struct pisp_fe_dpc_config { ++ u8 coeff_level; ++ u8 coeff_range; ++ u8 coeff_range2; ++#define PISP_FE_DPC_FLAG_FOLDBACK 1 ++#define PISP_FE_DPC_FLAG_VFLAG 2 ++ u8 flags; ++}; ++ ++#define PISP_FE_LSC_LUT_SIZE 16 ++ ++struct pisp_fe_lsc_config { ++ u8 shift; ++ u8 pad0; ++ u16 scale; ++ u16 centre_x; ++ u16 centre_y; ++ u16 lut[PISP_FE_LSC_LUT_SIZE]; ++}; ++ ++struct pisp_fe_rgby_config { ++ u16 gain_r; ++ u16 gain_g; ++ u16 gain_b; ++ u8 maxflag; ++ u8 pad; ++}; ++ ++struct pisp_fe_agc_stats_config { ++ u16 offset_x; ++ u16 offset_y; ++ u16 size_x; ++ u16 size_y; ++ /* each weight only 4 bits */ ++ u8 weights[PISP_AGC_STATS_NUM_ZONES / 2]; ++ u16 row_offset_x; ++ u16 row_offset_y; ++ u16 row_size_x; ++ u16 row_size_y; ++ u8 row_shift; ++ u8 float_shift; ++ u8 pad1[2]; ++}; ++ ++struct pisp_fe_awb_stats_config { ++ u16 offset_x; ++ u16 offset_y; ++ u16 size_x; ++ u16 size_y; ++ u8 shift; ++ u8 pad[3]; ++ u16 r_lo; ++ u16 r_hi; ++ u16 g_lo; ++ u16 g_hi; ++ u16 b_lo; ++ u16 b_hi; ++}; ++ ++struct pisp_fe_floating_stats_region { ++ u16 offset_x; ++ u16 offset_y; ++ u16 size_x; ++ u16 size_y; ++}; ++ ++struct pisp_fe_floating_stats_config { ++ struct pisp_fe_floating_stats_region ++ regions[PISP_FLOATING_STATS_NUM_ZONES]; ++}; ++ ++#define PISP_FE_CDAF_NUM_WEIGHTS 8 ++ ++struct pisp_fe_cdaf_stats_config { ++ u16 noise_constant; ++ u16 noise_slope; ++ u16 offset_x; ++ u16 offset_y; ++ u16 size_x; ++ u16 size_y; ++ u16 skip_x; ++ u16 skip_y; ++ u32 mode; ++}; ++ ++struct pisp_fe_stats_buffer_config { ++ u32 addr_lo; ++ u32 addr_hi; ++}; ++ ++struct pisp_fe_crop_config { ++ u16 offset_x; ++ u16 offset_y; ++ u16 width; ++ u16 height; ++}; ++ ++enum pisp_fe_downscale_flags { ++ DOWNSCALE_BAYER = ++ 1, /* downscale the four Bayer components independently... */ ++ DOWNSCALE_BIN = ++ 2 /* ...without trying to preserve their spatial relationship */ ++}; ++ ++struct pisp_fe_downscale_config { ++ u8 xin; ++ u8 xout; ++ u8 yin; ++ u8 yout; ++ u8 flags; /* enum pisp_fe_downscale_flags */ ++ u8 pad[3]; ++ u16 output_width; ++ u16 output_height; ++}; ++ ++struct pisp_fe_output_buffer_config { ++ u32 addr_lo; ++ u32 addr_hi; ++}; ++ ++/* Each of the two output channels/branches: */ ++struct pisp_fe_output_branch_config { ++ struct pisp_fe_crop_config crop; ++ struct pisp_fe_downscale_config downscale; ++ struct pisp_compress_config compress; ++ struct pisp_fe_output_config output; ++ u32 pad; ++}; ++ ++/* And finally one to rule them all: */ ++struct pisp_fe_config { ++ /* I/O configuration: */ ++ struct pisp_fe_stats_buffer_config stats_buffer; ++ struct pisp_fe_output_buffer_config output_buffer[PISP_FE_NUM_OUTPUTS]; ++ struct pisp_fe_input_buffer_config input_buffer; ++ /* processing configuration: */ ++ struct pisp_fe_global_config global; ++ struct pisp_fe_input_config input; ++ struct pisp_decompress_config decompress; ++ struct pisp_fe_decompand_config decompand; ++ struct pisp_bla_config bla; ++ struct pisp_fe_dpc_config dpc; ++ struct pisp_fe_crop_config stats_crop; ++ u32 spare1; /* placeholder for future decimate configuration */ ++ struct pisp_bla_config blc; ++ struct pisp_fe_rgby_config rgby; ++ struct pisp_fe_lsc_config lsc; ++ struct pisp_fe_agc_stats_config agc_stats; ++ struct pisp_fe_awb_stats_config awb_stats; ++ struct pisp_fe_cdaf_stats_config cdaf_stats; ++ struct pisp_fe_floating_stats_config floating_stats; ++ struct pisp_fe_output_axi_config output_axi; ++ struct pisp_fe_output_branch_config ch[PISP_FE_NUM_OUTPUTS]; ++ /* non-register fields: */ ++ u32 dirty_flags; /* these use pisp_fe_enable */ ++ u32 dirty_flags_extra; /* these use pisp_fe_dirty */ ++}; ++ ++#endif /* _PISP_FE_CONFIG_ */ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h +@@ -0,0 +1,62 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 PiSP Front End statistics definitions ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _PISP_FE_STATISTICS_H_ ++#define _PISP_FE_STATISTICS_H_ ++ ++#define PISP_FLOATING_STATS_NUM_ZONES 4 ++#define PISP_AGC_STATS_NUM_BINS 1024 ++#define PISP_AGC_STATS_SIZE 16 ++#define PISP_AGC_STATS_NUM_ZONES (PISP_AGC_STATS_SIZE * PISP_AGC_STATS_SIZE) ++#define PISP_AGC_STATS_NUM_ROW_SUMS 512 ++ ++struct pisp_agc_statistics_zone { ++ u64 Y_sum; ++ u32 counted; ++ u32 pad; ++}; ++ ++struct pisp_agc_statistics { ++ u32 row_sums[PISP_AGC_STATS_NUM_ROW_SUMS]; ++ /* ++ * 32-bits per bin means an image (just less than) 16384x16384 pixels ++ * in size can weight every pixel from 0 to 15. ++ */ ++ u32 histogram[PISP_AGC_STATS_NUM_BINS]; ++ struct pisp_agc_statistics_zone floating[PISP_FLOATING_STATS_NUM_ZONES]; ++}; ++ ++#define PISP_AWB_STATS_SIZE 32 ++#define PISP_AWB_STATS_NUM_ZONES (PISP_AWB_STATS_SIZE * PISP_AWB_STATS_SIZE) ++ ++struct pisp_awb_statistics_zone { ++ u32 R_sum; ++ u32 G_sum; ++ u32 B_sum; ++ u32 counted; ++}; ++ ++struct pisp_awb_statistics { ++ struct pisp_awb_statistics_zone zones[PISP_AWB_STATS_NUM_ZONES]; ++ struct pisp_awb_statistics_zone floating[PISP_FLOATING_STATS_NUM_ZONES]; ++}; ++ ++#define PISP_CDAF_STATS_SIZE 8 ++#define PISP_CDAF_STATS_NUM_FOMS (PISP_CDAF_STATS_SIZE * PISP_CDAF_STATS_SIZE) ++ ++struct pisp_cdaf_statistics { ++ u64 foms[PISP_CDAF_STATS_NUM_FOMS]; ++ u64 floating[PISP_FLOATING_STATS_NUM_ZONES]; ++}; ++ ++struct pisp_statistics { ++ struct pisp_awb_statistics awb; ++ struct pisp_agc_statistics agc; ++ struct pisp_cdaf_statistics cdaf; ++}; ++ ++#endif /* _PISP_FE_STATISTICS_H_ */ +--- /dev/null ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h +@@ -0,0 +1,144 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RP1 PiSP Front End image definitions. ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _PISP_FE_TYPES_H_ ++#define _PISP_FE_TYPES_H_ ++ ++/* This definition must match the format description in the hardware exactly! */ ++struct pisp_image_format_config { ++ /* size in pixels */ ++ u16 width, height; ++ /* must match struct pisp_image_format below */ ++ u32 format; ++ s32 stride; ++ /* some planar image formats will need a second stride */ ++ s32 stride2; ++}; ++ ++static_assert(sizeof(struct pisp_image_format_config) == 16); ++ ++enum pisp_bayer_order { ++ /* ++ * Note how bayer_order&1 tells you if G is on the even pixels of the ++ * checkerboard or not, and bayer_order&2 tells you if R is on the even ++ * rows or is swapped with B. Note that if the top (of the 8) bits is ++ * set, this denotes a monochrome or greyscale image, and the lower bits ++ * should all be ignored. ++ */ ++ PISP_BAYER_ORDER_RGGB = 0, ++ PISP_BAYER_ORDER_GBRG = 1, ++ PISP_BAYER_ORDER_BGGR = 2, ++ PISP_BAYER_ORDER_GRBG = 3, ++ PISP_BAYER_ORDER_GREYSCALE = 128 ++}; ++ ++enum pisp_image_format { ++ /* ++ * Precise values are mostly tbd. Generally these will be portmanteau ++ * values comprising bit fields and flags. This format must be shared ++ * throughout the PiSP. ++ */ ++ PISP_IMAGE_FORMAT_BPS_8 = 0x00000000, ++ PISP_IMAGE_FORMAT_BPS_10 = 0x00000001, ++ PISP_IMAGE_FORMAT_BPS_12 = 0x00000002, ++ PISP_IMAGE_FORMAT_BPS_16 = 0x00000003, ++ PISP_IMAGE_FORMAT_BPS_MASK = 0x00000003, ++ ++ PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED = 0x00000000, ++ PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR = 0x00000010, ++ PISP_IMAGE_FORMAT_PLANARITY_PLANAR = 0x00000020, ++ PISP_IMAGE_FORMAT_PLANARITY_MASK = 0x00000030, ++ ++ PISP_IMAGE_FORMAT_SAMPLING_444 = 0x00000000, ++ PISP_IMAGE_FORMAT_SAMPLING_422 = 0x00000100, ++ PISP_IMAGE_FORMAT_SAMPLING_420 = 0x00000200, ++ PISP_IMAGE_FORMAT_SAMPLING_MASK = 0x00000300, ++ ++ PISP_IMAGE_FORMAT_ORDER_NORMAL = 0x00000000, ++ PISP_IMAGE_FORMAT_ORDER_SWAPPED = 0x00001000, ++ ++ PISP_IMAGE_FORMAT_SHIFT_0 = 0x00000000, ++ PISP_IMAGE_FORMAT_SHIFT_1 = 0x00010000, ++ PISP_IMAGE_FORMAT_SHIFT_2 = 0x00020000, ++ PISP_IMAGE_FORMAT_SHIFT_3 = 0x00030000, ++ PISP_IMAGE_FORMAT_SHIFT_4 = 0x00040000, ++ PISP_IMAGE_FORMAT_SHIFT_5 = 0x00050000, ++ PISP_IMAGE_FORMAT_SHIFT_6 = 0x00060000, ++ PISP_IMAGE_FORMAT_SHIFT_7 = 0x00070000, ++ PISP_IMAGE_FORMAT_SHIFT_8 = 0x00080000, ++ PISP_IMAGE_FORMAT_SHIFT_MASK = 0x000f0000, ++ ++ PISP_IMAGE_FORMAT_UNCOMPRESSED = 0x00000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MODE_1 = 0x01000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MODE_2 = 0x02000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MODE_3 = 0x03000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MASK = 0x03000000, ++ ++ PISP_IMAGE_FORMAT_HOG_SIGNED = 0x04000000, ++ PISP_IMAGE_FORMAT_HOG_UNSIGNED = 0x08000000, ++ PISP_IMAGE_FORMAT_INTEGRAL_IMAGE = 0x10000000, ++ PISP_IMAGE_FORMAT_WALLPAPER_ROLL = 0x20000000, ++ PISP_IMAGE_FORMAT_THREE_CHANNEL = 0x40000000, ++ ++ /* Lastly a few specific instantiations of the above. */ ++ PISP_IMAGE_FORMAT_SINGLE_16 = PISP_IMAGE_FORMAT_BPS_16, ++ PISP_IMAGE_FORMAT_THREE_16 = ++ PISP_IMAGE_FORMAT_BPS_16 | PISP_IMAGE_FORMAT_THREE_CHANNEL ++}; ++ ++#define PISP_IMAGE_FORMAT_bps_8(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_8) ++#define PISP_IMAGE_FORMAT_bps_10(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_10) ++#define PISP_IMAGE_FORMAT_bps_12(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_12) ++#define PISP_IMAGE_FORMAT_bps_16(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_16) ++#define PISP_IMAGE_FORMAT_bps(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) ? \ ++ 8 + (2 << (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) - 1)) : \ ++ 8) ++#define PISP_IMAGE_FORMAT_shift(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_SHIFT_MASK) / PISP_IMAGE_FORMAT_SHIFT_1) ++#define PISP_IMAGE_FORMAT_three_channel(fmt) \ ++ ((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL) ++#define PISP_IMAGE_FORMAT_single_channel(fmt) \ ++ (!((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL)) ++#define PISP_IMAGE_FORMAT_compressed(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_COMPRESSION_MASK) != \ ++ PISP_IMAGE_FORMAT_UNCOMPRESSED) ++#define PISP_IMAGE_FORMAT_sampling_444(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ ++ PISP_IMAGE_FORMAT_SAMPLING_444) ++#define PISP_IMAGE_FORMAT_sampling_422(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ ++ PISP_IMAGE_FORMAT_SAMPLING_422) ++#define PISP_IMAGE_FORMAT_sampling_420(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ ++ PISP_IMAGE_FORMAT_SAMPLING_420) ++#define PISP_IMAGE_FORMAT_order_normal(fmt) \ ++ (!((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED)) ++#define PISP_IMAGE_FORMAT_order_swapped(fmt) \ ++ ((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED) ++#define PISP_IMAGE_FORMAT_interleaved(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ ++ PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED) ++#define PISP_IMAGE_FORMAT_semiplanar(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ ++ PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR) ++#define PISP_IMAGE_FORMAT_planar(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ ++ PISP_IMAGE_FORMAT_PLANARITY_PLANAR) ++#define PISP_IMAGE_FORMAT_wallpaper(fmt) \ ++ ((fmt) & PISP_IMAGE_FORMAT_WALLPAPER_ROLL) ++#define PISP_IMAGE_FORMAT_HOG(fmt) \ ++ ((fmt) & \ ++ (PISP_IMAGE_FORMAT_HOG_SIGNED | PISP_IMAGE_FORMAT_HOG_UNSIGNED)) ++ ++#define PISP_WALLPAPER_WIDTH 128 // in bytes ++ ++#endif /* _PISP_FE_TYPES_H_ */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0890-dt-bindings-net-cdns-macb-AXI-tuning-properties.patch b/target/linux/bcm27xx/patches-6.1/950-0890-dt-bindings-net-cdns-macb-AXI-tuning-properties.patch new file mode 100644 index 0000000000..7d81e03429 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0890-dt-bindings-net-cdns-macb-AXI-tuning-properties.patch @@ -0,0 +1,38 @@ +From 2be65d1fd1f7d3cf6f59b58b53e285400f04a160 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + .../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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0891-ASoC-dwc-list-all-supported-sample-sizes.patch b/target/linux/bcm27xx/patches-6.1/950-0891-ASoC-dwc-list-all-supported-sample-sizes.patch new file mode 100644 index 0000000000..06d69c7c4c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0891-ASoC-dwc-list-all-supported-sample-sizes.patch @@ -0,0 +1,29 @@ +From 9ef0615a5c5f93cb72af8df3a2dae6d23b106eb5 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0892-ASoC-dwc-Support-set_bclk_ratio.patch b/target/linux/bcm27xx/patches-6.1/950-0892-ASoC-dwc-Support-set_bclk_ratio.patch new file mode 100644 index 0000000000..b18e5f888f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0892-ASoC-dwc-Support-set_bclk_ratio.patch @@ -0,0 +1,59 @@ +From 06f794e8cb227249e03893e4b4923ff58556eb60 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 4 Mar 2021 14:49:23 +0000 +Subject: [PATCH] ASoC: dwc: Support set_bclk_ratio + +Signed-off-by: Phil Elwell +--- + 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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0893-ASoC-dwc-Add-DMACR-handling.patch b/target/linux/bcm27xx/patches-6.1/950-0893-ASoC-dwc-Add-DMACR-handling.patch new file mode 100644 index 0000000000..474903c327 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0893-ASoC-dwc-Add-DMACR-handling.patch @@ -0,0 +1,81 @@ +From b3b1177092d4d2ba6df74042d39aa42c5055f687 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0894-ASOC-dwc-Improve-DMA-shutdown.patch b/target/linux/bcm27xx/patches-6.1/950-0894-ASOC-dwc-Improve-DMA-shutdown.patch new file mode 100644 index 0000000000..73704a8be3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0894-ASOC-dwc-Improve-DMA-shutdown.patch @@ -0,0 +1,128 @@ +From e6baee4502c0228c79408b047096a1259a84353f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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, diff --git a/target/linux/bcm27xx/patches-6.1/950-0895-ASOC-dwc-Fix-16-bit-audio-handling.patch b/target/linux/bcm27xx/patches-6.1/950-0895-ASOC-dwc-Fix-16-bit-audio-handling.patch new file mode 100644 index 0000000000..fa5eb61044 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0895-ASOC-dwc-Fix-16-bit-audio-handling.patch @@ -0,0 +1,88 @@ +From 9c6694c24f26ea435165431d41c72451fadbd753 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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; diff --git a/target/linux/bcm27xx/patches-6.1/950-0896-ASoC-bcm-Remove-dependency-on-BCM2835-I2S.patch b/target/linux/bcm27xx/patches-6.1/950-0896-ASoC-bcm-Remove-dependency-on-BCM2835-I2S.patch new file mode 100644 index 0000000000..9f4f7a0c9a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0896-ASoC-bcm-Remove-dependency-on-BCM2835-I2S.patch @@ -0,0 +1,304 @@ +From f476db1b71e8b82e5299168f963a2fefb7a395e2 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0897-hwmon-Add-RP1-ADC-and-temperature-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0897-hwmon-Add-RP1-ADC-and-temperature-driver.patch new file mode 100644 index 0000000000..c3cf21455b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0897-hwmon-Add-RP1-ADC-and-temperature-driver.patch @@ -0,0 +1,343 @@ +From cad3c92ff0c1a5fa539d08b695b0f6b326924890 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 Mar 2023 18:04:42 +0000 +Subject: [PATCH] hwmon: Add RP1 ADC and temperature driver + +Signed-off-by: Phil Elwell +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0898-mfd-bcm2835-pm-Add-support-for-BCM2712.patch b/target/linux/bcm27xx/patches-6.1/950-0898-mfd-bcm2835-pm-Add-support-for-BCM2712.patch new file mode 100644 index 0000000000..37210173db --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0898-mfd-bcm2835-pm-Add-support-for-BCM2712.patch @@ -0,0 +1,69 @@ +From 0c7aeb96fd3ab68011ba6c24239c501190890308 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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 = { diff --git a/target/linux/bcm27xx/patches-6.1/950-0899-soc-bcm-bcm2835-power-Add-support-for-BCM2712.patch b/target/linux/bcm27xx/patches-6.1/950-0899-soc-bcm-bcm2835-power-Add-support-for-BCM2712.patch new file mode 100644 index 0000000000..e7e3652d91 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0899-soc-bcm-bcm2835-power-Add-support-for-BCM2712.patch @@ -0,0 +1,76 @@ +From 9cf85a95eeb239a079a3485bd1d0447431bdc7f1 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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, diff --git a/target/linux/bcm27xx/patches-6.1/950-0900-drivers-spi-Fix-spi-gpio-to-correctly-implement-sck-.patch b/target/linux/bcm27xx/patches-6.1/950-0900-drivers-spi-Fix-spi-gpio-to-correctly-implement-sck-.patch new file mode 100644 index 0000000000..ff8471411f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0900-drivers-spi-Fix-spi-gpio-to-correctly-implement-sck-.patch @@ -0,0 +1,150 @@ +From 380c336af070edf85826abbb0057bf92a03ec466 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +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 +--- + 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) diff --git a/target/linux/bcm27xx/patches-6.1/950-0901-spi-spi-gpio-Implement-spidelay-when-requested-bit-r.patch b/target/linux/bcm27xx/patches-6.1/950-0901-spi-spi-gpio-Implement-spidelay-when-requested-bit-r.patch new file mode 100644 index 0000000000..1b7952ab18 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0901-spi-spi-gpio-Implement-spidelay-when-requested-bit-r.patch @@ -0,0 +1,55 @@ +From 586f87307e75552292cfc6c76b81cd38d5ec31e2 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +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 +--- + 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 + #include + #include ++#include + + #include + #include + #include + +- + /* + * 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" + diff --git a/target/linux/bcm27xx/patches-6.1/950-0902-drm-v3d-fix-up-register-addresses-for-V3D-7.x.patch b/target/linux/bcm27xx/patches-6.1/950-0902-drm-v3d-fix-up-register-addresses-for-V3D-7.x.patch new file mode 100644 index 0000000000..1a51a85660 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0902-drm-v3d-fix-up-register-addresses-for-V3D-7.x.patch @@ -0,0 +1,672 @@ +From 3f949caeef21269afc67dd62ae9826204f215934 Mon Sep 17 00:00:00 2001 +From: Iago Toral Quiroga +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. diff --git a/target/linux/bcm27xx/patches-6.1/950-0903-drm-v3d-update-UAPI-to-match-user-space-for-V3D-7.x.patch b/target/linux/bcm27xx/patches-6.1/950-0903-drm-v3d-update-UAPI-to-match-user-space-for-V3D-7.x.patch new file mode 100644 index 0000000000..ed1d5f05df --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0903-drm-v3d-update-UAPI-to-match-user-space-for-V3D-7.x.patch @@ -0,0 +1,24 @@ +From 22fb30936524ae96151789741885edbc45efb53d Mon Sep 17 00:00:00 2001 +From: Iago Toral Quiroga +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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0904-drm-v3d-add-brcm-2712-v3d-as-a-compatible-V3D-device.patch b/target/linux/bcm27xx/patches-6.1/950-0904-drm-v3d-add-brcm-2712-v3d-as-a-compatible-V3D-device.patch new file mode 100644 index 0000000000..64189338e6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0904-drm-v3d-add-brcm-2712-v3d-as-a-compatible-V3D-device.patch @@ -0,0 +1,19 @@ +From 18bc419d38eda06ded78c7b702c0e21e5af8f24c Mon Sep 17 00:00:00 2001 +From: Iago Toral Quiroga +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" }, diff --git a/target/linux/bcm27xx/patches-6.1/950-0905-drm-v3d-Improve-MMU-support-for-larger-pages.patch b/target/linux/bcm27xx/patches-6.1/950-0905-drm-v3d-Improve-MMU-support-for-larger-pages.patch new file mode 100644 index 0000000000..3c53996ff0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0905-drm-v3d-Improve-MMU-support-for-larger-pages.patch @@ -0,0 +1,64 @@ +From 12c7ea43b930976f35ce75d11fd3f55438868e13 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +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 +--- + 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"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0906-dt-bindings-gpu-v3d-Add-BCM2712-to-compatibility-lis.patch b/target/linux/bcm27xx/patches-6.1/950-0906-dt-bindings-gpu-v3d-Add-BCM2712-to-compatibility-lis.patch new file mode 100644 index 0000000000..43c5c395c9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0906-dt-bindings-gpu-v3d-Add-BCM2712-to-compatibility-lis.patch @@ -0,0 +1,19 @@ +From 5970fa51663511d7f773db7109ff6fa2504f186a Mon Sep 17 00:00:00 2001 +From: Iago Toral Quiroga +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 diff --git a/target/linux/bcm27xx/patches-6.1/950-0907-drivers-char-add-generic-gpiomem-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0907-drivers-char-add-generic-gpiomem-driver.patch new file mode 100644 index 0000000000..14e6b0a9e4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0907-drivers-char-add-generic-gpiomem-driver.patch @@ -0,0 +1,328 @@ +From fdf9cab5eaa849e90b12e17718bc47130a91433c Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +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 +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); diff --git a/target/linux/bcm27xx/patches-6.1/950-0909-drivers-char-delete-bcm2835-gpiomem.patch b/target/linux/bcm27xx/patches-6.1/950-0909-drivers-char-delete-bcm2835-gpiomem.patch new file mode 100644 index 0000000000..5d6eb16fb2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0909-drivers-char-delete-bcm2835-gpiomem.patch @@ -0,0 +1,301 @@ +From 27bda80061b46e18fe83be11228df5365363b377 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 26 Apr 2023 13:44:15 +0100 +Subject: [PATCH] drivers: char: delete bcm2835-gpiomem + +This functionality is now provided by raspberrypi-gpiomem. + +Signed-off-by: Jonathan Bell +--- + drivers/char/broadcom/Kconfig | 8 - + drivers/char/broadcom/Makefile | 1 - + drivers/char/broadcom/bcm2835-gpiomem.c | 258 ------------------------ + 3 files changed, 267 deletions(-) + delete mode 100644 drivers/char/broadcom/bcm2835-gpiomem.c + +--- a/drivers/char/broadcom/Kconfig ++++ b/drivers/char/broadcom/Kconfig +@@ -23,14 +23,6 @@ config BCM_VCIO + + endif + +-config BCM2835_DEVGPIOMEM +- tristate "/dev/gpiomem rootless GPIO access via mmap() on the BCM2835" +- default m +- help +- Provides users with root-free access to the GPIO registers +- on the 2835. Calling mmap(/dev/gpiomem) will map the GPIO +- register page to the user's pointer. +- + config BCM2835_SMI_DEV + tristate "Character device driver for BCM2835 Secondary Memory Interface" + depends on BCM2835_SMI +--- a/drivers/char/broadcom/Makefile ++++ b/drivers/char/broadcom/Makefile +@@ -1,5 +1,4 @@ + obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o + obj-$(CONFIG_BCM_VCIO) += vcio.o +-obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o + obj-$(CONFIG_BCM2835_SMI_DEV) += bcm2835_smi_dev.o + obj-$(CONFIG_RPIVID_MEM) += rpivid-mem.o +--- a/drivers/char/broadcom/bcm2835-gpiomem.c ++++ /dev/null +@@ -1,258 +0,0 @@ +-/** +- * GPIO memory device driver +- * +- * Creates a chardev /dev/gpiomem which will provide user access to +- * the BCM2835's GPIO registers when it is mmap()'d. +- * No longer need root for user GPIO access, but without relaxing permissions +- * on /dev/mem. +- * +- * Written by Luke Wren +- * Copyright (c) 2015, Raspberry Pi (Trading) Ltd. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions, and the following disclaimer, +- * without modification. +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * 3. The names of the above-listed copyright holders may not be used +- * to endorse or promote products derived from this software without +- * specific prior written permission. +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") version 2, as published by the Free +- * Software Foundation. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define DEVICE_NAME "bcm2835-gpiomem" +-#define DRIVER_NAME "gpiomem-bcm2835" +-#define DEVICE_MINOR 0 +- +-struct bcm2835_gpiomem_instance { +- unsigned long gpio_regs_phys; +- struct device *dev; +-}; +- +-static struct cdev bcm2835_gpiomem_cdev; +-static dev_t bcm2835_gpiomem_devid; +-static struct class *bcm2835_gpiomem_class; +-static struct device *bcm2835_gpiomem_dev; +-static struct bcm2835_gpiomem_instance *inst; +- +- +-/**************************************************************************** +-* +-* GPIO mem chardev file ops +-* +-***************************************************************************/ +- +-static int bcm2835_gpiomem_open(struct inode *inode, struct file *file) +-{ +- int dev = iminor(inode); +- int ret = 0; +- +- if (dev != DEVICE_MINOR) { +- dev_err(inst->dev, "Unknown minor device: %d", dev); +- ret = -ENXIO; +- } +- return ret; +-} +- +-static int bcm2835_gpiomem_release(struct inode *inode, struct file *file) +-{ +- int dev = iminor(inode); +- int ret = 0; +- +- if (dev != DEVICE_MINOR) { +- dev_err(inst->dev, "Unknown minor device %d", dev); +- ret = -ENXIO; +- } +- return ret; +-} +- +-static const struct vm_operations_struct bcm2835_gpiomem_vm_ops = { +-#ifdef CONFIG_HAVE_IOREMAP_PROT +- .access = generic_access_phys +-#endif +-}; +- +-static int bcm2835_gpiomem_mmap(struct file *file, struct vm_area_struct *vma) +-{ +- /* Ignore what the user says - they're getting the GPIO regs +- whether they like it or not! */ +- unsigned long gpio_page = inst->gpio_regs_phys >> PAGE_SHIFT; +- +- vma->vm_page_prot = phys_mem_access_prot(file, gpio_page, +- PAGE_SIZE, +- vma->vm_page_prot); +- vma->vm_ops = &bcm2835_gpiomem_vm_ops; +- if (remap_pfn_range(vma, vma->vm_start, +- gpio_page, +- PAGE_SIZE, +- vma->vm_page_prot)) { +- return -EAGAIN; +- } +- return 0; +-} +- +-static const struct file_operations +-bcm2835_gpiomem_fops = { +- .owner = THIS_MODULE, +- .open = bcm2835_gpiomem_open, +- .release = bcm2835_gpiomem_release, +- .mmap = bcm2835_gpiomem_mmap, +-}; +- +- +- /**************************************************************************** +-* +-* Probe and remove functions +-* +-***************************************************************************/ +- +- +-static int bcm2835_gpiomem_probe(struct platform_device *pdev) +-{ +- int err; +- void *ptr_err; +- struct device *dev = &pdev->dev; +- struct resource *ioresource; +- +- /* Allocate buffers and instance data */ +- +- inst = kzalloc(sizeof(struct bcm2835_gpiomem_instance), GFP_KERNEL); +- +- if (!inst) { +- err = -ENOMEM; +- goto failed_inst_alloc; +- } +- +- inst->dev = dev; +- +- ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (ioresource) { +- inst->gpio_regs_phys = ioresource->start; +- } else { +- dev_err(inst->dev, "failed to get IO resource"); +- err = -ENOENT; +- goto failed_get_resource; +- } +- +- /* Create character device entries */ +- +- err = alloc_chrdev_region(&bcm2835_gpiomem_devid, +- DEVICE_MINOR, 1, DEVICE_NAME); +- if (err != 0) { +- dev_err(inst->dev, "unable to allocate device number"); +- goto failed_alloc_chrdev; +- } +- cdev_init(&bcm2835_gpiomem_cdev, &bcm2835_gpiomem_fops); +- bcm2835_gpiomem_cdev.owner = THIS_MODULE; +- err = cdev_add(&bcm2835_gpiomem_cdev, bcm2835_gpiomem_devid, 1); +- if (err != 0) { +- dev_err(inst->dev, "unable to register device"); +- goto failed_cdev_add; +- } +- +- /* Create sysfs entries */ +- +- bcm2835_gpiomem_class = class_create(THIS_MODULE, DEVICE_NAME); +- ptr_err = bcm2835_gpiomem_class; +- if (IS_ERR(ptr_err)) +- goto failed_class_create; +- +- bcm2835_gpiomem_dev = device_create(bcm2835_gpiomem_class, NULL, +- bcm2835_gpiomem_devid, NULL, +- "gpiomem"); +- ptr_err = bcm2835_gpiomem_dev; +- if (IS_ERR(ptr_err)) +- goto failed_device_create; +- +- dev_info(inst->dev, "Initialised: Registers at 0x%08lx", +- inst->gpio_regs_phys); +- +- return 0; +- +-failed_device_create: +- class_destroy(bcm2835_gpiomem_class); +-failed_class_create: +- cdev_del(&bcm2835_gpiomem_cdev); +- err = PTR_ERR(ptr_err); +-failed_cdev_add: +- unregister_chrdev_region(bcm2835_gpiomem_devid, 1); +-failed_alloc_chrdev: +-failed_get_resource: +- kfree(inst); +-failed_inst_alloc: +- dev_err(inst->dev, "could not load bcm2835_gpiomem"); +- return err; +-} +- +-static int bcm2835_gpiomem_remove(struct platform_device *pdev) +-{ +- struct device *dev = inst->dev; +- +- kfree(inst); +- device_destroy(bcm2835_gpiomem_class, bcm2835_gpiomem_devid); +- class_destroy(bcm2835_gpiomem_class); +- cdev_del(&bcm2835_gpiomem_cdev); +- unregister_chrdev_region(bcm2835_gpiomem_devid, 1); +- +- dev_info(dev, "GPIO mem driver removed - OK"); +- return 0; +-} +- +- /**************************************************************************** +-* +-* Register the driver with device tree +-* +-***************************************************************************/ +- +-static const struct of_device_id bcm2835_gpiomem_of_match[] = { +- {.compatible = "brcm,bcm2835-gpiomem",}, +- { /* sentinel */ }, +-}; +- +-MODULE_DEVICE_TABLE(of, bcm2835_gpiomem_of_match); +- +-static struct platform_driver bcm2835_gpiomem_driver = { +- .probe = bcm2835_gpiomem_probe, +- .remove = bcm2835_gpiomem_remove, +- .driver = { +- .name = DRIVER_NAME, +- .owner = THIS_MODULE, +- .of_match_table = bcm2835_gpiomem_of_match, +- }, +-}; +- +-module_platform_driver(bcm2835_gpiomem_driver); +- +-MODULE_ALIAS("platform:gpiomem-bcm2835"); +-MODULE_LICENSE("GPL"); +-MODULE_DESCRIPTION("gpiomem driver for accessing GPIO from userspace"); +-MODULE_AUTHOR("Luke Wren "); diff --git a/target/linux/bcm27xx/patches-6.1/950-0910-drivers-hwmon-rp1-adc-check-conversion-validity-befo.patch b/target/linux/bcm27xx/patches-6.1/950-0910-drivers-hwmon-rp1-adc-check-conversion-validity-befo.patch new file mode 100644 index 0000000000..557b7ac406 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0910-drivers-hwmon-rp1-adc-check-conversion-validity-befo.patch @@ -0,0 +1,34 @@ +From 3cafcfbab9b5f3f1357b415b6ca09911eeb405d6 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Thu, 4 May 2023 15:48:53 +0100 +Subject: [PATCH] drivers: hwmon: rp1-adc: check conversion validity before + supplying value + +The SAR ADC architecture may complete a conversion but instability in the +comparator can corrupt the result. Such corruption is signalled in the CS +ERR bit, asserted alongside each conversion result. + +Signed-off-by: Jonathan Bell +--- + drivers/hwmon/rp1-adc.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/hwmon/rp1-adc.c ++++ b/drivers/hwmon/rp1-adc.c +@@ -97,8 +97,14 @@ static int rp1_adc_read(struct rp1_adc_d + data->base + RP1_ADC_RWTYPE_SET + RP1_ADC_CS); + + ret = rp1_adc_ready_wait(data); +- if (!ret) +- *val = readl(data->base + RP1_ADC_RESULT); ++ if (ret) ++ return ret; ++ ++ /* Asserted if the completed conversion had a convergence error */ ++ if (readl(data->base + RP1_ADC_CS) & RP1_ADC_CS_ERR) ++ return -EIO; ++ ++ *val = readl(data->base + RP1_ADC_RESULT); + + spin_unlock(&data->lock); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0911-dmaengine-bcm2835-Add-BCM2712-support.patch b/target/linux/bcm27xx/patches-6.1/950-0911-dmaengine-bcm2835-Add-BCM2712-support.patch new file mode 100644 index 0000000000..58095cf8fd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0911-dmaengine-bcm2835-Add-BCM2712-support.patch @@ -0,0 +1,36 @@ +From 87c5545f9a66984894384da5f8c2eeb60983732a Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 8 Mar 2023 16:53:38 +0000 +Subject: [PATCH] dmaengine: bcm2835: Add BCM2712 support + +BCM2712 has 6 40-bit channels - DMA6 to DMA11. Add a new compatible +string to indicate that the current platform is BCM2712. + +Signed-off-by: Phil Elwell +--- + drivers/dma/bcm2835-dma.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/dma/bcm2835-dma.c ++++ b/drivers/dma/bcm2835-dma.c +@@ -331,6 +331,12 @@ static const struct bcm2835_dma_cfg_data + .dma_mask = DMA_BIT_MASK(36), + }; + ++static const struct bcm2835_dma_cfg_data bcm2712_dma_cfg = { ++ .chan_40bit_mask = BIT(6) | BIT(7) | BIT(8) | BIT(9) | ++ BIT(10) | BIT(11), ++ .dma_mask = DMA_BIT_MASK(40), ++}; ++ + static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c) + { + /* lite and normal channels have different max frame length */ +@@ -1260,6 +1266,7 @@ EXPORT_SYMBOL(bcm2711_dma40_memcpy); + static const struct of_device_id bcm2835_dma_of_match[] = { + { .compatible = "brcm,bcm2835-dma", .data = &bcm2835_dma_cfg }, + { .compatible = "brcm,bcm2711-dma", .data = &bcm2711_dma_cfg }, ++ { .compatible = "brcm,bcm2712-dma", .data = &bcm2712_dma_cfg }, + {}, + }; + MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match); diff --git a/target/linux/bcm27xx/patches-6.1/950-0912-dmaengine-bcm2835-HACK-Support-DMA-Lite-channels.patch b/target/linux/bcm27xx/patches-6.1/950-0912-dmaengine-bcm2835-HACK-Support-DMA-Lite-channels.patch new file mode 100644 index 0000000000..6f651a65f6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0912-dmaengine-bcm2835-HACK-Support-DMA-Lite-channels.patch @@ -0,0 +1,57 @@ +From a671a2774cb3bcfb144622149757f6821aa0604c Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 13 Apr 2023 16:52:19 +0200 +Subject: [PATCH] dmaengine: bcm2835: HACK: Support DMA-Lite channels + +The BCM2712 has a DMA-Lite controller that is basically a BCM2835-style +DMA controller that supports 40 bits DMA addresses. + +We need it for HDMI audio to work, but this breaks BCM2835-38 so we +should rework this later. + +Signed-off-by: Maxime Ripard +--- + drivers/dma/bcm2835-dma.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/dma/bcm2835-dma.c ++++ b/drivers/dma/bcm2835-dma.c +@@ -550,7 +550,7 @@ static struct bcm2835_desc *bcm2835_dma_ + control_block->info = info; + control_block->src = src; + control_block->dst = dst; +- control_block->stride = 0; ++ control_block->stride = (upper_32_bits(dst) << 8) | upper_32_bits(src); + control_block->next = 0; + } + +@@ -575,7 +575,7 @@ static struct bcm2835_desc *bcm2835_dma_ + d->cb_list[frame - 1].cb)->next_cb = + to_bcm2711_cbaddr(cb_entry->paddr); + if (frame && !c->is_40bit_channel) +- d->cb_list[frame - 1].cb->next = cb_entry->paddr; ++ d->cb_list[frame - 1].cb->next = to_bcm2711_cbaddr(cb_entry->paddr); + + /* update src and dst and length */ + if (src && (info & BCM2835_DMA_S_INC)) { +@@ -760,7 +760,10 @@ static void bcm2835_dma_start_desc(struc + writel(BCM2711_DMA40_ACTIVE | BCM2711_DMA40_PROT | BCM2711_DMA40_CS_FLAGS(c->dreq), + c->chan_base + BCM2711_DMA40_CS); + } else { +- writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR); ++ writel(BIT(31), c->chan_base + BCM2835_DMA_CS); ++ ++ writel(to_bcm2711_cbaddr(d->cb_list[0].paddr), ++ c->chan_base + BCM2835_DMA_ADDR); + writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq), + c->chan_base + BCM2835_DMA_CS); + } +@@ -1129,7 +1132,7 @@ static struct dma_async_tx_descriptor *b + d->cb_list[frames - 1].cb)->next_cb = + to_bcm2711_cbaddr(d->cb_list[0].paddr); + else +- d->cb_list[d->frames - 1].cb->next = d->cb_list[0].paddr; ++ d->cb_list[d->frames - 1].cb->next = to_bcm2711_cbaddr(d->cb_list[0].paddr); + + return vchan_tx_prep(&c->vc, &d->vd, flags); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0913-clk-bcm-rpi-Add-disp-clock.patch b/target/linux/bcm27xx/patches-6.1/950-0913-clk-bcm-rpi-Add-disp-clock.patch new file mode 100644 index 0000000000..6f5e55d956 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0913-clk-bcm-rpi-Add-disp-clock.patch @@ -0,0 +1,46 @@ +From c8fd69c6f567bd43ba084b95a987532940465ef5 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 24 Feb 2023 14:12:50 +0100 +Subject: [PATCH] clk: bcm: rpi: Add disp clock + +BCM2712 has an extra clock exposed by the firmware called DISP, and used +by (at least) the HVS. Let's add it to the list of clocks to register in +Linux. + +Signed-off-by: Maxime Ripard +--- + drivers/clk/bcm/clk-raspberrypi.c | 5 +++++ + include/soc/bcm2835/raspberrypi-firmware.h | 1 + + 2 files changed, 6 insertions(+) + +--- a/drivers/clk/bcm/clk-raspberrypi.c ++++ b/drivers/clk/bcm/clk-raspberrypi.c +@@ -34,6 +34,7 @@ static char *rpi_firmware_clk_names[] = + [RPI_FIRMWARE_M2MC_CLK_ID] = "m2mc", + [RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = "pixel-bvb", + [RPI_FIRMWARE_VEC_CLK_ID] = "vec", ++ [RPI_FIRMWARE_DISP_CLK_ID] = "disp", + }; + + #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0) +@@ -139,6 +140,10 @@ raspberrypi_clk_variants[RPI_FIRMWARE_NU + .export = true, + .minimize = true, + }, ++ [RPI_FIRMWARE_DISP_CLK_ID] = { ++ .export = true, ++ .minimize = true, ++ }, + }; + + /* +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -176,6 +176,7 @@ enum rpi_firmware_clk_id { + RPI_FIRMWARE_M2MC_CLK_ID, + RPI_FIRMWARE_PIXEL_BVB_CLK_ID, + RPI_FIRMWARE_VEC_CLK_ID, ++ RPI_FIRMWARE_DISP_CLK_ID, + RPI_FIRMWARE_NUM_CLK_ID, + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0914-net-phy-broadcom-optionally-enable-link-down-powersa.patch b/target/linux/bcm27xx/patches-6.1/950-0914-net-phy-broadcom-optionally-enable-link-down-powersa.patch new file mode 100644 index 0000000000..2df48297b5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0914-net-phy-broadcom-optionally-enable-link-down-powersa.patch @@ -0,0 +1,26 @@ +From 6370a6cd16a5aa9726bf209c0f0a3179f4011cb1 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 22 May 2023 15:31:17 +0100 +Subject: [PATCH] net: phy: broadcom: optionally enable link-down powersave + based on DT + +It's really a function of the board whether or not to use this feature +as it may require MAC compatibility as well as interop testing. + +Signed-off-by: Jonathan Bell +--- + drivers/net/phy/broadcom.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/phy/broadcom.c ++++ b/drivers/net/phy/broadcom.c +@@ -370,6 +370,9 @@ static int bcm54xx_config_init(struct ph + (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) + bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0); + ++ if (of_property_read_bool(np, "brcm,powerdown-enable")) ++ phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE; ++ + bcm54xx_adjust_rxrefclk(phydev); + + switch (BRCM_PHY_MODEL(phydev)) { diff --git a/target/linux/bcm27xx/patches-6.1/950-0915-dmaengine-bcm2835-Rename-to_bcm2711_cbaddr-to-to_40b.patch b/target/linux/bcm27xx/patches-6.1/950-0915-dmaengine-bcm2835-Rename-to_bcm2711_cbaddr-to-to_40b.patch new file mode 100644 index 0000000000..ce59f6072b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0915-dmaengine-bcm2835-Rename-to_bcm2711_cbaddr-to-to_40b.patch @@ -0,0 +1,75 @@ +From cfad3f71fc450639fc259d576d0903e9132fe34a Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Thu, 25 May 2023 14:48:28 +0100 +Subject: [PATCH] dmaengine: bcm2835: Rename to_bcm2711_cbaddr to + to_40bit_cbaddr + +As the shifted address also applies to bcm2712, +give the function a more specific name. + +Signed-off-by: Dom Cobley +--- + drivers/dma/bcm2835-dma.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/dma/bcm2835-dma.c ++++ b/drivers/dma/bcm2835-dma.c +@@ -390,7 +390,7 @@ static inline uint32_t to_bcm2711_dsti(u + BCM2711_DMA40_BURST_LEN(BCM2835_DMA_GET_BURST_LENGTH(info)); + } + +-static inline uint32_t to_bcm2711_cbaddr(dma_addr_t addr) ++static inline uint32_t to_40bit_cbaddr(dma_addr_t addr) + { + BUG_ON(addr & 0x1f); + return (addr >> 5); +@@ -573,9 +573,9 @@ static struct bcm2835_desc *bcm2835_dma_ + if (frame && c->is_40bit_channel) + ((struct bcm2711_dma40_scb *) + d->cb_list[frame - 1].cb)->next_cb = +- to_bcm2711_cbaddr(cb_entry->paddr); ++ to_40bit_cbaddr(cb_entry->paddr); + if (frame && !c->is_40bit_channel) +- d->cb_list[frame - 1].cb->next = to_bcm2711_cbaddr(cb_entry->paddr); ++ d->cb_list[frame - 1].cb->next = to_40bit_cbaddr(cb_entry->paddr); + + /* update src and dst and length */ + if (src && (info & BCM2835_DMA_S_INC)) { +@@ -755,14 +755,14 @@ static void bcm2835_dma_start_desc(struc + c->desc = d = to_bcm2835_dma_desc(&vd->tx); + + if (c->is_40bit_channel) { +- writel(to_bcm2711_cbaddr(d->cb_list[0].paddr), ++ writel(to_40bit_cbaddr(d->cb_list[0].paddr), + c->chan_base + BCM2711_DMA40_CB); + writel(BCM2711_DMA40_ACTIVE | BCM2711_DMA40_PROT | BCM2711_DMA40_CS_FLAGS(c->dreq), + c->chan_base + BCM2711_DMA40_CS); + } else { + writel(BIT(31), c->chan_base + BCM2835_DMA_CS); + +- writel(to_bcm2711_cbaddr(d->cb_list[0].paddr), ++ writel(to_40bit_cbaddr(d->cb_list[0].paddr), + c->chan_base + BCM2835_DMA_ADDR); + writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq), + c->chan_base + BCM2835_DMA_CS); +@@ -1130,9 +1130,9 @@ static struct dma_async_tx_descriptor *b + if (c->is_40bit_channel) + ((struct bcm2711_dma40_scb *) + d->cb_list[frames - 1].cb)->next_cb = +- to_bcm2711_cbaddr(d->cb_list[0].paddr); ++ to_40bit_cbaddr(d->cb_list[0].paddr); + else +- d->cb_list[d->frames - 1].cb->next = to_bcm2711_cbaddr(d->cb_list[0].paddr); ++ d->cb_list[d->frames - 1].cb->next = to_40bit_cbaddr(d->cb_list[0].paddr); + + return vchan_tx_prep(&c->vc, &d->vd, flags); + } +@@ -1252,7 +1252,7 @@ void bcm2711_dma40_memcpy(dma_addr_t dst + scb->len = size; + scb->next_cb = 0; + +- writel(to_bcm2711_cbaddr(memcpy_scb_dma), memcpy_chan + BCM2711_DMA40_CB); ++ writel(to_40bit_cbaddr(memcpy_scb_dma), memcpy_chan + BCM2711_DMA40_CB); + writel(BCM2711_DMA40_MEMCPY_FLAGS | BCM2711_DMA40_ACTIVE | BCM2711_DMA40_PROT, + memcpy_chan + BCM2711_DMA40_CS); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0916-dmaengine-bcm2835-Fix-dma-driver-for-BCM2835-38.patch b/target/linux/bcm27xx/patches-6.1/950-0916-dmaengine-bcm2835-Fix-dma-driver-for-BCM2835-38.patch new file mode 100644 index 0000000000..a2ff2a6bb0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0916-dmaengine-bcm2835-Fix-dma-driver-for-BCM2835-38.patch @@ -0,0 +1,77 @@ +From 75f44d1416c5de17865247d6d012c37f7650437c Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Wed, 24 May 2023 19:32:16 +0100 +Subject: [PATCH] dmaengine: bcm2835: Fix dma driver for BCM2835-38 + +The previous commit broke support on older devices. +Make the breaking parts of patch conditional on +the device being used. + +Fixes: 6e1856ac7c39 ("dmaengine: bcm2835: HACK: Support DMA-Lite channels") + +Signed-off-by: Dom Cobley +--- + drivers/dma/bcm2835-dma.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +--- a/drivers/dma/bcm2835-dma.c ++++ b/drivers/dma/bcm2835-dma.c +@@ -102,6 +102,7 @@ struct bcm2835_chan { + + bool is_lite_channel; + bool is_40bit_channel; ++ bool is_2712; + }; + + struct bcm2835_desc { +@@ -550,7 +551,11 @@ static struct bcm2835_desc *bcm2835_dma_ + control_block->info = info; + control_block->src = src; + control_block->dst = dst; +- control_block->stride = (upper_32_bits(dst) << 8) | upper_32_bits(src); ++ if (c->is_2712) ++ control_block->stride = (upper_32_bits(dst) << 8) | ++ upper_32_bits(src); ++ else ++ control_block->stride = 0; + control_block->next = 0; + } + +@@ -575,7 +580,8 @@ static struct bcm2835_desc *bcm2835_dma_ + d->cb_list[frame - 1].cb)->next_cb = + to_40bit_cbaddr(cb_entry->paddr); + if (frame && !c->is_40bit_channel) +- d->cb_list[frame - 1].cb->next = to_40bit_cbaddr(cb_entry->paddr); ++ d->cb_list[frame - 1].cb->next = c->is_2712 ? ++ to_40bit_cbaddr(cb_entry->paddr) : cb_entry->paddr; + + /* update src and dst and length */ + if (src && (info & BCM2835_DMA_S_INC)) { +@@ -762,7 +768,7 @@ static void bcm2835_dma_start_desc(struc + } else { + writel(BIT(31), c->chan_base + BCM2835_DMA_CS); + +- writel(to_40bit_cbaddr(d->cb_list[0].paddr), ++ writel(c->is_2712 ? to_40bit_cbaddr(d->cb_list[0].paddr) : d->cb_list[0].paddr, + c->chan_base + BCM2835_DMA_ADDR); + writel(BCM2835_DMA_ACTIVE | BCM2835_DMA_CS_FLAGS(c->dreq), + c->chan_base + BCM2835_DMA_CS); +@@ -1132,7 +1138,8 @@ static struct dma_async_tx_descriptor *b + d->cb_list[frames - 1].cb)->next_cb = + to_40bit_cbaddr(d->cb_list[0].paddr); + else +- d->cb_list[d->frames - 1].cb->next = to_40bit_cbaddr(d->cb_list[0].paddr); ++ d->cb_list[d->frames - 1].cb->next = c->is_2712 ? ++ to_40bit_cbaddr(d->cb_list[0].paddr) : d->cb_list[0].paddr; + + return vchan_tx_prep(&c->vc, &d->vd, flags); + } +@@ -1199,6 +1206,8 @@ static int bcm2835_dma_chan_init(struct + else if (readl(c->chan_base + BCM2835_DMA_DEBUG) & + BCM2835_DMA_DEBUG_LITE) + c->is_lite_channel = true; ++ if (d->cfg_data->dma_mask == DMA_BIT_MASK(40)) ++ c->is_2712 = true; + + return 0; + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0917-drivers-iommu-Add-BCM2712-IOMMU.patch b/target/linux/bcm27xx/patches-6.1/950-0917-drivers-iommu-Add-BCM2712-IOMMU.patch new file mode 100644 index 0000000000..92f43fa71b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0917-drivers-iommu-Add-BCM2712-IOMMU.patch @@ -0,0 +1,855 @@ +From 5fd6ee7fd084838e09d4e463ae53cd9aaa7fce70 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Thu, 11 May 2023 16:37:34 +0100 +Subject: [PATCH] drivers: iommu: Add BCM2712 IOMMU + +Add a driver for BCM2712 IOMMUs. +There is a small driver for the Shared IOMMU TLB Cache. +Each IOMMU instance is a separate device. + +IOMMUs are set up with a "pass-through" range covering +the lowest 40BGytes (which should cover all of SDRAM) +for the benefit of non-IOMMU-aware devices that share +a physical IOMMU; and translation for addresses in the +range 40GB to 42GB. + +An optional parameter adds a DMA offset (which otherwise +would be lost?) to virtual addresses for DMA masters on a +bus such as PCIe. + +Signed-off-by: Nick Hollinghurst +--- + drivers/iommu/Kconfig | 7 + + drivers/iommu/Makefile | 1 + + drivers/iommu/bcm2712-iommu-cache.c | 77 ++++ + drivers/iommu/bcm2712-iommu.c | 672 ++++++++++++++++++++++++++++ + drivers/iommu/bcm2712-iommu.h | 45 ++ + 5 files changed, 802 insertions(+) + create mode 100644 drivers/iommu/bcm2712-iommu-cache.c + create mode 100644 drivers/iommu/bcm2712-iommu.c + create mode 100644 drivers/iommu/bcm2712-iommu.h + +--- a/drivers/iommu/Kconfig ++++ b/drivers/iommu/Kconfig +@@ -506,4 +506,11 @@ config SPRD_IOMMU + + Say Y here if you want to use the multimedia devices listed above. + ++config BCM2712_IOMMU ++ tristate "BCM2712 IOMMU driver" ++ depends on ARM64 && ARCH_BCM ++ select IOMMU_API ++ help ++ IOMMU driver for BCM2712 ++ + endif # IOMMU_SUPPORT +--- a/drivers/iommu/Makefile ++++ b/drivers/iommu/Makefile +@@ -31,3 +31,4 @@ obj-$(CONFIG_VIRTIO_IOMMU) += virtio-iom + obj-$(CONFIG_IOMMU_SVA) += iommu-sva-lib.o io-pgfault.o + obj-$(CONFIG_SPRD_IOMMU) += sprd-iommu.o + obj-$(CONFIG_APPLE_DART) += apple-dart.o ++obj-$(CONFIG_BCM2712_IOMMU) += bcm2712-iommu.o bcm2712-iommu-cache.o +--- /dev/null ++++ b/drivers/iommu/bcm2712-iommu-cache.c +@@ -0,0 +1,77 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * IOMMU driver for BCM2712 ++ * ++ * Copyright (c) 2023 Raspberry Pi Ltd. ++ */ ++ ++#include "bcm2712-iommu.h" ++ ++#include ++#include ++#include ++#include ++ ++#define MMUC_CONTROL_ENABLE 1 ++#define MMUC_CONTROL_FLUSH 2 ++#define MMUC_CONTROL_FLUSHING 4 ++ ++void bcm2712_iommu_cache_flush(struct bcm2712_iommu_cache *cache) ++{ ++ unsigned long flags; ++ int i; ++ ++ spin_lock_irqsave(&cache->hw_lock, flags); ++ if (cache->reg_base) { ++ /* Enable and flush the TLB cache */ ++ writel(MMUC_CONTROL_ENABLE | MMUC_CONTROL_FLUSH, ++ cache->reg_base); ++ ++ /* Wait for flush to complete: it should be very quick */ ++ for (i = 0; i < 1024; i++) { ++ if (!(MMUC_CONTROL_FLUSHING & readl(cache->reg_base))) ++ break; ++ cpu_relax(); ++ } ++ } ++ spin_unlock_irqrestore(&cache->hw_lock, flags); ++} ++ ++static int bcm2712_iommu_cache_probe(struct platform_device *pdev) ++{ ++ struct bcm2712_iommu_cache *cache; ++ ++ dev_info(&pdev->dev, __func__); ++ cache = devm_kzalloc(&pdev->dev, sizeof(*cache), GFP_KERNEL); ++ if (!cache) ++ return -ENOMEM; ++ ++ cache->dev = &pdev->dev; ++ platform_set_drvdata(pdev, cache); ++ spin_lock_init(&cache->hw_lock); ++ ++ /* Get IOMMUC registers; we only use the first register (IOMMUC_CTRL) */ ++ cache->reg_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(cache->reg_base)) { ++ dev_err(&pdev->dev, "Failed to get IOMMU Cache registers address\n"); ++ cache->reg_base = NULL; ++ } ++ return 0; ++} ++ ++static const struct of_device_id bcm2712_iommu_cache_of_match[] = { ++ { ++ . compatible = "brcm,bcm2712-iommuc" ++ }, ++ { /* sentinel */ }, ++}; ++ ++static struct platform_driver bcm2712_iommu_cache_driver = { ++ .probe = bcm2712_iommu_cache_probe, ++ .driver = { ++ .name = "bcm2712-iommu-cache", ++ .of_match_table = bcm2712_iommu_cache_of_match ++ }, ++}; ++ ++builtin_platform_driver(bcm2712_iommu_cache_driver); +--- /dev/null ++++ b/drivers/iommu/bcm2712-iommu.c +@@ -0,0 +1,672 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * IOMMU driver for BCM2712 ++ * ++ * Copyright (c) 2023 Raspberry Pi Ltd. ++ */ ++ ++#include "bcm2712-iommu.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MMU_WR(off, val) writel(val, mmu->reg_base + (off)) ++#define MMU_RD(off) readl(mmu->reg_base + (off)) ++ ++#define domain_to_mmu(d) (container_of(d, struct bcm2712_iommu_domain, base)->mmu) ++ ++#define MMMU_CTRL_OFFSET 0x00 ++#define MMMU_CTRL_CAP_EXCEEDED BIT(27) ++#define MMMU_CTRL_CAP_EXCEEDED_ABORT_EN BIT(26) ++#define MMMU_CTRL_CAP_EXCEEDED_INT_EN BIT(25) ++#define MMMU_CTRL_CAP_EXCEEDED_EXCEPTION_EN BIT(24) ++#define MMMU_CTRL_PT_INVALID BIT(20) ++#define MMMU_CTRL_PT_INVALID_ABORT_EN BIT(19) ++#define MMMU_CTRL_PT_INVALID_EXCEPTION_EN BIT(18) ++#define MMMU_CTRL_PT_INVALID_EN BIT(17) ++#define MMMU_CTRL_WRITE_VIOLATION BIT(12) ++#define MMMU_CTRL_WRITE_VIOLATION_ABORT_EN BIT(11) ++#define MMMU_CTRL_WRITE_VIOLATION_INT_EN BIT(10) ++#define MMMU_CTRL_WRITE_VIOLATION_EXCEPTION_EN BIT(9) ++#define MMMU_CTRL_BYPASS BIT(8) ++#define MMMU_CTRL_TLB_CLEARING BIT(7) ++#define MMMU_CTRL_STATS_CLEAR BIT(3) ++#define MMMU_CTRL_TLB_CLEAR BIT(2) ++#define MMMU_CTRL_STATS_ENABLE BIT(1) ++#define MMMU_CTRL_ENABLE BIT(0) ++ ++#define MMMU_PT_PA_BASE_OFFSET 0x04 ++ ++#define MMMU_HIT_OFFSET 0x08 ++#define MMMU_MISS_OFFSET 0x0C ++#define MMMU_STALL_OFFSET 0x10 ++ ++#define MMMU_ADDR_CAP_OFFSET 0x14 ++#define MMMU_ADDR_CAP_ENABLE BIT(31) ++#define ADDR_CAP_SHIFT 28 /* ADDR_CAP is defined to be in 256 MByte units */ ++ ++#define MMMU_SHOOT_DOWN_OFFSET 0x18 ++#define MMMU_SHOOT_DOWN_SHOOTING BIT(31) ++#define MMMU_SHOOT_DOWN_SHOOT BIT(30) ++ ++#define MMMU_BYPASS_START_OFFSET 0x1C ++#define MMMU_BYPASS_START_ENABLE BIT(31) ++#define MMMU_BYPASS_START_INVERT BIT(30) ++ ++#define MMMU_BYPASS_END_OFFSET 0x20 ++#define MMMU_BYPASS_END_ENABLE BIT(31) ++ ++#define MMMU_MISC_OFFSET 0x24 ++#define MMMU_MISC_SINGLE_TABLE BIT(31) ++ ++#define MMMU_ILLEGAL_ADR_OFFSET 0x30 ++#define MMMU_ILLEGAL_ADR_ENABLE BIT(31) ++ ++#define MMMU_DEBUG_INFO_OFFSET 0x38 ++#define MMMU_DEBUG_INFO_VERSION_MASK 0x0000000Fu ++#define MMMU_DEBUG_INFO_VA_WIDTH_MASK 0x000000F0u ++#define MMMU_DEBUG_INFO_PA_WIDTH_MASK 0x00000F00u ++#define MMMU_DEBUG_INFO_BIGPAGE_WIDTH_MASK 0x000FF000u ++#define MMMU_DEBUG_INFO_SUPERPAGE_WIDTH_MASK 0x0FF00000u ++#define MMMU_DEBUG_INFO_BYPASS_4M BIT(28) ++#define MMMU_DEBUG_INFO_BYPASS BIT(29) ++ ++#define MMMU_PTE_PAGESIZE_MASK 0xC0000000u ++#define MMMU_PTE_WRITEABLE BIT(29) ++#define MMMU_PTE_VALID BIT(28) ++ ++/* ++ * BCM2712 IOMMU is organized around 4Kbyte pages (MMU_PAGE_SIZE). ++ * Linux PAGE_SIZE must not be smaller but may be larger (e.g. 4K, 16K). ++ * ++ * Unlike many larger MMUs, this one uses a 4-byte word size, allowing ++ * 1024 entries within each 4K table page, and two-level translation. ++ * ++ * Let's allocate enough table space for 2GB of translated memory (IOVA). ++ * This requires 512 4K pages (2MB) of level-2 tables, one page of ++ * top-level table (only half-filled in this particular configuration), ++ * plus one "default" page to catch illegal requests. ++ * ++ * The translated virtual address region is between 40GB and 42GB; ++ * addresses below this range pass straight through to the SDRAM. ++ * ++ * Currently we assume a 1:1:1 correspondence of IOMMU, group and domain. ++ */ ++ ++#define MMU_PAGE_SHIFT 12 ++#define MMU_PAGE_SIZE BIT(MMU_PAGE_SHIFT) ++ ++#define PAGEWORDS_SHIFT (MMU_PAGE_SHIFT - 2) ++#define HUGEPAGE_SHIFT (MMU_PAGE_SHIFT + PAGEWORDS_SHIFT) ++#define L1_CHUNK_SHIFT (MMU_PAGE_SHIFT + 2 * PAGEWORDS_SHIFT) ++ ++#define APERTURE_BASE (40ul << 30) ++#define APERTURE_SIZE (2ul << 30) ++#define APERTURE_TOP (APERTURE_BASE + APERTURE_SIZE) ++#define TRANSLATED_PAGES (APERTURE_SIZE >> MMU_PAGE_SHIFT) ++#define L2_PAGES (TRANSLATED_PAGES >> PAGEWORDS_SHIFT) ++#define TABLES_ALLOC_SIZE (L2_PAGES * MMU_PAGE_SIZE + 2 * PAGE_SIZE) ++ ++static void bcm2712_iommu_init(struct bcm2712_iommu *mmu) ++{ ++ unsigned int i, bypass_shift; ++ struct sg_dma_page_iter it; ++ u32 u = MMU_RD(MMMU_DEBUG_INFO_OFFSET); ++ ++ /* ++ * Check IOMMU version and hardware configuration. ++ * This driver is for VC IOMMU version >= 4 (with 2-level tables) ++ * and assumes at least 36 bits of virtual and physical address space. ++ * Bigpage and superpage sizes are typically 64K and 1M, but may vary ++ * (hugepage size is fixed at 4M, the range covered by an L2 page). ++ */ ++ dev_info(mmu->dev, "%s: DEBUG_INFO = 0x%08x\n", __func__, u); ++ WARN_ON(FIELD_GET(MMMU_DEBUG_INFO_VERSION_MASK, u) < 4 || ++ FIELD_GET(MMMU_DEBUG_INFO_VA_WIDTH_MASK, u) < 6 || ++ FIELD_GET(MMMU_DEBUG_INFO_PA_WIDTH_MASK, u) < 6 || ++ !(u & MMMU_DEBUG_INFO_BYPASS)); ++ ++ mmu->bigpage_mask = ++ ((1u << FIELD_GET(MMMU_DEBUG_INFO_BIGPAGE_WIDTH_MASK, u)) - 1u) << MMU_PAGE_SHIFT; ++ mmu->superpage_mask = ++ ((1u << FIELD_GET(MMMU_DEBUG_INFO_SUPERPAGE_WIDTH_MASK, u)) - 1u) << MMU_PAGE_SHIFT; ++ bypass_shift = (u & MMMU_DEBUG_INFO_BYPASS_4M) ? ++ HUGEPAGE_SHIFT : ADDR_CAP_SHIFT; ++ ++ /* Disable MMU and clear sticky flags; meanwhile flush the TLB */ ++ MMU_WR(MMMU_CTRL_OFFSET, ++ MMMU_CTRL_CAP_EXCEEDED | ++ MMMU_CTRL_PT_INVALID | ++ MMMU_CTRL_WRITE_VIOLATION | ++ MMMU_CTRL_STATS_CLEAR | ++ MMMU_CTRL_TLB_CLEAR); ++ ++ /* ++ * Put MMU into 2-level mode; set address cap and "bypass" range ++ * (note that some of these registers have unintuitive off-by-ones). ++ * Addresses below APERTURE_BASE are passed unchanged: this is ++ * useful for blocks which share an IOMMU with other blocks ++ * whose drivers are not IOMMU-aware. ++ */ ++ MMU_WR(MMMU_MISC_OFFSET, ++ MMU_RD(MMMU_MISC_OFFSET) & ~MMMU_MISC_SINGLE_TABLE); ++ MMU_WR(MMMU_ADDR_CAP_OFFSET, ++ MMMU_ADDR_CAP_ENABLE + ++ (APERTURE_TOP >> ADDR_CAP_SHIFT) - 1); ++ if (APERTURE_BASE > 0) { ++ MMU_WR(MMMU_BYPASS_START_OFFSET, ++ MMMU_BYPASS_START_ENABLE + MMMU_BYPASS_START_INVERT + ++ (APERTURE_BASE >> bypass_shift) - 1); ++ MMU_WR(MMMU_BYPASS_END_OFFSET, ++ MMMU_BYPASS_END_ENABLE + ++ (APERTURE_TOP >> bypass_shift)); ++ } else { ++ MMU_WR(MMMU_BYPASS_START_OFFSET, 0); ++ MMU_WR(MMMU_BYPASS_END_OFFSET, 0); ++ } ++ ++ /* Ensure tables are zeroed (which marks all pages as invalid) */ ++ dma_sync_sgtable_for_cpu(mmu->dev, mmu->sgt, DMA_TO_DEVICE); ++ memset(mmu->tables, 0, TABLES_ALLOC_SIZE); ++ mmu->nmapped_pages = 0; ++ ++ /* Initialize the high-level table to point to the low-level pages */ ++ __sg_page_iter_start(&it.base, mmu->sgt->sgl, mmu->sgt->nents, 0); ++ for (i = 0; i < L2_PAGES; i++) { ++ if (!(i % (PAGE_SIZE / MMU_PAGE_SIZE))) { ++ __sg_page_iter_dma_next(&it); ++ u = (sg_page_iter_dma_address(&it) >> MMU_PAGE_SHIFT); ++ } else { ++ u++; ++ } ++ mmu->tables[TRANSLATED_PAGES + i] = MMMU_PTE_VALID + u; ++ } ++ ++ /* ++ * Configure the addresses of the top-level table (offset because ++ * the aperture does not start from zero), and of the default page. ++ * For simplicity, both these regions are whole Linux pages. ++ */ ++ __sg_page_iter_dma_next(&it); ++ u = (sg_page_iter_dma_address(&it) >> MMU_PAGE_SHIFT); ++ MMU_WR(MMMU_PT_PA_BASE_OFFSET, u - (APERTURE_BASE >> L1_CHUNK_SHIFT)); ++ __sg_page_iter_dma_next(&it); ++ u = (sg_page_iter_dma_address(&it) >> MMU_PAGE_SHIFT); ++ MMU_WR(MMMU_ILLEGAL_ADR_OFFSET, MMMU_ILLEGAL_ADR_ENABLE + u); ++ dma_sync_sgtable_for_device(mmu->dev, mmu->sgt, DMA_TO_DEVICE); ++ mmu->dirty = false; ++ ++ /* Flush (and enable) the shared TLB cache; enable this MMU. */ ++ if (mmu->cache) ++ bcm2712_iommu_cache_flush(mmu->cache); ++ MMU_WR(MMMU_CTRL_OFFSET, ++ MMMU_CTRL_CAP_EXCEEDED_ABORT_EN | ++ MMMU_CTRL_PT_INVALID_ABORT_EN | ++ MMMU_CTRL_WRITE_VIOLATION_ABORT_EN | ++ MMMU_CTRL_STATS_ENABLE | ++ MMMU_CTRL_ENABLE); ++} ++ ++static int bcm2712_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) ++{ ++ struct bcm2712_iommu *mmu = dev ? dev_iommu_priv_get(dev) : 0; ++ struct bcm2712_iommu_domain *mydomain = ++ container_of(domain, struct bcm2712_iommu_domain, base); ++ ++ dev_info(dev, "%s: MMU %s\n", ++ __func__, mmu ? dev_name(mmu->dev) : ""); ++ ++ if (mmu) { ++ mydomain->mmu = mmu; ++ mmu->domain = mydomain; ++ ++ if (mmu->dma_iova_offset) { ++ domain->geometry.aperture_start = ++ mmu->dma_iova_offset + APERTURE_BASE; ++ domain->geometry.aperture_end = ++ mmu->dma_iova_offset + APERTURE_TOP - 1ul; ++ } ++ ++ return 0; ++ } ++ return -EINVAL; ++} ++ ++static void bcm2712_iommu_detach_dev(struct iommu_domain *domain, struct device *dev) ++{ ++ (void)domain; ++ (void)dev; ++} ++ ++static int bcm2712_iommu_map(struct iommu_domain *domain, unsigned long iova, ++ phys_addr_t pa, size_t bytes, int prot, gfp_t gfp) ++{ ++ struct bcm2712_iommu *mmu = domain_to_mmu(domain); ++ ++ (void)gfp; ++ iova -= mmu->dma_iova_offset; ++ if (iova >= APERTURE_BASE && iova + bytes <= APERTURE_TOP) { ++ unsigned int p; ++ u32 entry = MMMU_PTE_VALID | (pa >> MMU_PAGE_SHIFT); ++ u32 align = (u32)(iova | pa | bytes); ++ ++ /* large page and write enable flags */ ++ if (!(align & ((1 << HUGEPAGE_SHIFT) - 1))) ++ entry |= FIELD_PREP(MMMU_PTE_PAGESIZE_MASK, 3); ++ else if (!(align & mmu->superpage_mask) && mmu->superpage_mask) ++ entry |= FIELD_PREP(MMMU_PTE_PAGESIZE_MASK, 2); ++ else if (!(align & mmu->bigpage_mask) && mmu->bigpage_mask) ++ entry |= FIELD_PREP(MMMU_PTE_PAGESIZE_MASK, 1); ++ if (prot & IOMMU_WRITE) ++ entry |= MMMU_PTE_WRITEABLE; ++ ++ /* Ensure tables are cache-coherent with CPU */ ++ if (!mmu->dirty) { ++ dma_sync_sgtable_for_cpu(mmu->dev, mmu->sgt, DMA_TO_DEVICE); ++ mmu->dirty = true; ++ } ++ ++ iova -= APERTURE_BASE; ++ for (p = iova >> MMU_PAGE_SHIFT; ++ p < (iova + bytes) >> MMU_PAGE_SHIFT; p++) { ++ mmu->nmapped_pages += !(mmu->tables[p]); ++ mmu->tables[p] = entry++; ++ } ++ } else if (iova + bytes > APERTURE_BASE || iova != pa) { ++ dev_warn(mmu->dev, "%s: iova=0x%lx pa=0x%llx size=0x%llx OUT OF RANGE!\n", ++ __func__, iova, ++ (unsigned long long)pa, (unsigned long long)bytes); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static size_t bcm2712_iommu_unmap(struct iommu_domain *domain, unsigned long iova, ++ size_t bytes, struct iommu_iotlb_gather *gather) ++{ ++ struct bcm2712_iommu *mmu = domain_to_mmu(domain); ++ ++ if (iova >= mmu->dma_iova_offset + APERTURE_BASE && ++ iova + bytes <= mmu->dma_iova_offset + APERTURE_TOP) { ++ unsigned int p; ++ ++ /* Record just the lower and upper bounds in "gather" */ ++ if (gather) { ++ bool empty = (gather->end <= gather->start); ++ ++ if (empty || gather->start < iova) ++ gather->start = iova; ++ if (empty || gather->end < iova + bytes) ++ gather->end = iova + bytes; ++ } ++ ++ /* Ensure tables are cache-coherent with CPU */ ++ if (!mmu->dirty) { ++ dma_sync_sgtable_for_cpu(mmu->dev, mmu->sgt, DMA_TO_DEVICE); ++ mmu->dirty = true; ++ } ++ ++ /* Clear table entries, this marks the addresses as illegal */ ++ iova -= (mmu->dma_iova_offset + APERTURE_BASE); ++ for (p = iova >> MMU_PAGE_SHIFT; ++ p < (iova + bytes) >> MMU_PAGE_SHIFT; ++ p++) { ++ mmu->nmapped_pages -= !!(mmu->tables[p]); ++ mmu->tables[p] = 0; ++ } ++ } ++ ++ return bytes; ++} ++ ++static void bcm2712_iommu_sync_range(struct iommu_domain *domain, ++ unsigned long iova, size_t size) ++{ ++ struct bcm2712_iommu *mmu = domain_to_mmu(domain); ++ unsigned long iova_end; ++ unsigned int i, p4; ++ ++ if (!mmu || !mmu->dirty) ++ return; ++ ++ /* Ensure tables are cleaned from CPU cache or write-buffer */ ++ dma_sync_sgtable_for_device(mmu->dev, mmu->sgt, DMA_TO_DEVICE); ++ mmu->dirty = false; ++ ++ /* Flush the shared TLB cache */ ++ if (mmu->cache) ++ bcm2712_iommu_cache_flush(mmu->cache); ++ ++ /* ++ * When flushing a large range or when nothing needs to be kept, ++ * it's quicker to use the"TLB_CLEAR" flag. Otherwise, invalidate ++ * TLB entries in lines of 4 words each. Each flush/clear operation ++ * should complete almost instantaneously. ++ */ ++ iova -= mmu->dma_iova_offset; ++ iova_end = min(APERTURE_TOP, iova + size); ++ iova = max(APERTURE_BASE, iova); ++ if (mmu->nmapped_pages == 0 || iova_end - iova >= APERTURE_SIZE / 8) { ++ MMU_WR(MMMU_CTRL_OFFSET, ++ MMMU_CTRL_CAP_EXCEEDED_ABORT_EN | ++ MMMU_CTRL_PT_INVALID_ABORT_EN | ++ MMMU_CTRL_WRITE_VIOLATION_ABORT_EN | ++ MMMU_CTRL_TLB_CLEAR | ++ MMMU_CTRL_STATS_ENABLE | ++ MMMU_CTRL_ENABLE); ++ for (i = 0; i < 1024; i++) { ++ if (!(MMMU_CTRL_TLB_CLEARING & MMU_RD(MMMU_CTRL_OFFSET))) ++ break; ++ cpu_relax(); ++ } ++ } else { ++ for (p4 = iova >> (MMU_PAGE_SHIFT + 2); ++ p4 < (iova_end + 3 * MMU_PAGE_SIZE) >> (MMU_PAGE_SHIFT + 2); ++ p4++) { ++ MMU_WR(MMMU_SHOOT_DOWN_OFFSET, ++ MMMU_SHOOT_DOWN_SHOOT + (p4 << 2)); ++ for (i = 0; i < 1024; i++) { ++ if (!(MMMU_SHOOT_DOWN_SHOOTING & MMU_RD(MMMU_SHOOT_DOWN_OFFSET))) ++ break; ++ cpu_relax(); ++ } ++ } ++ } ++} ++ ++static void bcm2712_iommu_sync(struct iommu_domain *domain, ++ struct iommu_iotlb_gather *gather) ++{ ++ bcm2712_iommu_sync_range(domain, gather->start, ++ gather->end - gather->start); ++} ++ ++static void bcm2712_iommu_sync_all(struct iommu_domain *domain) ++{ ++ bcm2712_iommu_sync_range(domain, APERTURE_BASE, APERTURE_SIZE); ++} ++ ++static phys_addr_t bcm2712_iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova) ++{ ++ struct bcm2712_iommu *mmu = domain_to_mmu(domain); ++ u32 p; ++ ++ iova -= mmu->dma_iova_offset; ++ if (iova >= APERTURE_BASE && iova < APERTURE_TOP) { ++ p = (iova - APERTURE_BASE) >> MMU_PAGE_SHIFT; ++ p = mmu->tables[p] & 0x0FFFFFFFu; ++ return (((phys_addr_t)p) << MMU_PAGE_SHIFT) + (iova & (MMU_PAGE_SIZE - 1u)); ++ } else if (iova < APERTURE_BASE) { ++ return (phys_addr_t)iova; ++ } else { ++ return (phys_addr_t)-EINVAL; ++ } ++} ++ ++static void bcm2712_iommu_domain_free(struct iommu_domain *domain) ++{ ++ struct bcm2712_iommu_domain *mydomain = ++ container_of(domain, struct bcm2712_iommu_domain, base); ++ ++ kfree(mydomain); ++} ++ ++static const struct iommu_domain_ops bcm2712_iommu_domain_ops = { ++ .attach_dev = bcm2712_iommu_attach_dev, ++ .detach_dev = bcm2712_iommu_detach_dev, ++ .map = bcm2712_iommu_map, ++ .unmap = bcm2712_iommu_unmap, ++ .iotlb_sync = bcm2712_iommu_sync, ++ .iotlb_sync_map = bcm2712_iommu_sync_range, ++ .flush_iotlb_all = bcm2712_iommu_sync_all, ++ .iova_to_phys = bcm2712_iommu_iova_to_phys, ++ .free = bcm2712_iommu_domain_free, ++}; ++ ++static struct iommu_domain *bcm2712_iommu_domain_alloc(unsigned int type) ++{ ++ struct bcm2712_iommu_domain *domain; ++ ++ if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA) ++ return NULL; ++ ++ domain = kzalloc(sizeof(*domain), GFP_KERNEL); ++ if (!domain) ++ return NULL; ++ ++ domain->base.type = type; ++ domain->base.ops = &bcm2712_iommu_domain_ops; ++ domain->base.geometry.aperture_start = APERTURE_BASE; ++ domain->base.geometry.aperture_end = APERTURE_TOP - 1ul; ++ domain->base.geometry.force_aperture = true; ++ return &domain->base; ++} ++ ++static struct iommu_device *bcm2712_iommu_probe_device(struct device *dev) ++{ ++ struct bcm2712_iommu *mmu; ++ ++ /* ++ * For reasons I don't fully understand, we need to try both ++ * cases (dev_iommu_priv_get() and platform_get_drvdata()) ++ * in order to get both GPU and ISP-BE to probe successfully. ++ */ ++ mmu = dev_iommu_priv_get(dev); ++ if (!mmu) { ++ struct device_node *np; ++ struct platform_device *pdev; ++ ++ /* Ignore devices that don't have an "iommus" property with exactly one phandle */ ++ if (!dev->of_node || ++ of_property_count_elems_of_size(dev->of_node, "iommus", sizeof(phandle)) != 1) ++ return ERR_PTR(-ENODEV); ++ ++ np = of_parse_phandle(dev->of_node, "iommus", 0); ++ if (!np) ++ return ERR_PTR(-EINVAL); ++ ++ pdev = of_find_device_by_node(np); ++ of_node_put(np); ++ if (pdev) ++ mmu = platform_get_drvdata(pdev); ++ ++ if (!mmu) ++ return ERR_PTR(-ENODEV); ++ } ++ ++ dev_info(dev, "%s: MMU %s\n", __func__, dev_name(mmu->dev)); ++ dev_iommu_priv_set(dev, mmu); ++ return &mmu->iommu; ++} ++ ++static void bcm2712_iommu_release_device(struct device *dev) ++{ ++ dev_iommu_priv_set(dev, NULL); ++} ++ ++static struct iommu_group *bcm2712_iommu_device_group(struct device *dev) ++{ ++ struct bcm2712_iommu *mmu = dev_iommu_priv_get(dev); ++ ++ if (!mmu || !mmu->group) ++ return ERR_PTR(-EINVAL); ++ ++ dev_info(dev, "%s: MMU %s\n", __func__, dev_name(mmu->dev)); ++ return iommu_group_ref_get(mmu->group); ++} ++ ++static int bcm2712_iommu_of_xlate(struct device *dev, ++ struct of_phandle_args *args) ++{ ++ struct platform_device *iommu_dev; ++ struct bcm2712_iommu *mmu; ++ ++ iommu_dev = of_find_device_by_node(args->np); ++ mmu = platform_get_drvdata(iommu_dev); ++ dev_iommu_priv_set(dev, mmu); ++ dev_info(dev, "%s: MMU %s\n", __func__, dev_name(mmu->dev)); ++ ++ return 0; ++} ++ ++static bool bcm2712_iommu_capable(struct device *dev, enum iommu_cap cap) ++{ ++ return false; ++} ++ ++static const struct iommu_ops bcm2712_iommu_ops = { ++ .capable = bcm2712_iommu_capable, ++ .domain_alloc = bcm2712_iommu_domain_alloc, ++ .probe_device = bcm2712_iommu_probe_device, ++ .release_device = bcm2712_iommu_release_device, ++ .device_group = bcm2712_iommu_device_group, ++ /* Advertise native page sizes as well as 2M, 16K which Linux may prefer */ ++ .pgsize_bitmap = (SZ_4M | SZ_2M | SZ_1M | SZ_64K | SZ_16K | SZ_4K), ++ .default_domain_ops = &bcm2712_iommu_domain_ops, ++ .of_xlate = bcm2712_iommu_of_xlate, ++}; ++ ++static int bcm2712_iommu_probe(struct platform_device *pdev) ++{ ++ struct bcm2712_iommu *mmu; ++ struct bcm2712_iommu_cache *cache = NULL; ++ int ret; ++ ++ /* First of all, check for an IOMMU shared cache */ ++ if (pdev->dev.of_node) { ++ struct device_node *cache_np; ++ struct platform_device *cache_pdev; ++ ++ cache_np = of_parse_phandle(pdev->dev.of_node, "cache", 0); ++ if (cache_np) { ++ cache_pdev = of_find_device_by_node(cache_np); ++ of_node_put(cache_np); ++ if (cache_pdev && !IS_ERR(cache_pdev)) ++ cache = platform_get_drvdata(cache_pdev); ++ if (!cache) ++ return -EPROBE_DEFER; ++ } ++ } ++ ++ /* Allocate private data */ ++ mmu = devm_kzalloc(&pdev->dev, sizeof(*mmu), GFP_KERNEL); ++ if (!mmu) ++ return -ENOMEM; ++ ++ mmu->name = dev_name(&pdev->dev); ++ mmu->dev = &pdev->dev; ++ mmu->cache = cache; ++ platform_set_drvdata(pdev, mmu); ++ spin_lock_init(&mmu->hw_lock); ++ ++ /* ++ * XXX When an IOMMU is downstream of a PCIe RC or some other chip/bus ++ * and serves some of the masters thereon (others using pass-through), ++ * we seem to fumble and lose the "dma-ranges" address offset for ++ * masters using IOMMU. This property restores it, where needed. ++ */ ++ if (!pdev->dev.of_node || ++ of_property_read_u64(pdev->dev.of_node, "dma-iova-offset", ++ &mmu->dma_iova_offset)) ++ mmu->dma_iova_offset = 0; ++ ++ /* ++ * The IOMMU is itself a device that allocates DMA-able memory ++ * to hold its translation tables. Provided the IOVA aperture ++ * is no larger than 4 GBytes (so that the L1 table fits within ++ * a single 4K page), we don't need the tables to be contiguous. ++ * Assume we can address at least 36 bits (64 GB). ++ */ ++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); ++ WARN_ON(ret); ++ mmu->sgt = dma_alloc_noncontiguous(&pdev->dev, TABLES_ALLOC_SIZE, ++ DMA_TO_DEVICE, GFP_KERNEL, ++ DMA_ATTR_ALLOC_SINGLE_PAGES); ++ if (!mmu->sgt) { ++ ret = -ENOMEM; ++ goto done_err; ++ } ++ mmu->tables = dma_vmap_noncontiguous(&pdev->dev, TABLES_ALLOC_SIZE, ++ mmu->sgt); ++ if (!mmu->tables) { ++ ret = -ENOMEM; ++ goto done_err; ++ } ++ ++ /* Get IOMMU registers */ ++ mmu->reg_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(mmu->reg_base)) { ++ dev_err(&pdev->dev, "Failed to get IOMMU registers address\n"); ++ ret = PTR_ERR(mmu->reg_base); ++ goto done_err; ++ } ++ ++ /* Stuff */ ++ mmu->group = iommu_group_alloc(); ++ if (IS_ERR(mmu->group)) { ++ ret = PTR_ERR(mmu->group); ++ mmu->group = NULL; ++ goto done_err; ++ } ++ ret = iommu_device_sysfs_add(&mmu->iommu, mmu->dev, NULL, mmu->name); ++ if (ret) ++ goto done_err; ++ ++ /* Initialize table and hardware */ ++ bcm2712_iommu_init(mmu); ++ ret = iommu_device_register(&mmu->iommu, &bcm2712_iommu_ops, &pdev->dev); ++ ++ dev_info(&pdev->dev, "%s: Success\n", __func__); ++ return 0; ++ ++done_err: ++ dev_info(&pdev->dev, "%s: Failure %d\n", __func__, ret); ++ if (mmu->group) ++ iommu_group_put(mmu->group); ++ if (mmu->tables) ++ dma_vunmap_noncontiguous(&pdev->dev, ++ (void *)(mmu->tables)); ++ mmu->tables = NULL; ++ if (mmu->sgt) ++ dma_free_noncontiguous(&pdev->dev, TABLES_ALLOC_SIZE, ++ mmu->sgt, DMA_TO_DEVICE); ++ mmu->sgt = NULL; ++ kfree(mmu); ++ return ret; ++} ++ ++static int bcm2712_iommu_remove(struct platform_device *pdev) ++{ ++ struct bcm2712_iommu *mmu = platform_get_drvdata(pdev); ++ ++ if (mmu->reg_base) ++ MMU_WR(MMMU_CTRL_OFFSET, 0); /* disable the MMU */ ++ if (mmu->sgt) ++ dma_free_noncontiguous(&pdev->dev, TABLES_ALLOC_SIZE, ++ mmu->sgt, DMA_TO_DEVICE); ++ ++ return 0; ++} ++ ++static const struct of_device_id bcm2712_iommu_of_match[] = { ++ { ++ . compatible = "brcm,bcm2712-iommu" ++ }, ++ { /* sentinel */ }, ++}; ++ ++static struct platform_driver bcm2712_iommu_driver = { ++ .probe = bcm2712_iommu_probe, ++ .remove = bcm2712_iommu_remove, ++ .driver = { ++ .name = "bcm2712-iommu", ++ .of_match_table = bcm2712_iommu_of_match ++ }, ++}; ++ ++builtin_platform_driver(bcm2712_iommu_driver); +--- /dev/null ++++ b/drivers/iommu/bcm2712-iommu.h +@@ -0,0 +1,45 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * IOMMU driver for BCM2712 ++ * ++ * Copyright (c) 2023 Raspberry Pi Ltd. ++ */ ++ ++#ifndef _BCM2712_IOMMU_H ++#define _BCM2712_IOMMU_H ++ ++#include ++#include ++ ++struct bcm2712_iommu_cache { ++ struct device *dev; ++ spinlock_t hw_lock; /* to protect HW registers */ ++ void __iomem *reg_base; ++}; ++ ++void bcm2712_iommu_cache_flush(struct bcm2712_iommu_cache *cache); ++ ++struct bcm2712_iommu { ++ struct device *dev; ++ struct iommu_device iommu; ++ struct iommu_group *group; ++ struct bcm2712_iommu_domain *domain; ++ char const *name; ++ struct sg_table *sgt; /* allocated memory for page tables */ ++ u32 *tables; /* kernel mapping for page tables */ ++ struct bcm2712_iommu_cache *cache; ++ spinlock_t hw_lock; /* to protect HW registers */ ++ void __iomem *reg_base; ++ u64 dma_iova_offset; /* Hack for IOMMU attached to PCIe RC */ ++ u32 bigpage_mask; ++ u32 superpage_mask; ++ unsigned int nmapped_pages; ++ bool dirty; /* true when tables are oriented towards CPU */ ++}; ++ ++struct bcm2712_iommu_domain { ++ struct iommu_domain base; ++ struct bcm2712_iommu *mmu; ++}; ++ ++#endif diff --git a/target/linux/bcm27xx/patches-6.1/950-0918-irqchip-irq-brcmstb-l2-Add-config-for-2711-controlle.patch b/target/linux/bcm27xx/patches-6.1/950-0918-irqchip-irq-brcmstb-l2-Add-config-for-2711-controlle.patch new file mode 100644 index 0000000000..5ea212d4a7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0918-irqchip-irq-brcmstb-l2-Add-config-for-2711-controlle.patch @@ -0,0 +1,73 @@ +From fa4d4ed28c92cf4470e518f1a7362dc7941632d7 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Wed, 28 Jun 2023 16:24:29 +0100 +Subject: [PATCH] irqchip/irq-brcmstb-l2: Add config for 2711 controller + +We currently see these regularly: +[ 25.157560] irq 31, desc: 00000000c15e6d2c, depth: 0, count: 0, unhandled: 0 +[ 25.164658] ->handle_irq(): 00000000b1775675, brcmstb_l2_intc_irq_handle+0x0/0x1a8 +[ 25.172352] ->irq_data.chip(): 00000000fea59f1c, gic_chip_mode1+0x0/0x108 +[ 25.179166] ->action(): 000000003eda6d6f +[ 25.183096] ->action->handler(): 000000002c09e646, bad_chained_irq+0x0/0x58 +[ 25.190084] IRQ_LEVEL set +[ 25.193142] IRQ_NOPROBE set +[ 25.196198] IRQ_NOREQUEST set +[ 25.199255] IRQ_NOTHREAD set + +with: +$ cat /proc/interrupts | grep 31: + 31: 1 0 0 0 GICv2 129 Level (null) + +The interrupt is described in DT with IRQ_TYPE_LEVEL_HIGH + +But the current compatible string uses the controller in edge triggered mode +(as that config matches our register layout). + +Add a new compatible structure for level driven interrupt with our register layout. + +We had already been using this compatible string in device tree, so no change needed +there. + +Signed-off-by: Dom Cobley +--- + drivers/irqchip/irq-brcmstb-l2.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/drivers/irqchip/irq-brcmstb-l2.c ++++ b/drivers/irqchip/irq-brcmstb-l2.c +@@ -52,6 +52,16 @@ static const struct brcmstb_intc_init_pa + .cpu_mask_clear = 0x0C + }; + ++/* Register offsets in the 2711 L2 level interrupt controller */ ++static const struct brcmstb_intc_init_params l2_2711_lvl_intc_init = { ++ .handler = handle_level_irq, ++ .cpu_status = 0x00, ++ .cpu_clear = 0x08, ++ .cpu_mask_status = 0x0c, ++ .cpu_mask_set = 0x10, ++ .cpu_mask_clear = 0x14 ++}; ++ + /* L2 intc private data structure */ + struct brcmstb_l2_intc_data { + struct irq_domain *domain; +@@ -286,11 +296,18 @@ static int __init brcmstb_l2_lvl_intc_of + return brcmstb_l2_intc_of_init(np, parent, &l2_lvl_intc_init); + } + ++static int __init brcmstb_l2_2711_lvl_intc_of_init(struct device_node *np, ++ struct device_node *parent) ++{ ++ return brcmstb_l2_intc_of_init(np, parent, &l2_2711_lvl_intc_init); ++} ++ + IRQCHIP_PLATFORM_DRIVER_BEGIN(brcmstb_l2) + IRQCHIP_MATCH("brcm,l2-intc", brcmstb_l2_edge_intc_of_init) + IRQCHIP_MATCH("brcm,hif-spi-l2-intc", brcmstb_l2_edge_intc_of_init) + IRQCHIP_MATCH("brcm,upg-aux-aon-l2-intc", brcmstb_l2_edge_intc_of_init) + IRQCHIP_MATCH("brcm,bcm7271-l2-intc", brcmstb_l2_lvl_intc_of_init) ++IRQCHIP_MATCH("brcm,bcm2711-l2-intc", brcmstb_l2_2711_lvl_intc_of_init) + IRQCHIP_PLATFORM_DRIVER_END(brcmstb_l2) + MODULE_DESCRIPTION("Broadcom STB generic L2 interrupt controller"); + MODULE_LICENSE("GPL v2"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0919-rtc-rtc-rpi-Add-simple-RTC-driver-for-Raspberry-Pi.patch b/target/linux/bcm27xx/patches-6.1/950-0919-rtc-rtc-rpi-Add-simple-RTC-driver-for-Raspberry-Pi.patch new file mode 100644 index 0000000000..e2b8c6c6a1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0919-rtc-rtc-rpi-Add-simple-RTC-driver-for-Raspberry-Pi.patch @@ -0,0 +1,237 @@ +From 222dedcdc09247126d39364a614ff2019789f52a Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Fri, 7 Jul 2023 20:00:45 +0100 +Subject: [PATCH] rtc: rtc-rpi: Add simple RTC driver for Raspberry Pi + +This supports setting and reading the real time clock +and supports wakeup alarms. + +To support wake up alarms you want this bootloader config: + POWER_OFF_ON_HALT=1 + WAKE_ON_GPIO=0 + +You can test with: + echo +600 | sudo tee /sys/class/rtc/rtc0/wakealarm + sudo halt + +That will halt (in an almost no power state), +then wake and restart after 10 minutes. + +Signed-off-by: Dom Cobley +--- + drivers/rtc/Kconfig | 11 +++ + drivers/rtc/Makefile | 1 + + drivers/rtc/rtc-rpi.c | 177 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 189 insertions(+) + create mode 100644 drivers/rtc/rtc-rpi.c + +--- a/drivers/rtc/Kconfig ++++ b/drivers/rtc/Kconfig +@@ -223,6 +223,17 @@ config RTC_DRV_AC100 + This driver can also be built as a module. If so, the module + will be called rtc-ac100. + ++config RTC_DRV_RPI ++ tristate "Raspberry Pi RTC" ++ depends on ARCH_BRCMSTB || COMPILE_TEST ++ default ARCH_BRCMSTB ++ help ++ If you say yes here you get support for the RTC found on ++ Raspberry Pi devices. ++ ++ This driver can also be built as a module. If so, the module ++ will be called rtc-rpi. ++ + config RTC_DRV_BRCMSTB + tristate "Broadcom STB wake-timer" + depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST +--- a/drivers/rtc/Makefile ++++ b/drivers/rtc/Makefile +@@ -140,6 +140,7 @@ obj-$(CONFIG_RTC_DRV_RC5T583) += rtc-rc5 + obj-$(CONFIG_RTC_DRV_RC5T619) += rtc-rc5t619.o + obj-$(CONFIG_RTC_DRV_RK808) += rtc-rk808.o + obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o ++obj-$(CONFIG_RTC_DRV_RPI) += rtc-rpi.o + obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o + obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o + obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o +--- /dev/null ++++ b/drivers/rtc/rtc-rpi.c +@@ -0,0 +1,177 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause ++/** ++ * rtc-rpi.c ++ * ++ * RTC driver using firmware mailbox ++ * Supports battery backed RTC and wake alarms ++ * ++ * Based on rtc-meson-vrtc by Neil Armstrong ++ * ++ * Copyright (c) 2023, Raspberry Pi Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++struct rpi_rtc_data { ++ struct rtc_device *rtc; ++ struct rpi_firmware *fw; ++}; ++ ++#define RPI_FIRMWARE_GET_RTC_REG 0x00030087 ++#define RPI_FIRMWARE_SET_RTC_REG 0x00038087 ++enum {RTC_TIME, RTC_ALARM, RTC_ALARM_PENDING, RTC_ALARM_ENABLE}; ++ ++static int rpi_rtc_read_time(struct device *dev, struct rtc_time *tm) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_TIME}; ++ int err; ++ ++ err = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_GET_RTC_REG, ++ &data, sizeof(data)); ++ rtc_time64_to_tm(data[1], tm); ++ return err; ++} ++ ++static int rpi_rtc_set_time(struct device *dev, struct rtc_time *tm) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_TIME, rtc_tm_to_time64(tm)}; ++ ++ return rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_SET_RTC_REG, ++ &data, sizeof(data)); ++} ++ ++static int rpi_rtc_alarm_irq_is_enabled(struct device *dev, unsigned char *enabled) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_ALARM_ENABLE}; ++ s32 err = 0; ++ ++ err = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_GET_RTC_REG, ++ &data, sizeof(data)); ++ *enabled = data[1] & 0x1; ++ return err; ++} ++ ++static int rpi_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_ALARM_ENABLE, enabled}; ++ ++ return rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_SET_RTC_REG, ++ &data, sizeof(data)); ++} ++ ++static int rpi_rtc_alarm_clear_pending(struct device *dev) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_ALARM_PENDING, 1}; ++ ++ return rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_SET_RTC_REG, ++ &data, sizeof(data)); ++} ++ ++static int rpi_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_ALARM}; ++ s32 err = 0; ++ ++ err = rpi_rtc_alarm_irq_is_enabled(dev, &alarm->enabled); ++ if (!err) ++ err = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_GET_RTC_REG, ++ &data, sizeof(data)); ++ rtc_time64_to_tm(data[1], &alarm->time); ++ ++ return err; ++} ++ ++static int rpi_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_ALARM, rtc_tm_to_time64(&alarm->time)}; ++ int err; ++ ++ err = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_SET_RTC_REG, ++ &data, sizeof(data)); ++ ++ if (err == 0) ++ err = rpi_rtc_alarm_irq_enable(dev, alarm->enabled); ++ ++ return err; ++} ++ ++static const struct rtc_class_ops rpi_rtc_ops = { ++ .read_time = rpi_rtc_read_time, ++ .set_time = rpi_rtc_set_time, ++ .read_alarm = rpi_rtc_read_alarm, ++ .set_alarm = rpi_rtc_set_alarm, ++ .alarm_irq_enable = rpi_rtc_alarm_irq_enable, ++}; ++ ++static int rpi_rtc_probe(struct platform_device *pdev) ++{ ++ struct rpi_rtc_data *vrtc; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct device_node *fw_node; ++ struct rpi_firmware *fw; ++ int ret; ++ ++ fw_node = of_parse_phandle(np, "firmware", 0); ++ if (!fw_node) { ++ dev_err(dev, "Missing firmware node\n"); ++ return -ENOENT; ++ } ++ ++ fw = rpi_firmware_get(fw_node); ++ if (!fw) ++ return -EPROBE_DEFER; ++ ++ vrtc = devm_kzalloc(&pdev->dev, sizeof(*vrtc), GFP_KERNEL); ++ if (!vrtc) ++ return -ENOMEM; ++ ++ vrtc->fw = fw; ++ ++ device_init_wakeup(&pdev->dev, 1); ++ ++ platform_set_drvdata(pdev, vrtc); ++ ++ vrtc->rtc = devm_rtc_allocate_device(&pdev->dev); ++ if (IS_ERR(vrtc->rtc)) ++ return PTR_ERR(vrtc->rtc); ++ ++ set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, vrtc->rtc->features); ++ clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, vrtc->rtc->features); ++ ++ vrtc->rtc->ops = &rpi_rtc_ops; ++ ret = devm_rtc_register_device(vrtc->rtc); ++ ++ rpi_rtc_alarm_clear_pending(dev); ++ return ret; ++} ++ ++static const struct of_device_id rpi_rtc_dt_match[] = { ++ { .compatible = "raspberrypi,rpi-rtc"}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rpi_rtc_dt_match); ++ ++static struct platform_driver rpi_rtc_driver = { ++ .probe = rpi_rtc_probe, ++ .driver = { ++ .name = "rpi-rtc", ++ .of_match_table = rpi_rtc_dt_match, ++ }, ++}; ++ ++module_platform_driver(rpi_rtc_driver); ++ ++MODULE_DESCRIPTION("Raspberry Pi RTC driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/bcm27xx/patches-6.1/950-0920-dt-bindings-rtc-new-binding-for-Raspberry-Pi-RTC-dri.patch b/target/linux/bcm27xx/patches-6.1/950-0920-dt-bindings-rtc-new-binding-for-Raspberry-Pi-RTC-dri.patch new file mode 100644 index 0000000000..f4c630cf09 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0920-dt-bindings-rtc-new-binding-for-Raspberry-Pi-RTC-dri.patch @@ -0,0 +1,35 @@ +From ff2c2f67689e10ad66c1e33ae6a7552d82ac983c Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Fri, 7 Jul 2023 20:16:06 +0100 +Subject: [PATCH] dt-bindings: rtc: new binding for Raspberry Pi RTC driver + +Add binding for the new RTC driver for Raspberry Pi. +This platform has an RTC managed by firmware, and this RTC +driver provides the simple mailbox interface to access it. + +Signed-off-by: Dom Cobley +--- + .../devicetree/bindings/rtc/rtc-rpi.txt | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + create mode 100644 Documentation/devicetree/bindings/rtc/rtc-rpi.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/rtc/rtc-rpi.txt +@@ -0,0 +1,17 @@ ++* Raspberry Pi RTC ++ ++This is a Linux interface to an RTC managed by firmware, hence it's ++virtual from a Linux perspective. ++ ++The interface uses the firmware mailbox api to access the RTC registers. ++ ++Required properties: ++compatible: should be "raspberrypi,rpi-rtc" ++firmware: Reference to the RPi firmware device node. ++ ++Example: ++ ++ rpi_rtc: rpi_rtc { ++ compatible = "raspberrypi,rpi-rtc"; ++ firmware = <&firmware>; ++ }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0921-hwmon-pwm-fan-Add-fan-speed-register-support.patch b/target/linux/bcm27xx/patches-6.1/950-0921-hwmon-pwm-fan-Add-fan-speed-register-support.patch new file mode 100644 index 0000000000..205806cdfd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0921-hwmon-pwm-fan-Add-fan-speed-register-support.patch @@ -0,0 +1,164 @@ +From 96a8a4776cb142f5d2bb7f6379df9af40e727c0b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 11 Jul 2023 10:17:29 +0100 +Subject: [PATCH] hwmon: (pwm-fan) Add fan speed register support + +Some platforms include a fan-speed register that reports RPM directly +as an alternative to counting interrupts from the fan tachometer input. +Add support for reading a register at a given offset (rpm-offset) within +a block declared in another node (rpm-regmap). This indirection allows +the usual address mapping to be performed, and for address sharing with +another driver. + +Signed-off-by: Phil Elwell +--- + drivers/hwmon/pwm-fan.c | 59 ++++++++++++++++++++++++++++++++++++----- + 1 file changed, 52 insertions(+), 7 deletions(-) + +--- a/drivers/hwmon/pwm-fan.c ++++ b/drivers/hwmon/pwm-fan.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -51,6 +52,9 @@ struct pwm_fan_ctx { + ktime_t sample_start; + struct timer_list rpm_timer; + ++ void __iomem *rpm_regbase; ++ unsigned int rpm_offset; ++ + unsigned int pwm_value; + unsigned int pwm_fan_state; + unsigned int pwm_fan_max_state; +@@ -61,6 +65,10 @@ struct pwm_fan_ctx { + struct hwmon_channel_info fan_channel; + }; + ++static const u32 rpm_reg_channel_config[] = { ++ HWMON_F_INPUT, 0 ++}; ++ + /* This handler assumes self resetting edge triggered interrupt. */ + static irqreturn_t pulse_handler(int irq, void *dev_id) + { +@@ -335,7 +343,10 @@ static int pwm_fan_read(struct device *d + } + return -EOPNOTSUPP; + case hwmon_fan: +- *val = ctx->tachs[channel].rpm; ++ if (ctx->rpm_regbase) ++ *val = (long)readl(ctx->rpm_regbase + ctx->rpm_offset); ++ else ++ *val = ctx->tachs[channel].rpm; + return 0; + + default: +@@ -470,6 +481,7 @@ static void pwm_fan_cleanup(void *__ctx) + /* Switch off everything */ + ctx->enable_mode = pwm_disable_reg_disable; + pwm_fan_power_off(ctx); ++ iounmap(ctx->rpm_regbase); + } + + static int pwm_fan_probe(struct platform_device *pdev) +@@ -534,10 +546,23 @@ static int pwm_fan_probe(struct platform + return ret; + + ctx->tach_count = platform_irq_count(pdev); ++ if (ctx->tach_count == 0) { ++ struct device_node *rpm_node; ++ ++ rpm_node = of_parse_phandle(dev->of_node, "rpm-regmap", 0); ++ if (rpm_node) ++ ctx->rpm_regbase = of_iomap(rpm_node, 0); ++ } ++ + if (ctx->tach_count < 0) + return dev_err_probe(dev, ctx->tach_count, + "Could not get number of fan tachometer inputs\n"); +- dev_dbg(dev, "%d fan tachometer inputs\n", ctx->tach_count); ++ if (IS_ERR(ctx->rpm_regbase)) ++ return dev_err_probe(dev, PTR_ERR(ctx->rpm_regbase), ++ "Could not get rpm reg\n"); ++ ++ dev_dbg(dev, "%d fan tachometer inputs, %d rpm regmap\n", ctx->tach_count, ++ !!ctx->rpm_regbase); + + if (ctx->tach_count) { + channel_count++; /* We also have a FAN channel. */ +@@ -554,12 +579,24 @@ static int pwm_fan_probe(struct platform + if (!fan_channel_config) + return -ENOMEM; + ctx->fan_channel.config = fan_channel_config; ++ } else if (ctx->rpm_regbase) { ++ channel_count++; /* We also have a FAN channel. */ ++ ctx->fan_channel.type = hwmon_fan; ++ ctx->fan_channel.config = rpm_reg_channel_config; ++ ++ if (of_property_read_u32(pdev->dev.of_node, "rpm-offset", &ctx->rpm_offset)) { ++ dev_err(&pdev->dev, "unable to read 'rpm-offset'"); ++ ret = -EINVAL; ++ goto error; ++ } + } + + channels = devm_kcalloc(dev, channel_count + 1, + sizeof(struct hwmon_channel_info *), GFP_KERNEL); +- if (!channels) +- return -ENOMEM; ++ if (!channels) { ++ ret = -ENOMEM; ++ goto error; ++ } + + channels[0] = HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE); + +@@ -602,6 +639,8 @@ static int pwm_fan_probe(struct platform + mod_timer(&ctx->rpm_timer, jiffies + HZ); + + channels[1] = &ctx->fan_channel; ++ } else if (ctx->rpm_regbase) { ++ channels[1] = &ctx->fan_channel; + } + + ctx->info.ops = &pwm_fan_hwmon_ops; +@@ -611,12 +650,13 @@ static int pwm_fan_probe(struct platform + ctx, &ctx->info, NULL); + if (IS_ERR(hwmon)) { + dev_err(dev, "Failed to register hwmon device\n"); +- return PTR_ERR(hwmon); ++ ret = PTR_ERR(hwmon); ++ goto error; + } + + ret = pwm_fan_of_get_cooling_data(dev, ctx); + if (ret) +- return ret; ++ goto error; + + ctx->pwm_fan_state = ctx->pwm_fan_max_state; + if (IS_ENABLED(CONFIG_THERMAL)) { +@@ -627,12 +667,17 @@ static int pwm_fan_probe(struct platform + dev_err(dev, + "Failed to register pwm-fan as cooling device: %d\n", + ret); +- return ret; ++ goto error; + } + ctx->cdev = cdev; + } + + return 0; ++ ++error: ++ if (ctx->rpm_regbase) ++ iounmap(ctx->rpm_regbase); ++ return ret; + } + + static void pwm_fan_shutdown(struct platform_device *pdev) diff --git a/target/linux/bcm27xx/patches-6.1/950-0923-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch b/target/linux/bcm27xx/patches-6.1/950-0923-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch new file mode 100644 index 0000000000..2972c57fd7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0923-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch @@ -0,0 +1,63 @@ +From 07419175fdb507be2c9d3aaf4b7d18306a336348 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 2 Aug 2023 11:38:03 +0100 +Subject: [PATCH] dt-bindings: input: Add bindings for raspberrypi-button + +Add bindings for the firmware-based button driver. + +Signed-off-by: Phil Elwell +--- + .../input/raspberrypi,firmware-button.yaml | 47 +++++++++++++++++++ + 1 file changed, 47 insertions(+) + create mode 100644 Documentation/devicetree/bindings/input/raspberrypi,firmware-button.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/input/raspberrypi,firmware-button.yaml +@@ -0,0 +1,47 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/input/raspberrypi,firmware-button.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Raspberry Pi firmware buttons ++ ++maintainers: ++ - Phil Elwell ++ ++description: > ++ The Raspberry Pi 5 firmware exposes the state of the power button. The ++ raspberrypi-button driver generates a keycode when it is pressed. ++ ++properties: ++ compatible: ++ enum: ++ - raspberrypi,firmware-button ++ ++ id: ++ description: A numeric identifier of the button ++ ++ label: ++ description: Descriptive name of the button. ++ ++ linux,code: ++ description: Key code to emit. ++ ++required: ++ - compatible ++ - linux,code ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ ++ pwr_button: pwr_button { ++ compatible = "raspberrypi,firmware-button"; ++ id = ; ++ label = "pwr_button"; ++ linux,code = <116>; // KEY_POWER ++ }; ++ ++... diff --git a/target/linux/bcm27xx/patches-6.1/950-0924-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch b/target/linux/bcm27xx/patches-6.1/950-0924-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch new file mode 100644 index 0000000000..e8fea23ce8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0924-dt-bindings-input-Add-bindings-for-raspberrypi-butto.patch @@ -0,0 +1,27 @@ +From 93c8947bc7813b49fe27a5251eef97c6df1e14c6 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 2 Aug 2023 15:01:29 +0100 +Subject: [PATCH] dt-bindings: input: Add bindings for raspberrypi-button + +Add bindings for the firmware-based button driver. + +Signed-off-by: Phil Elwell +--- + include/dt-bindings/input/raspberrypi-button.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + create mode 100644 include/dt-bindings/input/raspberrypi-button.h + +--- /dev/null ++++ b/include/dt-bindings/input/raspberrypi-button.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ ++/* ++ * This header provides constants the raspberrypi-button driver. ++ */ ++ ++#ifndef _DT_BINDINGS_RASPBERRYPI_BUTTON_H ++#define _DT_BINDINGS_RASPBERRYPI_BUTTON_H ++ ++#define RASPBERRYPI_BUTTON_POWER 0 ++ ++#endif diff --git a/target/linux/bcm27xx/patches-6.1/950-0925-Input-Add-raspberrypi-button-firmware-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0925-Input-Add-raspberrypi-button-firmware-driver.patch new file mode 100644 index 0000000000..76a9261a68 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0925-Input-Add-raspberrypi-button-firmware-driver.patch @@ -0,0 +1,197 @@ +From 7c0d40384b0648030d5202114d90239b8db7d4e0 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 2 Aug 2023 11:30:48 +0100 +Subject: [PATCH] Input: Add raspberrypi-button firmware driver + +Raspberry Pi 5s have a power/suspend button that is only accessible to +the firmware. Add a driver to read it and generate key events. + +Signed-off-by: Phil Elwell +--- + drivers/input/misc/Kconfig | 10 ++ + drivers/input/misc/Makefile | 1 + + drivers/input/misc/raspberrypi-button.c | 138 +++++++++++++++++++++ + include/soc/bcm2835/raspberrypi-firmware.h | 1 + + 4 files changed, 150 insertions(+) + create mode 100644 drivers/input/misc/raspberrypi-button.c + +--- a/drivers/input/misc/Kconfig ++++ b/drivers/input/misc/Kconfig +@@ -918,6 +918,16 @@ config INPUT_RT5120_PWRKEY + To compile this driver as a module, choose M here. the module will + be called rt5120-pwrkey. + ++config INPUT_RASPBERRYPI_BUTTON ++ tristate "Raspberry Pi button support" ++ depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE) ++ help ++ This enables support for firmware-controlled buttons on Raspberry ++ Pi devices. ++ ++ To compile this driver as a module, choose M here. the module will ++ be called raspberrypi-button. ++ + config INPUT_STPMIC1_ONKEY + tristate "STPMIC1 PMIC Onkey support" + depends on MFD_STPMIC1 +--- a/drivers/input/misc/Makefile ++++ b/drivers/input/misc/Makefile +@@ -70,6 +70,7 @@ obj-$(CONFIG_INPUT_RAVE_SP_PWRBUTTON) += + obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o + obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o + obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o ++obj-$(CONFIG_INPUT_RASPBERRYPI_BUTTON) += raspberrypi-button.o + obj-$(CONFIG_INPUT_RT5120_PWRKEY) += rt5120-pwrkey.o + obj-$(CONFIG_INPUT_AXP20X_PEK) += axp20x-pek.o + obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o +--- /dev/null ++++ b/drivers/input/misc/raspberrypi-button.c +@@ -0,0 +1,138 @@ ++// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 ++/* ++ * Driver for Raspberry Pi power button ++ * ++ * Copyright (C) 2023 Raspberry Pi Ltd. ++ * ++ * This driver is based on drivers/hwmon/raspberrypi-hwmon.c and ++ * input/misc/pm8941-pwrkey.c/ - see original files for copyright information ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct rpi_button { ++ struct device *dev; ++ struct rpi_firmware *fw; ++ struct input_dev *input; ++ struct delayed_work poll_work; ++ unsigned long poll_rate; ++ const char *name; ++ u32 id; ++ u32 code; ++}; ++ ++static void button_poll(struct work_struct *work) ++{ ++ struct rpi_button *button; ++ u32 value; ++ int err; ++ ++ button = container_of(work, struct rpi_button, ++ poll_work.work); ++ ++ value = BIT(button->id); ++ err = rpi_firmware_property(button->fw, RPI_FIRMWARE_GET_BUTTONS_PRESSED, ++ &value, sizeof(value)); ++ if (err) { ++ dev_err_once(button->dev, "GET_BUTTON_PRESSED not implemented?\n"); ++ return; ++ } ++ ++ if (value & BIT(button->id)) { ++ input_event(button->input, EV_KEY, button->code, 1); ++ input_sync(button->input); ++ input_event(button->input, EV_KEY, button->code, 0); ++ input_sync(button->input); ++ } ++ ++ schedule_delayed_work(&button->poll_work, button->poll_rate); ++} ++ ++static int rpi_button_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rpi_button *button; ++ int err; ++ ++ button = devm_kzalloc(dev, sizeof(*button), GFP_KERNEL); ++ if (!button) ++ return -ENOMEM; ++ ++ button->dev = dev; ++ ++ /* Get the firmware pointer from our parent */ ++ button->fw = dev_get_drvdata(dev->parent); ++ ++ if (device_property_read_u32(dev, "id", &button->id)) ++ button->id = RASPBERRYPI_BUTTON_POWER; ++ ++ if (device_property_read_string(dev, "label", &button->name)) ++ button->name = "raspberrypi-button"; ++ ++ if (device_property_read_u32(dev, "linux,code", &button->code)) { ++ dev_err(&pdev->dev, "no linux,code property\n"); ++ return -EINVAL; ++ } ++ ++ button->input = devm_input_allocate_device(dev); ++ if (!button->input) { ++ dev_dbg(&pdev->dev, "unable to allocate input device\n"); ++ return -ENOMEM; ++ } ++ ++ input_set_capability(button->input, EV_KEY, button->code); ++ ++ button->input->name = button->name; ++ button->input->phys = "raspberrypi-button/input0"; ++ button->input->dev.parent = dev; ++ button->poll_rate = HZ; ++ ++ err = input_register_device(button->input); ++ if (err) { ++ dev_err(&pdev->dev, "failed to register input device: %d\n", ++ err); ++ return err; ++ } ++ ++ err = devm_delayed_work_autocancel(dev, &button->poll_work, ++ button_poll); ++ if (err) ++ return err; ++ ++ platform_set_drvdata(pdev, button); ++ schedule_delayed_work(&button->poll_work, button->poll_rate); ++ ++ return 0; ++} ++ ++static const struct of_device_id rpi_button_match[] = { ++ { .compatible = "raspberrypi,firmware-button", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, rpi_button_match); ++ ++static struct platform_driver rpi_button_driver = { ++ .probe = rpi_button_probe, ++ .driver = { ++ .name = "raspberrypi-button", ++ .of_match_table = of_match_ptr(rpi_button_match), ++ }, ++}; ++module_platform_driver(rpi_button_driver); ++ ++MODULE_AUTHOR("Phil Elwell "); ++MODULE_DESCRIPTION("Raspberry Pi button driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -98,6 +98,7 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_GET_REBOOT_FLAGS = 0x00030064, + RPI_FIRMWARE_SET_REBOOT_FLAGS = 0x00038064, + RPI_FIRMWARE_NOTIFY_DISPLAY_DONE = 0x00030066, ++ RPI_FIRMWARE_GET_BUTTONS_PRESSED = 0x00030088, + + /* Dispmanx TAGS */ + RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, diff --git a/target/linux/bcm27xx/patches-6.1/950-0926-dt-bindings-update-rpi-rtc-binding.patch b/target/linux/bcm27xx/patches-6.1/950-0926-dt-bindings-update-rpi-rtc-binding.patch new file mode 100644 index 0000000000..ffc5cc1a9d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0926-dt-bindings-update-rpi-rtc-binding.patch @@ -0,0 +1,29 @@ +From a7a3679a148e40879f1ce77580d9edf64cb5b51c Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 18 Sep 2023 16:33:06 +0100 +Subject: [PATCH] dt: bindings: update rpi-rtc binding + +Add property for bcm2712 firmware RTC driver charger control + +Signed-off-by: Jonathan Bell +--- + Documentation/devicetree/bindings/rtc/rtc-rpi.txt | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/Documentation/devicetree/bindings/rtc/rtc-rpi.txt ++++ b/Documentation/devicetree/bindings/rtc/rtc-rpi.txt +@@ -9,9 +9,14 @@ Required properties: + compatible: should be "raspberrypi,rpi-rtc" + firmware: Reference to the RPi firmware device node. + ++Optional property: ++trickle-charge-microvolt: specify a trickle charge voltage for the backup ++ battery in microvolts. ++ + Example: + + rpi_rtc: rpi_rtc { + compatible = "raspberrypi,rpi-rtc"; + firmware = <&firmware>; ++ trickle-charge-microvolt = <3000000>; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0927-drivers-rtc-rpi-add-battery-charge-circuit-control-a.patch b/target/linux/bcm27xx/patches-6.1/950-0927-drivers-rtc-rpi-add-battery-charge-circuit-control-a.patch new file mode 100644 index 0000000000..dae0a1cbff --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0927-drivers-rtc-rpi-add-battery-charge-circuit-control-a.patch @@ -0,0 +1,153 @@ +From 33b514cb16dbf13395a0becf7442d19676ae4224 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Fri, 15 Sep 2023 17:33:03 +0100 +Subject: [PATCH] drivers: rtc-rpi: add battery charge circuit control and + readback + +Parse devicetree for a charger voltage and apply it. If nonzero and a +valid voltage, the firmware will enable charging, otherwise the charger +circuit is disabled. + +Add sysfs attributes to read back the supported charge voltage range, +the measured battery voltage, and the charger setpoint. + +Signed-off-by: Jonathan Bell +--- + drivers/rtc/rtc-rpi.c | 106 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 103 insertions(+), 3 deletions(-) + +--- a/drivers/rtc/rtc-rpi.c ++++ b/drivers/rtc/rtc-rpi.c +@@ -19,11 +19,22 @@ + struct rpi_rtc_data { + struct rtc_device *rtc; + struct rpi_firmware *fw; ++ u32 bbat_vchg_microvolts; + }; + + #define RPI_FIRMWARE_GET_RTC_REG 0x00030087 + #define RPI_FIRMWARE_SET_RTC_REG 0x00038087 +-enum {RTC_TIME, RTC_ALARM, RTC_ALARM_PENDING, RTC_ALARM_ENABLE}; ++ ++enum { ++ RTC_TIME, ++ RTC_ALARM, ++ RTC_ALARM_PENDING, ++ RTC_ALARM_ENABLE, ++ RTC_BBAT_CHG_VOLTS, ++ RTC_BBAT_CHG_VOLTS_MIN, ++ RTC_BBAT_CHG_VOLTS_MAX, ++ RTC_BBAT_VOLTS ++}; + + static int rpi_rtc_read_time(struct device *dev, struct rtc_time *tm) + { +@@ -114,6 +125,83 @@ static const struct rtc_class_ops rpi_rt + .alarm_irq_enable = rpi_rtc_alarm_irq_enable, + }; + ++static int rpi_rtc_set_charge_voltage(struct device *dev) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev); ++ u32 data[2] = {RTC_BBAT_CHG_VOLTS, vrtc->bbat_vchg_microvolts}; ++ int err; ++ ++ err = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_SET_RTC_REG, ++ &data, sizeof(data)); ++ ++ if (err) ++ dev_err(dev, "failed to set trickle charge voltage to %uuV: %d\n", ++ vrtc->bbat_vchg_microvolts, err); ++ else if (vrtc->bbat_vchg_microvolts) ++ dev_info(dev, "trickle charging enabled at %uuV\n", ++ vrtc->bbat_vchg_microvolts); ++ ++ return err; ++} ++ ++static ssize_t rpi_rtc_print_uint_reg(struct device *dev, char *buf, u32 reg) ++{ ++ struct rpi_rtc_data *vrtc = dev_get_drvdata(dev->parent); ++ u32 data[2] = {reg, 0}; ++ int ret = 0; ++ ++ ret = rpi_firmware_property(vrtc->fw, RPI_FIRMWARE_GET_RTC_REG, ++ &data, sizeof(data)); ++ if (ret < 0) ++ return ret; ++ ++ return sprintf(buf, "%u\n", data[1]); ++} ++ ++static ssize_t charging_voltage_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return rpi_rtc_print_uint_reg(dev, buf, RTC_BBAT_CHG_VOLTS); ++} ++static DEVICE_ATTR_RO(charging_voltage); ++ ++static ssize_t charging_voltage_min_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return rpi_rtc_print_uint_reg(dev, buf, RTC_BBAT_CHG_VOLTS_MIN); ++} ++static DEVICE_ATTR_RO(charging_voltage_min); ++ ++static ssize_t charging_voltage_max_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return rpi_rtc_print_uint_reg(dev, buf, RTC_BBAT_CHG_VOLTS_MAX); ++} ++static DEVICE_ATTR_RO(charging_voltage_max); ++ ++static ssize_t battery_voltage_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return rpi_rtc_print_uint_reg(dev, buf, RTC_BBAT_VOLTS); ++} ++static DEVICE_ATTR_RO(battery_voltage); ++ ++static struct attribute *rpi_rtc_attrs[] = { ++ &dev_attr_charging_voltage.attr, ++ &dev_attr_charging_voltage_min.attr, ++ &dev_attr_charging_voltage_max.attr, ++ &dev_attr_battery_voltage.attr, ++ NULL ++}; ++ ++static const struct attribute_group rpi_rtc_sysfs_files = { ++ .attrs = rpi_rtc_attrs, ++}; ++ + static int rpi_rtc_probe(struct platform_device *pdev) + { + struct rpi_rtc_data *vrtc; +@@ -151,10 +239,22 @@ static int rpi_rtc_probe(struct platform + clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, vrtc->rtc->features); + + vrtc->rtc->ops = &rpi_rtc_ops; +- ret = devm_rtc_register_device(vrtc->rtc); ++ ret = rtc_add_group(vrtc->rtc, &rpi_rtc_sysfs_files); ++ if (ret) ++ return ret; + + rpi_rtc_alarm_clear_pending(dev); +- return ret; ++ ++ /* ++ * Optionally enable trickle charging - if the property isn't ++ * present (or set to zero), trickle charging is disabled. ++ */ ++ of_property_read_u32(np, "trickle-charge-microvolt", ++ &vrtc->bbat_vchg_microvolts); ++ ++ rpi_rtc_set_charge_voltage(dev); ++ ++ return devm_rtc_register_device(vrtc->rtc); + } + + static const struct of_device_id rpi_rtc_dt_match[] = { diff --git a/target/linux/bcm27xx/patches-6.1/950-0928-vc4_drv-Avoid-panic-when-booted-with-no-kms.patch b/target/linux/bcm27xx/patches-6.1/950-0928-vc4_drv-Avoid-panic-when-booted-with-no-kms.patch new file mode 100644 index 0000000000..8aae09c81a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0928-vc4_drv-Avoid-panic-when-booted-with-no-kms.patch @@ -0,0 +1,29 @@ +From 0f5fd4538774aa6c936bb8fc78611c3113bf19d7 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Mon, 17 Apr 2023 15:21:41 +0100 +Subject: [PATCH] vc4_drv: Avoid panic when booted with no kms + +If kms/fkms overlay is not present we have no matching drivers +and so match is NULL. + +It is not safe to call component_master_add_with_match with a null match argument. + +So don't do that + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_drv.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -456,6 +456,9 @@ static int vc4_platform_drm_probe(struct + vc4_match_add_drivers(dev, &match, + component_drivers, ARRAY_SIZE(component_drivers)); + ++ if (!match) ++ return -ENODEV; ++ + return component_master_add_with_match(dev, &vc4_drm_ops, match); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-0929-drm-vc4-Treat-zero-sized-destination-as-full-screen.patch b/target/linux/bcm27xx/patches-6.1/950-0929-drm-vc4-Treat-zero-sized-destination-as-full-screen.patch new file mode 100644 index 0000000000..70a11df293 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0929-drm-vc4-Treat-zero-sized-destination-as-full-screen.patch @@ -0,0 +1,28 @@ +From 2c987545a88507acdd8a572a3bd23a4ca0124d14 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Thu, 13 Apr 2023 17:41:11 +0100 +Subject: [PATCH] drm/vc4: Treat zero sized destination as full screen + +Kodi video planes come through with all zeros for fullscreen +Without this check, we WARN when writing width-1, height-1 +to destination dlist + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_plane.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -484,6 +484,11 @@ static int vc4_plane_setup_clipping_and_ + vc4_state->crtc_w = state->dst.x2 - state->dst.x1; + vc4_state->crtc_h = state->dst.y2 - state->dst.y1; + ++ if (!vc4_state->crtc_w) ++ vc4_state->crtc_w = state->crtc->mode.hdisplay; ++ if (!vc4_state->crtc_h) ++ vc4_state->crtc_h = state->crtc->mode.vdisplay; ++ + ret = vc4_plane_margins_adj(state); + if (ret) + return ret; diff --git a/target/linux/bcm27xx/patches-6.1/950-0930-drm-vc4-Fix-FKMS-for-when-the-YUV-chroma-planes-are-.patch b/target/linux/bcm27xx/patches-6.1/950-0930-drm-vc4-Fix-FKMS-for-when-the-YUV-chroma-planes-are-.patch new file mode 100644 index 0000000000..9182194403 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0930-drm-vc4-Fix-FKMS-for-when-the-YUV-chroma-planes-are-.patch @@ -0,0 +1,50 @@ +From bb1ee75de382c7a5218750476aa2a5792309cc70 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 30 Mar 2023 17:18:36 +0100 +Subject: [PATCH] drm/vc4: Fix FKMS for when the YUV chroma planes are + different buffers + +The code was assuming that it was a single buffer with offsets, +when kmstest uses separate buffers and 0 offsets for each plane. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_firmware_kms.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c +@@ -528,7 +528,7 @@ static int vc4_plane_to_mb(struct drm_pl + struct drm_plane_state *state) + { + struct drm_framebuffer *fb = state->fb; +- struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); ++ struct drm_gem_dma_object *bo; + const struct drm_format_info *drm_fmt = fb->format; + const struct vc_image_format *vc_fmt = + vc4_get_vc_image_fmt(drm_fmt->format); +@@ -552,6 +552,7 @@ static int vc4_plane_to_mb(struct drm_pl + state->normalized_zpos : -127; + mb->plane.num_planes = num_planes; + mb->plane.is_vu = vc_fmt->is_vu; ++ bo = drm_fb_dma_get_gem_obj(fb, 0); + mb->plane.planes[0] = bo->dma_addr + fb->offsets[0]; + + rotation = drm_rotation_simplify(state->rotation, +@@ -572,11 +573,14 @@ static int vc4_plane_to_mb(struct drm_pl + /* Makes assumptions on the stride for the chroma planes as we + * can't easily plumb in non-standard pitches. + */ ++ bo = drm_fb_dma_get_gem_obj(fb, 1); + mb->plane.planes[1] = bo->dma_addr + fb->offsets[1]; +- if (num_planes > 2) ++ if (num_planes > 2) { ++ bo = drm_fb_dma_get_gem_obj(fb, 2); + mb->plane.planes[2] = bo->dma_addr + fb->offsets[2]; +- else ++ } else { + mb->plane.planes[2] = 0; ++ } + + /* Special case the YUV420 with U and V as line interleaved + * planes as we have special handling for that case. diff --git a/target/linux/bcm27xx/patches-6.1/950-0931-drm-vc4-hdmi-Enable-the-audio-clock.patch b/target/linux/bcm27xx/patches-6.1/950-0931-drm-vc4-hdmi-Enable-the-audio-clock.patch new file mode 100644 index 0000000000..f228dca9d5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0931-drm-vc4-hdmi-Enable-the-audio-clock.patch @@ -0,0 +1,39 @@ +From 0da58dfbd2cc2cfa14a629787b9ba6fa10b5f666 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Wed, 29 Mar 2023 15:26:52 +0100 +Subject: [PATCH] drm/vc4: hdmi: Enable the audio clock + +The audio clock is used by the HDMI controller driver and we were using +it to get its audio rate and compute the dividers needed to reach a +given audio sample rate. + +However, we were never enabling it, which was resulting in lockups on +the BCM2712. + +Fixes: 632ee3aa8786 ("drm/vc4: hdmi: Add audio-related callbacks") +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -3625,6 +3625,7 @@ static int vc4_hdmi_runtime_suspend(stru + { + struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); + ++ clk_disable_unprepare(vc4_hdmi->audio_clock); + clk_disable_unprepare(vc4_hdmi->hsm_rpm_clock); + + return 0; +@@ -3666,6 +3667,10 @@ static int vc4_hdmi_runtime_resume(struc + goto err_disable_clk; + } + ++ ret = clk_prepare_enable(vc4_hdmi->audio_clock); ++ if (ret) ++ goto err_disable_clk; ++ + if (vc4_hdmi->variant->reset) + vc4_hdmi->variant->reset(vc4_hdmi); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0932-drm-vc4-hdmi-Warn-if-writing-to-an-unknown-HDMI-regi.patch b/target/linux/bcm27xx/patches-6.1/950-0932-drm-vc4-hdmi-Warn-if-writing-to-an-unknown-HDMI-regi.patch new file mode 100644 index 0000000000..fa6a399dae --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0932-drm-vc4-hdmi-Warn-if-writing-to-an-unknown-HDMI-regi.patch @@ -0,0 +1,31 @@ +From cdbebb3a92aca7327c88c6dc6ef5d4cd470d49fc Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 23 Feb 2023 19:44:32 +0100 +Subject: [PATCH] drm/vc4: hdmi: Warn if writing to an unknown HDMI register + +The VC4 HDMI driver has a bunch of accessors to read from a register. +The read accessor was warning when accessing an unknown register, but +the write one was just returning silently. + +Let's make sure we warn also when writing to an unknown register. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +@@ -498,8 +498,11 @@ static inline void vc4_hdmi_write(struct + + field = &variant->registers[reg]; + base = __vc4_hdmi_get_field_base(hdmi, field->reg); +- if (!base) ++ if (!base) { ++ dev_warn(&hdmi->pdev->dev, ++ "Unknown register ID %u\n", reg); + return; ++ } + + writel(value, base + field->offset); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0933-drm-vc4-hvs-More-logging-for-dlist-generation.patch b/target/linux/bcm27xx/patches-6.1/950-0933-drm-vc4-hvs-More-logging-for-dlist-generation.patch new file mode 100644 index 0000000000..dee2fc0d66 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0933-drm-vc4-hvs-More-logging-for-dlist-generation.patch @@ -0,0 +1,41 @@ +From 4ebd8283403daf5507e5aafb42fe3e4c7612eb14 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Wed, 22 Mar 2023 09:51:51 +0100 +Subject: [PATCH] drm/vc4: hvs: More logging for dlist generation + +DLIST generation can get pretty tricky and there's not a lot of debug in +the driver to help. Let's add a few more to track the generated DLIST +size. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -826,11 +826,22 @@ int vc4_hvs_atomic_check(struct drm_crtc + if (hweight32(crtc_state->connector_mask) > 1) + return -EINVAL; + +- drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) +- dlist_count += vc4_plane_dlist_size(plane_state); ++ drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) { ++ u32 plane_dlist_count = vc4_plane_dlist_size(plane_state); ++ ++ drm_dbg_driver(dev, "[CRTC:%d:%s] Found [PLANE:%d:%s] with DLIST size: %u\n", ++ crtc->base.id, crtc->name, ++ plane->base.id, plane->name, ++ plane_dlist_count); ++ ++ dlist_count += plane_dlist_count; ++ } + + dlist_count++; /* Account for SCALER_CTL0_END. */ + ++ drm_dbg_driver(dev, "[CRTC:%d:%s] Allocating DLIST block with size: %u\n", ++ crtc->base.id, crtc->name, dlist_count); ++ + alloc = vc4_hvs_alloc_dlist_entry(vc4->hvs, vc4_state->assigned_channel, dlist_count); + if (IS_ERR(alloc)) + return PTR_ERR(alloc); diff --git a/target/linux/bcm27xx/patches-6.1/950-0934-drm-vc4-hvs-Print-error-if-we-fail-an-allocation.patch b/target/linux/bcm27xx/patches-6.1/950-0934-drm-vc4-hvs-Print-error-if-we-fail-an-allocation.patch new file mode 100644 index 0000000000..7c7bbb4822 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0934-drm-vc4-hvs-Print-error-if-we-fail-an-allocation.patch @@ -0,0 +1,66 @@ +From c0af63193bd307f281211e7fb32a02a52c2869b2 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Wed, 22 Mar 2023 09:53:17 +0100 +Subject: [PATCH] drm/vc4: hvs: Print error if we fail an allocation + +We need to allocate a few additional structures when checking our +atomic_state, especially related to hardware SRAM that will hold the +plane descriptors (DLIST) and the current line context (LBM) during +composition. + +Since those allocation can fail, let's add some error message in that +case to help debug what goes wrong. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 6 +++++- + drivers/gpu/drm/vc4/vc4_plane.c | 7 +++++-- + 2 files changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -441,6 +441,8 @@ vc4_hvs_alloc_dlist_entry(struct vc4_hvs + unsigned int channel, + size_t dlist_count) + { ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *dev = &vc4->base; + struct vc4_hvs_dlist_allocation *alloc; + unsigned long flags; + int ret; +@@ -458,8 +460,10 @@ vc4_hvs_alloc_dlist_entry(struct vc4_hvs + ret = drm_mm_insert_node(&hvs->dlist_mm, &alloc->mm_node, + dlist_count); + spin_unlock_irqrestore(&hvs->mm_lock, flags); +- if (ret) ++ if (ret) { ++ drm_err(dev, "Failed to allocate DLIST entry: %d\n", ret); + return ERR_PTR(ret); ++ } + + alloc->channel = channel; + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -733,7 +733,8 @@ static void vc4_plane_calc_load(struct d + + static int vc4_plane_allocate_lbm(struct drm_plane_state *state) + { +- struct vc4_dev *vc4 = to_vc4_dev(state->plane->dev); ++ struct drm_device *drm = state->plane->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + unsigned long irqflags; + u32 lbm_size; +@@ -759,8 +760,10 @@ static int vc4_plane_allocate_lbm(struct + 0, 0); + spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); + +- if (ret) ++ if (ret) { ++ drm_err(drm, "Failed to allocate LBM entry: %d\n", ret); + return ret; ++ } + } else { + WARN_ON_ONCE(lbm_size != vc4_state->lbm.size); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0935-drm-vc4-plane-Add-more-debugging-for-LBM-allocation.patch b/target/linux/bcm27xx/patches-6.1/950-0935-drm-vc4-plane-Add-more-debugging-for-LBM-allocation.patch new file mode 100644 index 0000000000..d8d68e79aa --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0935-drm-vc4-plane-Add-more-debugging-for-LBM-allocation.patch @@ -0,0 +1,36 @@ +From 164f7e94da446984f275be1c082b93243beadfba Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Wed, 22 Mar 2023 16:17:57 +0100 +Subject: [PATCH] drm/vc4: plane: Add more debugging for LBM allocation + +LBM allocations need a different size depending on the line length, +format, etc. + +This can get tricky, and fail. Let's add some more prints to ease the +debugging when it does. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_plane.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -735,6 +735,7 @@ static int vc4_plane_allocate_lbm(struct + { + struct drm_device *drm = state->plane->dev; + struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct drm_plane *plane = state->plane; + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + unsigned long irqflags; + u32 lbm_size; +@@ -743,6 +744,9 @@ static int vc4_plane_allocate_lbm(struct + if (!lbm_size) + return 0; + ++ drm_dbg_driver(drm, "[PLANE:%d:%s] LBM Allocation Size: %u\n", ++ plane->base.id, plane->name, lbm_size); ++ + if (WARN_ON(!vc4_state->lbm_offset)) + return -EINVAL; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0936-drm-vc4-plane-Use-return-variable-in-atomic_check.patch b/target/linux/bcm27xx/patches-6.1/950-0936-drm-vc4-plane-Use-return-variable-in-atomic_check.patch new file mode 100644 index 0000000000..220245c351 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0936-drm-vc4-plane-Use-return-variable-in-atomic_check.patch @@ -0,0 +1,31 @@ +From 950394a39f659746e5933cbc203a8bedef8246b7 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 14:26:44 +0100 +Subject: [PATCH] drm/vc4: plane: Use return variable in atomic_check + +The vc4_plane_atomic_check() directly returns the result of the final +function it calls. + +Using the already defined ret variable to check its content on error, +and a separate return 0 on success, makes it easier to extend. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_plane.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -1378,7 +1378,11 @@ static int vc4_plane_atomic_check(struct + if (ret) + return ret; + +- return vc4_plane_allocate_lbm(new_plane_state); ++ ret = vc4_plane_allocate_lbm(new_plane_state); ++ if (ret) ++ return ret; ++ ++ return 0; + } + + static void vc4_plane_atomic_update(struct drm_plane *plane, diff --git a/target/linux/bcm27xx/patches-6.1/950-0937-drm-vc4-crtc-Move-assigned_channel-to-a-variable.patch b/target/linux/bcm27xx/patches-6.1/950-0937-drm-vc4-crtc-Move-assigned_channel-to-a-variable.patch new file mode 100644 index 0000000000..3476f548c4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0937-drm-vc4-crtc-Move-assigned_channel-to-a-variable.patch @@ -0,0 +1,47 @@ +From f3c6acc345113c57011f2b1c8421e6cf78f0bc30 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:39:13 +0100 +Subject: [PATCH] drm/vc4: crtc: Move assigned_channel to a variable + +We access multiple times the vc4_crtc_state->assigned_channel variable +in the vc4_crtc_get_scanout_position() function, so let's store it in a +local variable. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -104,6 +104,7 @@ static bool vc4_crtc_get_scanout_positio + struct vc4_hvs *hvs = vc4->hvs; + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state); ++ unsigned int channel = vc4_crtc_state->assigned_channel; + unsigned int cob_size; + u32 val; + int fifo_lines; +@@ -120,7 +121,7 @@ static bool vc4_crtc_get_scanout_positio + * Read vertical scanline which is currently composed for our + * pixelvalve by the HVS, and also the scaler status. + */ +- val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel)); ++ val = HVS_READ(SCALER_DISPSTATX(channel)); + + /* Get optional system timestamp after query. */ + if (etime) +@@ -136,11 +137,11 @@ static bool vc4_crtc_get_scanout_positio + *vpos /= 2; + + /* Use hpos to correct for field offset in interlaced mode. */ +- if (vc4_hvs_get_fifo_frame_count(hvs, vc4_crtc_state->assigned_channel) % 2) ++ if (vc4_hvs_get_fifo_frame_count(hvs, channel) % 2) + *hpos += mode->crtc_htotal / 2; + } + +- cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel); ++ cob_size = vc4_crtc_get_cob_allocation(vc4, channel); + /* This is the offset we need for translating hvs -> pv scanout pos. */ + fifo_lines = cob_size / mode->crtc_hdisplay; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0938-drm-vc4-Introduce-generation-number-enum.patch b/target/linux/bcm27xx/patches-6.1/950-0938-drm-vc4-Introduce-generation-number-enum.patch new file mode 100644 index 0000000000..9314c797a0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0938-drm-vc4-Introduce-generation-number-enum.patch @@ -0,0 +1,1029 @@ +From fa2571d625bb53b642cd9f29a7cfc3434e1cf576 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:07:36 +0100 +Subject: [PATCH] drm/vc4: Introduce generation number enum + +With the introduction of the BCM2712 support, we will get yet another +generation of display engine to support. + +The binary check of whether it's VC5 or not thus doesn't work anymore, +especially since some parts of the driver will have changed with BCM2711, +and some others with BCM2712. + +Let's introduce an enum to store the generation the driver is running +on, which should provide more flexibility. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 12 +++--- + drivers/gpu/drm/vc4/vc4_bo.c | 28 ++++++------ + drivers/gpu/drm/vc4/vc4_crtc.c | 14 +++--- + drivers/gpu/drm/vc4/vc4_drv.c | 22 ++++++---- + drivers/gpu/drm/vc4/vc4_drv.h | 7 ++- + drivers/gpu/drm/vc4/vc4_gem.c | 24 +++++------ + drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- + drivers/gpu/drm/vc4/vc4_hvs.c | 50 ++++++++++++---------- + drivers/gpu/drm/vc4/vc4_irq.c | 10 ++--- + drivers/gpu/drm/vc4/vc4_kms.c | 14 +++--- + drivers/gpu/drm/vc4/vc4_perfmon.c | 20 ++++----- + drivers/gpu/drm/vc4/vc4_plane.c | 12 +++--- + drivers/gpu/drm/vc4/vc4_render_cl.c | 2 +- + drivers/gpu/drm/vc4/vc4_v3d.c | 10 ++--- + drivers/gpu/drm/vc4/vc4_validate.c | 8 ++-- + drivers/gpu/drm/vc4/vc4_validate_shaders.c | 2 +- + 16 files changed, 126 insertions(+), 111 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -153,11 +153,11 @@ static int __build_mock(struct kunit *te + return 0; + } + +-static struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5) ++static struct vc4_dev *__mock_device(struct kunit *test, enum vc4_gen gen) + { + struct drm_device *drm; +- const struct drm_driver *drv = is_vc5 ? &vc5_drm_driver : &vc4_drm_driver; +- const struct vc4_mock_desc *desc = is_vc5 ? &vc5_mock : &vc4_mock; ++ const struct drm_driver *drv = (gen == VC4_GEN_5) ? &vc5_drm_driver : &vc4_drm_driver; ++ const struct vc4_mock_desc *desc = (gen == VC4_GEN_5) ? &vc5_mock : &vc4_mock; + struct vc4_dev *vc4; + struct device *dev; + int ret; +@@ -171,7 +171,7 @@ static struct vc4_dev *__mock_device(str + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); + + vc4->dev = dev; +- vc4->is_vc5 = is_vc5; ++ vc4->gen = gen; + + vc4->hvs = __vc4_hvs_alloc(vc4, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4->hvs); +@@ -191,10 +191,10 @@ static struct vc4_dev *__mock_device(str + + struct vc4_dev *vc4_mock_device(struct kunit *test) + { +- return __mock_device(test, false); ++ return __mock_device(test, VC4_GEN_4); + } + + struct vc4_dev *vc5_mock_device(struct kunit *test) + { +- return __mock_device(test, true); ++ return __mock_device(test, VC4_GEN_5); + } +--- a/drivers/gpu/drm/vc4/vc4_bo.c ++++ b/drivers/gpu/drm/vc4/vc4_bo.c +@@ -251,7 +251,7 @@ void vc4_bo_add_to_purgeable_pool(struct + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4->purgeable.lock); +@@ -265,7 +265,7 @@ static void vc4_bo_remove_from_purgeable + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* list_del_init() is used here because the caller might release +@@ -396,7 +396,7 @@ struct drm_gem_object *vc4_create_object + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return ERR_PTR(-ENODEV); + + bo = kzalloc(sizeof(*bo), GFP_KERNEL); +@@ -427,7 +427,7 @@ struct vc4_bo *vc4_bo_create(struct drm_ + struct drm_gem_dma_object *dma_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return ERR_PTR(-ENODEV); + + if (size == 0) +@@ -496,7 +496,7 @@ int vc4_bo_dumb_create(struct drm_file * + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + ret = vc4_dumb_fixup_args(args); +@@ -622,7 +622,7 @@ int vc4_bo_inc_usecnt(struct vc4_bo *bo) + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + /* Fast path: if the BO is already retained by someone, no need to +@@ -661,7 +661,7 @@ void vc4_bo_dec_usecnt(struct vc4_bo *bo + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* Fast path: if the BO is still retained by someone, no need to test +@@ -783,7 +783,7 @@ int vc4_create_bo_ioctl(struct drm_devic + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + ret = vc4_grab_bin_bo(vc4, vc4file); +@@ -813,7 +813,7 @@ int vc4_mmap_bo_ioctl(struct drm_device + struct drm_vc4_mmap_bo *args = data; + struct drm_gem_object *gem_obj; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + gem_obj = drm_gem_object_lookup(file_priv, args->handle); +@@ -839,7 +839,7 @@ vc4_create_shader_bo_ioctl(struct drm_de + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->size == 0) +@@ -918,7 +918,7 @@ int vc4_set_tiling_ioctl(struct drm_devi + struct vc4_bo *bo; + bool t_format; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->flags != 0) +@@ -964,7 +964,7 @@ int vc4_get_tiling_ioctl(struct drm_devi + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->flags != 0 || args->modifier != 0) +@@ -1011,7 +1011,7 @@ int vc4_bo_cache_init(struct drm_device + int ret; + int i; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + /* Create the initial set of BO labels that the kernel will +@@ -1075,7 +1075,7 @@ int vc4_label_bo_ioctl(struct drm_device + struct drm_gem_object *gem_obj; + int ret = 0, label; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!args->len) +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -263,7 +263,7 @@ static u32 vc4_get_fifo_full_level(struc + * Removing 1 from the FIFO full level however + * seems to completely remove that issue. + */ +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX - 1; + + return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX; +@@ -445,7 +445,7 @@ static void vc4_crtc_config_pv(struct dr + if (is_dsi) + CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); + +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + CRTC_WRITE(PV_MUX_CFG, + VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP, + PV_MUX_CFG_RGB_PIXEL_MUX_MODE)); +@@ -936,7 +936,7 @@ static int vc4_async_set_fence_cb(struct + struct dma_fence *fence; + int ret; + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); + + return vc4_queue_seqno_cb(dev, &flip_state->cb.seqno, bo->seqno, +@@ -1023,7 +1023,7 @@ static int vc4_async_page_flip(struct dr + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + /* +@@ -1066,7 +1066,7 @@ int vc4_page_flip(struct drm_crtc *crtc, + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + return vc5_async_page_flip(crtc, fb, event, flags); + else + return vc4_async_page_flip(crtc, fb, event, flags); +@@ -1358,13 +1358,13 @@ int __vc4_crtc_init(struct drm_device *d + + drm_crtc_helper_add(crtc, crtc_helper_funcs); + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); + drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); + } + + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + /* We support CTM, but only for one CRTC at a time. It's therefore + * implemented as private driver state in vc4_kms, not here. + */ +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -98,7 +98,7 @@ static int vc4_get_param_ioctl(struct dr + if (args->pad != 0) + return -EINVAL; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) +@@ -147,7 +147,7 @@ static int vc4_open(struct drm_device *d + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_file *vc4file; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + vc4file = kzalloc(sizeof(*vc4file), GFP_KERNEL); +@@ -165,7 +165,7 @@ static void vc4_close(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_file *vc4file = file->driver_priv; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (vc4file->bin_bo_used) +@@ -305,13 +305,17 @@ static int vc4_drm_bind(struct device *d + struct vc4_dev *vc4; + struct device_node *node; + struct drm_crtc *crtc; +- bool is_vc5; ++ enum vc4_gen gen; + int ret = 0; + + dev->coherent_dma_mask = DMA_BIT_MASK(32); + +- is_vc5 = of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5"); +- if (is_vc5) ++ if (of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5")) ++ gen = VC4_GEN_5; ++ else ++ gen = VC4_GEN_4; ++ ++ if (gen == VC4_GEN_5) + driver = &vc5_drm_driver; + else + driver = &vc4_drm_driver; +@@ -329,14 +333,14 @@ static int vc4_drm_bind(struct device *d + vc4 = devm_drm_dev_alloc(dev, driver, struct vc4_dev, base); + if (IS_ERR(vc4)) + return PTR_ERR(vc4); +- vc4->is_vc5 = is_vc5; ++ vc4->gen = gen; + vc4->dev = dev; + + drm = &vc4->base; + platform_set_drvdata(pdev, drm); + INIT_LIST_HEAD(&vc4->debugfs_list); + +- if (!is_vc5) { ++ if (gen == VC4_GEN_4) { + ret = drmm_mutex_init(drm, &vc4->bin_bo_lock); + if (ret) + return ret; +@@ -350,7 +354,7 @@ static int vc4_drm_bind(struct device *d + if (ret) + return ret; + +- if (!is_vc5) { ++ if (gen == VC4_GEN_4) { + ret = vc4_gem_init(drm); + if (ret) + return ret; +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -80,11 +80,16 @@ struct vc4_perfmon { + u64 counters[]; + }; + ++enum vc4_gen { ++ VC4_GEN_4, ++ VC4_GEN_5, ++}; ++ + struct vc4_dev { + struct drm_device base; + struct device *dev; + +- bool is_vc5; ++ enum vc4_gen gen; + + unsigned int irq; + +--- a/drivers/gpu/drm/vc4/vc4_gem.c ++++ b/drivers/gpu/drm/vc4/vc4_gem.c +@@ -76,7 +76,7 @@ vc4_get_hang_state_ioctl(struct drm_devi + u32 i; + int ret = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -389,7 +389,7 @@ vc4_wait_for_seqno(struct drm_device *de + unsigned long timeout_expire; + DEFINE_WAIT(wait); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (vc4->finished_seqno >= seqno) +@@ -474,7 +474,7 @@ vc4_submit_next_bin_job(struct drm_devic + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_exec_info *exec; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + again: +@@ -522,7 +522,7 @@ vc4_submit_next_render_job(struct drm_de + if (!exec) + return; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* A previous RCL may have written to one of our textures, and +@@ -543,7 +543,7 @@ vc4_move_job_to_render(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + bool was_empty = list_empty(&vc4->render_job_list); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + list_move_tail(&exec->head, &vc4->render_job_list); +@@ -1012,7 +1012,7 @@ vc4_job_handle_completed(struct vc4_dev + unsigned long irqflags; + struct vc4_seqno_cb *cb, *cb_temp; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + spin_lock_irqsave(&vc4->job_lock, irqflags); +@@ -1051,7 +1051,7 @@ int vc4_queue_seqno_cb(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + cb->func = func; +@@ -1107,7 +1107,7 @@ vc4_wait_seqno_ioctl(struct drm_device * + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_vc4_wait_seqno *args = data; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + return vc4_wait_for_seqno_ioctl_helper(dev, args->seqno, +@@ -1124,7 +1124,7 @@ vc4_wait_bo_ioctl(struct drm_device *dev + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->pad != 0) +@@ -1173,7 +1173,7 @@ vc4_submit_cl_ioctl(struct drm_device *d + args->shader_rec_size, + args->bo_handle_count); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -1310,7 +1310,7 @@ int vc4_gem_init(struct drm_device *dev) + struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + vc4->dma_fence_context = dma_fence_context_alloc(1); +@@ -1369,7 +1369,7 @@ int vc4_gem_madvise_ioctl(struct drm_dev + struct vc4_bo *bo; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + switch (args->madv) { +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -2614,7 +2614,7 @@ static int vc4_hdmi_audio_prepare(struct + VC4_HDMI_AUDIO_PACKET_CEA_MASK); + + /* Set the MAI threshold */ +- if (vc4->is_vc5) ++ if (vc4->gen >= VC4_GEN_5) + HDMI_WRITE(HDMI_MAI_THR, + VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) | + VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) | +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -416,7 +416,7 @@ static void vc4_hvs_irq_enable_eof(const + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; +- u32 irq_mask = vc4->is_vc5 ? ++ u32 irq_mask = vc4->gen == VC4_GEN_5 ? + SCALER5_DISPCTRL_DSPEIEOF(channel) : + SCALER_DISPCTRL_DSPEIEOF(channel); + +@@ -428,7 +428,7 @@ static void vc4_hvs_irq_clear_eof(const + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; +- u32 irq_mask = vc4->is_vc5 ? ++ u32 irq_mask = vc4->gen == VC4_GEN_5 ? + SCALER5_DISPCTRL_DSPEIEOF(channel) : + SCALER_DISPCTRL_DSPEIEOF(channel); + +@@ -620,7 +620,7 @@ int vc4_hvs_get_fifo_from_output(struct + u32 reg; + int ret; + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + return output; + + /* +@@ -701,7 +701,7 @@ static int vc4_hvs_init_channel(struct v + dispctrl = SCALER_DISPCTRLX_ENABLE; + dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan)); + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + dispctrl |= VC4_SET_FIELD(mode->hdisplay, + SCALER_DISPCTRLX_WIDTH) | + VC4_SET_FIELD(mode->vdisplay, +@@ -732,7 +732,7 @@ static int vc4_hvs_init_channel(struct v + /* Reload the LUT, since the SRAMs would have been disabled if + * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once. + */ +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + vc4_hvs_lut_load(hvs, vc4_crtc); + else + vc5_hvs_lut_load(hvs, vc4_crtc); +@@ -782,7 +782,7 @@ static int vc4_hvs_gamma_check(struct dr + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + return 0; + + if (!crtc_state->color_mgmt_changed) +@@ -1036,7 +1036,7 @@ void vc4_hvs_atomic_flush(struct drm_crt + u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(channel)); + + if (crtc->state->gamma_lut) { +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + vc4_hvs_update_gamma_lut(hvs, vc4_crtc); + dispbkgndx |= SCALER_DISPBKGND_GAMMA; + } else { +@@ -1053,7 +1053,7 @@ void vc4_hvs_atomic_flush(struct drm_crt + * should already be disabling/enabling the pipeline + * when gamma changes. + */ +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + dispbkgndx &= ~SCALER_DISPBKGND_GAMMA; + } + HVS_WRITE(SCALER_DISPBKGNDX(channel), dispbkgndx); +@@ -1069,7 +1069,8 @@ void vc4_hvs_atomic_flush(struct drm_crt + + void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + u32 dispctrl; + int idx; + +@@ -1077,8 +1078,9 @@ void vc4_hvs_mask_underrun(struct vc4_hv + return; + + dispctrl = HVS_READ(SCALER_DISPCTRL); +- dispctrl &= ~(hvs->vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) : +- SCALER_DISPCTRL_DSPEISLUR(channel)); ++ dispctrl &= ~((vc4->gen == VC4_GEN_5) ? ++ SCALER5_DISPCTRL_DSPEISLUR(channel) : ++ SCALER_DISPCTRL_DSPEISLUR(channel)); + + HVS_WRITE(SCALER_DISPCTRL, dispctrl); + +@@ -1087,7 +1089,8 @@ void vc4_hvs_mask_underrun(struct vc4_hv + + void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + u32 dispctrl; + int idx; + +@@ -1095,8 +1098,9 @@ void vc4_hvs_unmask_underrun(struct vc4_ + return; + + dispctrl = HVS_READ(SCALER_DISPCTRL); +- dispctrl |= (hvs->vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) : +- SCALER_DISPCTRL_DSPEISLUR(channel)); ++ dispctrl |= ((vc4->gen == VC4_GEN_5) ? ++ SCALER5_DISPCTRL_DSPEISLUR(channel) : ++ SCALER_DISPCTRL_DSPEISLUR(channel)); + + HVS_WRITE(SCALER_DISPSTAT, + SCALER_DISPSTAT_EUFLOW(channel)); +@@ -1139,8 +1143,10 @@ static irqreturn_t vc4_hvs_irq_handler(i + control = HVS_READ(SCALER_DISPCTRL); + + for (channel = 0; channel < SCALER_CHANNELS_COUNT; channel++) { +- dspeislur = vc4->is_vc5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) : +- SCALER_DISPCTRL_DSPEISLUR(channel); ++ dspeislur = (vc4->gen == VC4_GEN_5) ? ++ SCALER5_DISPCTRL_DSPEISLUR(channel) : ++ SCALER_DISPCTRL_DSPEISLUR(channel); ++ + /* Interrupt masking is not always honored, so check it here. */ + if (status & SCALER_DISPSTAT_EUFLOW(channel) && + control & dspeislur) { +@@ -1177,7 +1183,7 @@ int vc4_hvs_debugfs_init(struct drm_mino + if (!vc4->hvs) + return -ENODEV; + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR, + minor->debugfs_root, + &vc4->load_tracker_enabled); +@@ -1235,7 +1241,7 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + * between planes when they don't overlap on the screen, but + * for now we just allocate globally. + */ +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + /* 48k words of 2x12-bit pixels */ + drm_mm_init(&hvs->lbm_mm, 0, 48 * 1024); + else +@@ -1269,7 +1275,7 @@ static int vc4_hvs_bind(struct device *d + hvs->regset.regs = hvs_regs; + hvs->regset.nregs = ARRAY_SIZE(hvs_regs); + +- if (vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_5) { + struct rpi_firmware *firmware; + struct device_node *node; + unsigned int max_rate; +@@ -1307,7 +1313,7 @@ static int vc4_hvs_bind(struct device *d + } + } + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + hvs->dlist = hvs->regs + SCALER_DLIST_START; + else + hvs->dlist = hvs->regs + SCALER5_DLIST_START; +@@ -1348,7 +1354,7 @@ static int vc4_hvs_bind(struct device *d + SCALER_DISPCTRL_DISPEIRQ(1) | + SCALER_DISPCTRL_DISPEIRQ(2); + +- if (!vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_4) + dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ | + SCALER_DISPCTRL_SLVWREIRQ | + SCALER_DISPCTRL_SLVRDEIRQ | +@@ -1403,7 +1409,7 @@ static int vc4_hvs_bind(struct device *d + + /* Recompute Composite Output Buffer (COB) allocations for the displays + */ +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + /* The COB is 20736 pixels, or just over 10 lines at 2048 wide. + * The bottom 2048 pixels are full 32bpp RGBA (intended for the + * TXP composing RGBA to memory), whilst the remainder are only +--- a/drivers/gpu/drm/vc4/vc4_irq.c ++++ b/drivers/gpu/drm/vc4/vc4_irq.c +@@ -265,7 +265,7 @@ vc4_irq_enable(struct drm_device *dev) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (!vc4->v3d) +@@ -282,7 +282,7 @@ vc4_irq_disable(struct drm_device *dev) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (!vc4->v3d) +@@ -305,7 +305,7 @@ int vc4_irq_install(struct drm_device *d + struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (irq == IRQ_NOTCONNECTED) +@@ -326,7 +326,7 @@ void vc4_irq_uninstall(struct drm_device + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + vc4_irq_disable(dev); +@@ -339,7 +339,7 @@ void vc4_irq_reset(struct drm_device *de + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + /* Acknowledge any stale IRQs. */ +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -378,7 +378,7 @@ static void vc4_atomic_commit_tail(struc + old_hvs_state->fifo_state[channel].pending_commit = NULL; + } + +- if (vc4->is_vc5 && !vc4->firmware_kms) { ++ if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long state_rate = max(old_hvs_state->core_clock_rate, + new_hvs_state->core_clock_rate); + unsigned long core_rate = clamp_t(unsigned long, state_rate, +@@ -398,7 +398,7 @@ static void vc4_atomic_commit_tail(struc + vc4_ctm_commit(vc4, state); + + if (!vc4->firmware_kms) { +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + vc5_hvs_pv_muxing_commit(vc4, state); + else + vc4_hvs_pv_muxing_commit(vc4, state); +@@ -417,7 +417,7 @@ static void vc4_atomic_commit_tail(struc + + drm_atomic_helper_cleanup_planes(dev, state); + +- if (vc4->is_vc5 && !vc4->firmware_kms) { ++ if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long core_rate = min_t(unsigned long, + hvs->max_core_rate, + new_hvs_state->core_clock_rate); +@@ -482,7 +482,7 @@ static struct drm_framebuffer *vc4_fb_cr + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_mode_fb_cmd2 mode_cmd_local; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return ERR_PTR(-ENODEV); + + /* If the user didn't specify a modifier, use the +@@ -1065,7 +1065,7 @@ int vc4_kms_load(struct drm_device *dev) + * the BCM2711, but the load tracker computations are used for + * the core clock rate calculation. + */ +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + /* Start with the load tracker enabled. Can be + * disabled through the debugfs load_tracker file. + */ +@@ -1081,7 +1081,7 @@ int vc4_kms_load(struct drm_device *dev) + return ret; + } + +- if (vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_5) { + dev->mode_config.max_width = 7680; + dev->mode_config.max_height = 7680; + } else { +@@ -1089,7 +1089,7 @@ int vc4_kms_load(struct drm_device *dev) + dev->mode_config.max_height = 2048; + } + +- dev->mode_config.funcs = vc4->is_vc5 ? &vc5_mode_funcs : &vc4_mode_funcs; ++ dev->mode_config.funcs = (vc4->gen > VC4_GEN_4) ? &vc5_mode_funcs : &vc4_mode_funcs; + dev->mode_config.helper_private = &vc4_mode_config_helpers; + dev->mode_config.preferred_depth = 24; + dev->mode_config.async_page_flip = true; +--- a/drivers/gpu/drm/vc4/vc4_perfmon.c ++++ b/drivers/gpu/drm/vc4/vc4_perfmon.c +@@ -23,7 +23,7 @@ void vc4_perfmon_get(struct vc4_perfmon + return; + + vc4 = perfmon->dev; +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + refcount_inc(&perfmon->refcnt); +@@ -37,7 +37,7 @@ void vc4_perfmon_put(struct vc4_perfmon + return; + + vc4 = perfmon->dev; +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (refcount_dec_and_test(&perfmon->refcnt)) +@@ -49,7 +49,7 @@ void vc4_perfmon_start(struct vc4_dev *v + unsigned int i; + u32 mask; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (WARN_ON_ONCE(!perfmon || vc4->active_perfmon)) +@@ -69,7 +69,7 @@ void vc4_perfmon_stop(struct vc4_dev *vc + { + unsigned int i; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + if (WARN_ON_ONCE(!vc4->active_perfmon || +@@ -90,7 +90,7 @@ struct vc4_perfmon *vc4_perfmon_find(str + struct vc4_dev *vc4 = vc4file->dev; + struct vc4_perfmon *perfmon; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return NULL; + + mutex_lock(&vc4file->perfmon.lock); +@@ -105,7 +105,7 @@ void vc4_perfmon_open_file(struct vc4_fi + { + struct vc4_dev *vc4 = vc4file->dev; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_init(&vc4file->perfmon.lock); +@@ -126,7 +126,7 @@ void vc4_perfmon_close_file(struct vc4_f + { + struct vc4_dev *vc4 = vc4file->dev; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4file->perfmon.lock); +@@ -146,7 +146,7 @@ int vc4_perfmon_create_ioctl(struct drm_ + unsigned int i; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -200,7 +200,7 @@ int vc4_perfmon_destroy_ioctl(struct drm + struct drm_vc4_perfmon_destroy *req = data; + struct vc4_perfmon *perfmon; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -228,7 +228,7 @@ int vc4_perfmon_get_values_ioctl(struct + struct vc4_perfmon *perfmon; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (!vc4->v3d) { +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -633,10 +633,10 @@ static u32 vc4_lbm_size(struct drm_plane + } + + /* Align it to 64 or 128 (hvs5) bytes */ +- lbm = roundup(lbm, vc4->is_vc5 ? 128 : 64); ++ lbm = roundup(lbm, vc4->gen == VC4_GEN_5 ? 128 : 64); + + /* Each "word" of the LBM memory contains 2 or 4 (hvs5) pixels */ +- lbm /= vc4->is_vc5 ? 4 : 2; ++ lbm /= vc4->gen == VC4_GEN_5 ? 4 : 2; + + return lbm; + } +@@ -760,7 +760,7 @@ static int vc4_plane_allocate_lbm(struct + ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, + &vc4_state->lbm, + lbm_size, +- vc4->is_vc5 ? 64 : 32, ++ vc4->gen == VC4_GEN_5 ? 64 : 32, + 0, 0); + spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); + +@@ -1141,7 +1141,7 @@ static int vc4_plane_mode_set(struct drm + mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE && + fb->format->has_alpha; + +- if (!vc4->is_vc5) { ++ if (vc4->gen == VC4_GEN_4) { + /* Control word */ + vc4_dlist_write(vc4_state, + SCALER_CTL0_VALID | +@@ -1717,7 +1717,7 @@ struct drm_plane *vc4_plane_init(struct + }; + + for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { +- if (!hvs_formats[i].hvs5_only || vc4->is_vc5) { ++ if (!hvs_formats[i].hvs5_only || vc4->gen == VC4_GEN_5) { + formats[num_formats] = hvs_formats[i].drm; + num_formats++; + } +@@ -1732,7 +1732,7 @@ struct drm_plane *vc4_plane_init(struct + return ERR_CAST(vc4_plane); + plane = &vc4_plane->base; + +- if (vc4->is_vc5) ++ if (vc4->gen == VC4_GEN_5) + drm_plane_helper_add(plane, &vc5_plane_helper_funcs); + else + drm_plane_helper_add(plane, &vc4_plane_helper_funcs); +--- a/drivers/gpu/drm/vc4/vc4_render_cl.c ++++ b/drivers/gpu/drm/vc4/vc4_render_cl.c +@@ -599,7 +599,7 @@ int vc4_get_rcl(struct drm_device *dev, + bool has_bin = args->bin_cl_size != 0; + int ret; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + if (args->min_x_tile > args->max_x_tile || +--- a/drivers/gpu/drm/vc4/vc4_v3d.c ++++ b/drivers/gpu/drm/vc4/vc4_v3d.c +@@ -127,7 +127,7 @@ static int vc4_v3d_debugfs_ident(struct + int + vc4_v3d_pm_get(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + mutex_lock(&vc4->power_lock); +@@ -148,7 +148,7 @@ vc4_v3d_pm_get(struct vc4_dev *vc4) + void + vc4_v3d_pm_put(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4->power_lock); +@@ -178,7 +178,7 @@ int vc4_v3d_get_bin_slot(struct vc4_dev + uint64_t seqno = 0; + struct vc4_exec_info *exec; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + try_again: +@@ -325,7 +325,7 @@ int vc4_v3d_bin_bo_get(struct vc4_dev *v + { + int ret = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + mutex_lock(&vc4->bin_bo_lock); +@@ -360,7 +360,7 @@ static void bin_bo_release(struct kref * + + void vc4_v3d_bin_bo_put(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return; + + mutex_lock(&vc4->bin_bo_lock); +--- a/drivers/gpu/drm/vc4/vc4_validate.c ++++ b/drivers/gpu/drm/vc4/vc4_validate.c +@@ -109,7 +109,7 @@ vc4_use_bo(struct vc4_exec_info *exec, u + struct drm_gem_dma_object *obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return NULL; + + if (hindex >= exec->bo_count) { +@@ -169,7 +169,7 @@ vc4_check_tex_size(struct vc4_exec_info + uint32_t utile_w = utile_width(cpp); + uint32_t utile_h = utile_height(cpp); + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return false; + + /* The shaded vertex format stores signed 12.4 fixed point +@@ -495,7 +495,7 @@ vc4_validate_bin_cl(struct drm_device *d + uint32_t dst_offset = 0; + uint32_t src_offset = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + while (src_offset < len) { +@@ -942,7 +942,7 @@ vc4_validate_shader_recs(struct drm_devi + uint32_t i; + int ret = 0; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return -ENODEV; + + for (i = 0; i < exec->shader_state_count; i++) { +--- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c ++++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c +@@ -786,7 +786,7 @@ vc4_validate_shader(struct drm_gem_dma_o + struct vc4_validated_shader_info *validated_shader = NULL; + struct vc4_shader_validation_state validation_state; + +- if (WARN_ON_ONCE(vc4->is_vc5)) ++ if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) + return NULL; + + memset(&validation_state, 0, sizeof(validation_state)); diff --git a/target/linux/bcm27xx/patches-6.1/950-0939-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch b/target/linux/bcm27xx/patches-6.1/950-0939-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch new file mode 100644 index 0000000000..699db05e0c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0939-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch @@ -0,0 +1,577 @@ +From c382ea6b0457027b6ad883ee4348e03df515a785 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:29:27 +0100 +Subject: [PATCH] drm/vc4: Make v3d paths unavailable on any generation newer + than vc4 + +The V3D IP has been separate since BCM2711, so let's make sure we issue +a WARN if we're running not only on BCM2711, but also anything newer. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_bo.c | 28 +++++++++++----------- + drivers/gpu/drm/vc4/vc4_crtc.c | 4 ++-- + drivers/gpu/drm/vc4/vc4_drv.c | 8 +++---- + drivers/gpu/drm/vc4/vc4_gem.c | 24 +++++++++---------- + drivers/gpu/drm/vc4/vc4_irq.c | 10 ++++---- + drivers/gpu/drm/vc4/vc4_kms.c | 2 +- + drivers/gpu/drm/vc4/vc4_perfmon.c | 20 ++++++++-------- + drivers/gpu/drm/vc4/vc4_render_cl.c | 2 +- + drivers/gpu/drm/vc4/vc4_v3d.c | 10 ++++---- + drivers/gpu/drm/vc4/vc4_validate.c | 8 +++---- + drivers/gpu/drm/vc4/vc4_validate_shaders.c | 2 +- + 11 files changed, 59 insertions(+), 59 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_bo.c ++++ b/drivers/gpu/drm/vc4/vc4_bo.c +@@ -251,7 +251,7 @@ void vc4_bo_add_to_purgeable_pool(struct + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + mutex_lock(&vc4->purgeable.lock); +@@ -265,7 +265,7 @@ static void vc4_bo_remove_from_purgeable + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + /* list_del_init() is used here because the caller might release +@@ -396,7 +396,7 @@ struct drm_gem_object *vc4_create_object + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return ERR_PTR(-ENODEV); + + bo = kzalloc(sizeof(*bo), GFP_KERNEL); +@@ -427,7 +427,7 @@ struct vc4_bo *vc4_bo_create(struct drm_ + struct drm_gem_dma_object *dma_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return ERR_PTR(-ENODEV); + + if (size == 0) +@@ -496,7 +496,7 @@ int vc4_bo_dumb_create(struct drm_file * + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + ret = vc4_dumb_fixup_args(args); +@@ -622,7 +622,7 @@ int vc4_bo_inc_usecnt(struct vc4_bo *bo) + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + /* Fast path: if the BO is already retained by someone, no need to +@@ -661,7 +661,7 @@ void vc4_bo_dec_usecnt(struct vc4_bo *bo + { + struct vc4_dev *vc4 = to_vc4_dev(bo->base.base.dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + /* Fast path: if the BO is still retained by someone, no need to test +@@ -783,7 +783,7 @@ int vc4_create_bo_ioctl(struct drm_devic + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + ret = vc4_grab_bin_bo(vc4, vc4file); +@@ -813,7 +813,7 @@ int vc4_mmap_bo_ioctl(struct drm_device + struct drm_vc4_mmap_bo *args = data; + struct drm_gem_object *gem_obj; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + gem_obj = drm_gem_object_lookup(file_priv, args->handle); +@@ -839,7 +839,7 @@ vc4_create_shader_bo_ioctl(struct drm_de + struct vc4_bo *bo = NULL; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (args->size == 0) +@@ -918,7 +918,7 @@ int vc4_set_tiling_ioctl(struct drm_devi + struct vc4_bo *bo; + bool t_format; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (args->flags != 0) +@@ -964,7 +964,7 @@ int vc4_get_tiling_ioctl(struct drm_devi + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (args->flags != 0 || args->modifier != 0) +@@ -1011,7 +1011,7 @@ int vc4_bo_cache_init(struct drm_device + int ret; + int i; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + /* Create the initial set of BO labels that the kernel will +@@ -1075,7 +1075,7 @@ int vc4_label_bo_ioctl(struct drm_device + struct drm_gem_object *gem_obj; + int ret = 0, label; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!args->len) +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -1023,7 +1023,7 @@ static int vc4_async_page_flip(struct dr + struct vc4_bo *bo = to_vc4_bo(&dma_bo->base); + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + /* +@@ -1066,7 +1066,7 @@ int vc4_page_flip(struct drm_crtc *crtc, + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (vc4->gen == VC4_GEN_5) ++ if (vc4->gen > VC4_GEN_4) + return vc5_async_page_flip(crtc, fb, event, flags); + else + return vc4_async_page_flip(crtc, fb, event, flags); +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -98,7 +98,7 @@ static int vc4_get_param_ioctl(struct dr + if (args->pad != 0) + return -EINVAL; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) +@@ -147,7 +147,7 @@ static int vc4_open(struct drm_device *d + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_file *vc4file; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + vc4file = kzalloc(sizeof(*vc4file), GFP_KERNEL); +@@ -165,7 +165,7 @@ static void vc4_close(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_file *vc4file = file->driver_priv; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (vc4file->bin_bo_used) +@@ -315,7 +315,7 @@ static int vc4_drm_bind(struct device *d + else + gen = VC4_GEN_4; + +- if (gen == VC4_GEN_5) ++ if (gen > VC4_GEN_4) + driver = &vc5_drm_driver; + else + driver = &vc4_drm_driver; +--- a/drivers/gpu/drm/vc4/vc4_gem.c ++++ b/drivers/gpu/drm/vc4/vc4_gem.c +@@ -76,7 +76,7 @@ vc4_get_hang_state_ioctl(struct drm_devi + u32 i; + int ret = 0; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -389,7 +389,7 @@ vc4_wait_for_seqno(struct drm_device *de + unsigned long timeout_expire; + DEFINE_WAIT(wait); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (vc4->finished_seqno >= seqno) +@@ -474,7 +474,7 @@ vc4_submit_next_bin_job(struct drm_devic + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_exec_info *exec; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + again: +@@ -522,7 +522,7 @@ vc4_submit_next_render_job(struct drm_de + if (!exec) + return; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + /* A previous RCL may have written to one of our textures, and +@@ -543,7 +543,7 @@ vc4_move_job_to_render(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + bool was_empty = list_empty(&vc4->render_job_list); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + list_move_tail(&exec->head, &vc4->render_job_list); +@@ -1012,7 +1012,7 @@ vc4_job_handle_completed(struct vc4_dev + unsigned long irqflags; + struct vc4_seqno_cb *cb, *cb_temp; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + spin_lock_irqsave(&vc4->job_lock, irqflags); +@@ -1051,7 +1051,7 @@ int vc4_queue_seqno_cb(struct drm_device + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + cb->func = func; +@@ -1107,7 +1107,7 @@ vc4_wait_seqno_ioctl(struct drm_device * + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_vc4_wait_seqno *args = data; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + return vc4_wait_for_seqno_ioctl_helper(dev, args->seqno, +@@ -1124,7 +1124,7 @@ vc4_wait_bo_ioctl(struct drm_device *dev + struct drm_gem_object *gem_obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (args->pad != 0) +@@ -1173,7 +1173,7 @@ vc4_submit_cl_ioctl(struct drm_device *d + args->shader_rec_size, + args->bo_handle_count); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -1310,7 +1310,7 @@ int vc4_gem_init(struct drm_device *dev) + struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + vc4->dma_fence_context = dma_fence_context_alloc(1); +@@ -1369,7 +1369,7 @@ int vc4_gem_madvise_ioctl(struct drm_dev + struct vc4_bo *bo; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + switch (args->madv) { +--- a/drivers/gpu/drm/vc4/vc4_irq.c ++++ b/drivers/gpu/drm/vc4/vc4_irq.c +@@ -265,7 +265,7 @@ vc4_irq_enable(struct drm_device *dev) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (!vc4->v3d) +@@ -282,7 +282,7 @@ vc4_irq_disable(struct drm_device *dev) + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (!vc4->v3d) +@@ -305,7 +305,7 @@ int vc4_irq_install(struct drm_device *d + struct vc4_dev *vc4 = to_vc4_dev(dev); + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (irq == IRQ_NOTCONNECTED) +@@ -326,7 +326,7 @@ void vc4_irq_uninstall(struct drm_device + { + struct vc4_dev *vc4 = to_vc4_dev(dev); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + vc4_irq_disable(dev); +@@ -339,7 +339,7 @@ void vc4_irq_reset(struct drm_device *de + struct vc4_dev *vc4 = to_vc4_dev(dev); + unsigned long irqflags; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + /* Acknowledge any stale IRQs. */ +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -482,7 +482,7 @@ static struct drm_framebuffer *vc4_fb_cr + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_mode_fb_cmd2 mode_cmd_local; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return ERR_PTR(-ENODEV); + + /* If the user didn't specify a modifier, use the +--- a/drivers/gpu/drm/vc4/vc4_perfmon.c ++++ b/drivers/gpu/drm/vc4/vc4_perfmon.c +@@ -23,7 +23,7 @@ void vc4_perfmon_get(struct vc4_perfmon + return; + + vc4 = perfmon->dev; +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + refcount_inc(&perfmon->refcnt); +@@ -37,7 +37,7 @@ void vc4_perfmon_put(struct vc4_perfmon + return; + + vc4 = perfmon->dev; +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (refcount_dec_and_test(&perfmon->refcnt)) +@@ -49,7 +49,7 @@ void vc4_perfmon_start(struct vc4_dev *v + unsigned int i; + u32 mask; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (WARN_ON_ONCE(!perfmon || vc4->active_perfmon)) +@@ -69,7 +69,7 @@ void vc4_perfmon_stop(struct vc4_dev *vc + { + unsigned int i; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + if (WARN_ON_ONCE(!vc4->active_perfmon || +@@ -90,7 +90,7 @@ struct vc4_perfmon *vc4_perfmon_find(str + struct vc4_dev *vc4 = vc4file->dev; + struct vc4_perfmon *perfmon; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return NULL; + + mutex_lock(&vc4file->perfmon.lock); +@@ -105,7 +105,7 @@ void vc4_perfmon_open_file(struct vc4_fi + { + struct vc4_dev *vc4 = vc4file->dev; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + mutex_init(&vc4file->perfmon.lock); +@@ -126,7 +126,7 @@ void vc4_perfmon_close_file(struct vc4_f + { + struct vc4_dev *vc4 = vc4file->dev; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + mutex_lock(&vc4file->perfmon.lock); +@@ -146,7 +146,7 @@ int vc4_perfmon_create_ioctl(struct drm_ + unsigned int i; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -200,7 +200,7 @@ int vc4_perfmon_destroy_ioctl(struct drm + struct drm_vc4_perfmon_destroy *req = data; + struct vc4_perfmon *perfmon; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) { +@@ -228,7 +228,7 @@ int vc4_perfmon_get_values_ioctl(struct + struct vc4_perfmon *perfmon; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (!vc4->v3d) { +--- a/drivers/gpu/drm/vc4/vc4_render_cl.c ++++ b/drivers/gpu/drm/vc4/vc4_render_cl.c +@@ -599,7 +599,7 @@ int vc4_get_rcl(struct drm_device *dev, + bool has_bin = args->bin_cl_size != 0; + int ret; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + if (args->min_x_tile > args->max_x_tile || +--- a/drivers/gpu/drm/vc4/vc4_v3d.c ++++ b/drivers/gpu/drm/vc4/vc4_v3d.c +@@ -127,7 +127,7 @@ static int vc4_v3d_debugfs_ident(struct + int + vc4_v3d_pm_get(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + mutex_lock(&vc4->power_lock); +@@ -148,7 +148,7 @@ vc4_v3d_pm_get(struct vc4_dev *vc4) + void + vc4_v3d_pm_put(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + mutex_lock(&vc4->power_lock); +@@ -178,7 +178,7 @@ int vc4_v3d_get_bin_slot(struct vc4_dev + uint64_t seqno = 0; + struct vc4_exec_info *exec; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + try_again: +@@ -325,7 +325,7 @@ int vc4_v3d_bin_bo_get(struct vc4_dev *v + { + int ret = 0; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + mutex_lock(&vc4->bin_bo_lock); +@@ -360,7 +360,7 @@ static void bin_bo_release(struct kref * + + void vc4_v3d_bin_bo_put(struct vc4_dev *vc4) + { +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return; + + mutex_lock(&vc4->bin_bo_lock); +--- a/drivers/gpu/drm/vc4/vc4_validate.c ++++ b/drivers/gpu/drm/vc4/vc4_validate.c +@@ -109,7 +109,7 @@ vc4_use_bo(struct vc4_exec_info *exec, u + struct drm_gem_dma_object *obj; + struct vc4_bo *bo; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return NULL; + + if (hindex >= exec->bo_count) { +@@ -169,7 +169,7 @@ vc4_check_tex_size(struct vc4_exec_info + uint32_t utile_w = utile_width(cpp); + uint32_t utile_h = utile_height(cpp); + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return false; + + /* The shaded vertex format stores signed 12.4 fixed point +@@ -495,7 +495,7 @@ vc4_validate_bin_cl(struct drm_device *d + uint32_t dst_offset = 0; + uint32_t src_offset = 0; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + while (src_offset < len) { +@@ -942,7 +942,7 @@ vc4_validate_shader_recs(struct drm_devi + uint32_t i; + int ret = 0; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return -ENODEV; + + for (i = 0; i < exec->shader_state_count; i++) { +--- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c ++++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c +@@ -786,7 +786,7 @@ vc4_validate_shader(struct drm_gem_dma_o + struct vc4_validated_shader_info *validated_shader = NULL; + struct vc4_shader_validation_state validation_state; + +- if (WARN_ON_ONCE(vc4->gen == VC4_GEN_5)) ++ if (WARN_ON_ONCE(vc4->gen > VC4_GEN_4)) + return NULL; + + memset(&validation_state, 0, sizeof(validation_state)); diff --git a/target/linux/bcm27xx/patches-6.1/950-0940-drm-vc4-hvs-Use-switch-statement-to-simplify-vc4_hvs.patch b/target/linux/bcm27xx/patches-6.1/950-0940-drm-vc4-hvs-Use-switch-statement-to-simplify-vc4_hvs.patch new file mode 100644 index 0000000000..048b5d3222 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0940-drm-vc4-hvs-Use-switch-statement-to-simplify-vc4_hvs.patch @@ -0,0 +1,125 @@ +From 72e5eb3d9511af2f056911d70c4d033d4fc674b2 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:07:29 +0100 +Subject: [PATCH] drm/vc4: hvs: Use switch statement to simplify + vc4_hvs_get_fifo_from_output + +Since we'll support BCM2712 soon, let's move the logic behind +vc4_hvs_get_fifo_from_output() to a switch to extend it more easily. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 80 +++++++++++++++++++---------------- + 1 file changed, 43 insertions(+), 37 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -620,57 +620,63 @@ int vc4_hvs_get_fifo_from_output(struct + u32 reg; + int ret; + +- if (vc4->gen == VC4_GEN_4) ++ switch (vc4->gen) { ++ case VC4_GEN_4: + return output; + +- /* +- * NOTE: We should probably use drm_dev_enter()/drm_dev_exit() +- * here, but this function is only used during the DRM device +- * initialization, so we should be fine. +- */ +- +- switch (output) { +- case 0: +- return 0; +- +- case 1: +- return 1; +- +- case 2: +- reg = HVS_READ(SCALER_DISPECTRL); +- ret = FIELD_GET(SCALER_DISPECTRL_DSP2_MUX_MASK, reg); +- if (ret == 0) +- return 2; +- +- return 0; +- +- case 3: +- reg = HVS_READ(SCALER_DISPCTRL); +- ret = FIELD_GET(SCALER_DISPCTRL_DSP3_MUX_MASK, reg); +- if (ret == 3) +- return -EPIPE; +- +- return ret; +- +- case 4: +- reg = HVS_READ(SCALER_DISPEOLN); +- ret = FIELD_GET(SCALER_DISPEOLN_DSP4_MUX_MASK, reg); +- if (ret == 3) +- return -EPIPE; ++ case VC4_GEN_5: ++ /* ++ * NOTE: We should probably use ++ * drm_dev_enter()/drm_dev_exit() here, but this ++ * function is only used during the DRM device ++ * initialization, so we should be fine. ++ */ ++ ++ switch (output) { ++ case 0: ++ return 0; ++ ++ case 1: ++ return 1; ++ ++ case 2: ++ reg = HVS_READ(SCALER_DISPECTRL); ++ ret = FIELD_GET(SCALER_DISPECTRL_DSP2_MUX_MASK, reg); ++ if (ret == 0) ++ return 2; ++ ++ return 0; ++ ++ case 3: ++ reg = HVS_READ(SCALER_DISPCTRL); ++ ret = FIELD_GET(SCALER_DISPCTRL_DSP3_MUX_MASK, reg); ++ if (ret == 3) ++ return -EPIPE; ++ ++ return ret; ++ ++ case 4: ++ reg = HVS_READ(SCALER_DISPEOLN); ++ ret = FIELD_GET(SCALER_DISPEOLN_DSP4_MUX_MASK, reg); ++ if (ret == 3) ++ return -EPIPE; ++ ++ return ret; ++ ++ case 5: ++ reg = HVS_READ(SCALER_DISPDITHER); ++ ret = FIELD_GET(SCALER_DISPDITHER_DSP5_MUX_MASK, reg); ++ if (ret == 3) ++ return -EPIPE; + +- return ret; ++ return ret; + +- case 5: +- reg = HVS_READ(SCALER_DISPDITHER); +- ret = FIELD_GET(SCALER_DISPDITHER_DSP5_MUX_MASK, reg); +- if (ret == 3) ++ default: + return -EPIPE; +- +- return ret; +- +- default: +- return -EPIPE; ++ } + } ++ ++ return -EPIPE; + } + + static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc, diff --git a/target/linux/bcm27xx/patches-6.1/950-0941-drm-vc4-hvs-Use-switch-statement-to-simplify-enablin.patch b/target/linux/bcm27xx/patches-6.1/950-0941-drm-vc4-hvs-Use-switch-statement-to-simplify-enablin.patch new file mode 100644 index 0000000000..984b329fb4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0941-drm-vc4-hvs-Use-switch-statement-to-simplify-enablin.patch @@ -0,0 +1,74 @@ +From 72bfb10c9393688d00e4e0b00d416e23c2753318 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:07:29 +0100 +Subject: [PATCH] drm/vc4: hvs: Use switch statement to simplify + enabling/disabling irq + +Since we'll support BCM2712 soon, let's move the logic to enable and +disable the end-of-frame interrupts to a switch to extend it more +easily. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 42 ++++++++++++++++++++++++++--------- + 1 file changed, 32 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -416,24 +416,46 @@ static void vc4_hvs_irq_enable_eof(const + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; +- u32 irq_mask = vc4->gen == VC4_GEN_5 ? +- SCALER5_DISPCTRL_DSPEIEOF(channel) : +- SCALER_DISPCTRL_DSPEIEOF(channel); + +- HVS_WRITE(SCALER_DISPCTRL, +- HVS_READ(SCALER_DISPCTRL) | irq_mask); ++ switch (vc4->gen) { ++ case VC4_GEN_4: ++ HVS_WRITE(SCALER_DISPCTRL, ++ HVS_READ(SCALER_DISPCTRL) | ++ SCALER_DISPCTRL_DSPEIEOF(channel)); ++ break; ++ ++ case VC4_GEN_5: ++ HVS_WRITE(SCALER_DISPCTRL, ++ HVS_READ(SCALER_DISPCTRL) | ++ SCALER5_DISPCTRL_DSPEIEOF(channel)); ++ break; ++ ++ default: ++ break; ++ } + } + + static void vc4_hvs_irq_clear_eof(const struct vc4_hvs *hvs, + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; +- u32 irq_mask = vc4->gen == VC4_GEN_5 ? +- SCALER5_DISPCTRL_DSPEIEOF(channel) : +- SCALER_DISPCTRL_DSPEIEOF(channel); + +- HVS_WRITE(SCALER_DISPCTRL, +- HVS_READ(SCALER_DISPCTRL) & ~irq_mask); ++ switch (vc4->gen) { ++ case VC4_GEN_4: ++ HVS_WRITE(SCALER_DISPCTRL, ++ HVS_READ(SCALER_DISPCTRL) & ++ ~SCALER_DISPCTRL_DSPEIEOF(channel)); ++ break; ++ ++ case VC4_GEN_5: ++ HVS_WRITE(SCALER_DISPCTRL, ++ HVS_READ(SCALER_DISPCTRL) & ++ ~SCALER5_DISPCTRL_DSPEIEOF(channel)); ++ break; ++ ++ default: ++ break; ++ } + } + + static struct vc4_hvs_dlist_allocation * diff --git a/target/linux/bcm27xx/patches-6.1/950-0942-drm-vc4-hvs-Test-if-the-EOF-interrupts-are-enabled.patch b/target/linux/bcm27xx/patches-6.1/950-0942-drm-vc4-hvs-Test-if-the-EOF-interrupts-are-enabled.patch new file mode 100644 index 0000000000..704468b90e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0942-drm-vc4-hvs-Test-if-the-EOF-interrupts-are-enabled.patch @@ -0,0 +1,100 @@ +From bcf02f6ac0d429a425e8409f140bd875a1feed2e Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 13:46:53 +0200 +Subject: [PATCH] drm/vc4: hvs: Test if the EOF interrupts are enabled + +We currently enable the EOF interrupts through the CRTC destroy_state +implementation. + +However, nothing guarantees that we can't call destroy_state multiple +times in a row, and therefore before the EOF interrupt even happens. + +This means we would enable the interrupt multiple times but disable it +only once. It wasn't an issue so far since the interrupts were only +enabled by setting a bit in a register, but with BCM2712 we will use an +external interrupt controller, with a refcounted interrupt. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 8 ++++++-- + drivers/gpu/drm/vc4/vc4_hvs.c | 14 ++++++++++++-- + 2 files changed, 18 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -333,6 +333,8 @@ struct vc4_v3d { + struct debugfs_regset32 regset; + }; + ++#define HVS_NUM_CHANNELS 3 ++ + struct vc4_hvs { + struct vc4_dev *vc4; + struct platform_device *pdev; +@@ -341,6 +343,10 @@ struct vc4_hvs { + + struct clk *core_clk; + ++ struct { ++ unsigned int enabled: 1; ++ } eof_irq[HVS_NUM_CHANNELS]; ++ + unsigned long max_core_rate; + + /* Memory manager for CRTCs to allocate space in the display +@@ -373,8 +379,6 @@ struct vc4_hvs { + bool vc5_hdmi_enable_4096by2160; + }; + +-#define HVS_NUM_CHANNELS 3 +- + struct vc4_hvs_state { + struct drm_private_state base; + unsigned long core_clock_rate; +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -412,11 +412,14 @@ static void vc5_hvs_update_gamma_lut(str + vc5_hvs_lut_load(hvs, vc4_crtc); + } + +-static void vc4_hvs_irq_enable_eof(const struct vc4_hvs *hvs, ++static void vc4_hvs_irq_enable_eof(struct vc4_hvs *hvs, + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; + ++ if (hvs->eof_irq[channel].enabled) ++ return; ++ + switch (vc4->gen) { + case VC4_GEN_4: + HVS_WRITE(SCALER_DISPCTRL, +@@ -433,13 +436,18 @@ static void vc4_hvs_irq_enable_eof(const + default: + break; + } ++ ++ hvs->eof_irq[channel].enabled = true; + } + +-static void vc4_hvs_irq_clear_eof(const struct vc4_hvs *hvs, ++static void vc4_hvs_irq_clear_eof(struct vc4_hvs *hvs, + unsigned int channel) + { + struct vc4_dev *vc4 = hvs->vc4; + ++ if (!hvs->eof_irq[channel].enabled) ++ return; ++ + switch (vc4->gen) { + case VC4_GEN_4: + HVS_WRITE(SCALER_DISPCTRL, +@@ -456,6 +464,8 @@ static void vc4_hvs_irq_clear_eof(const + default: + break; + } ++ ++ hvs->eof_irq[channel].enabled = false; + } + + static struct vc4_hvs_dlist_allocation * diff --git a/target/linux/bcm27xx/patches-6.1/950-0943-drm-vc4-hvs-Create-hw_init-function.patch b/target/linux/bcm27xx/patches-6.1/950-0943-drm-vc4-hvs-Create-hw_init-function.patch new file mode 100644 index 0000000000..5b748b5e94 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0943-drm-vc4-hvs-Create-hw_init-function.patch @@ -0,0 +1,188 @@ +From f3c84bb53107cef0009347d071c1a188ce24b8a3 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 14:36:28 +0100 +Subject: [PATCH] drm/vc4: hvs: Create hw_init function + +Since the BCM2712 will feature a significantly different HVS, let's move +the hardware initialisation part of our bind function into a separate +function. + +That way, it will be easier to extend in the future. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 155 ++++++++++++++++++---------------- + 1 file changed, 83 insertions(+), 72 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1291,79 +1291,10 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + return hvs; + } + +-static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) ++static int vc4_hvs_hw_init(struct vc4_hvs *hvs) + { +- struct platform_device *pdev = to_platform_device(dev); +- struct drm_device *drm = dev_get_drvdata(master); +- struct vc4_dev *vc4 = to_vc4_dev(drm); +- struct vc4_hvs *hvs = NULL; +- int ret; +- u32 dispctrl; +- u32 reg, top; +- +- hvs = __vc4_hvs_alloc(vc4, NULL); +- if (IS_ERR(hvs)) +- return PTR_ERR(hvs); +- +- hvs->regs = vc4_ioremap_regs(pdev, 0); +- if (IS_ERR(hvs->regs)) +- return PTR_ERR(hvs->regs); +- +- hvs->regset.base = hvs->regs; +- hvs->regset.regs = hvs_regs; +- hvs->regset.nregs = ARRAY_SIZE(hvs_regs); +- +- if (vc4->gen == VC4_GEN_5) { +- struct rpi_firmware *firmware; +- struct device_node *node; +- unsigned int max_rate; +- +- node = rpi_firmware_find_node(); +- if (!node) +- return -EINVAL; +- +- firmware = rpi_firmware_get(node); +- of_node_put(node); +- if (!firmware) +- return -EPROBE_DEFER; +- +- hvs->core_clk = devm_clk_get(&pdev->dev, NULL); +- if (IS_ERR(hvs->core_clk)) { +- dev_err(&pdev->dev, "Couldn't get core clock\n"); +- return PTR_ERR(hvs->core_clk); +- } +- +- max_rate = rpi_firmware_clk_get_max_rate(firmware, +- RPI_FIRMWARE_CORE_CLK_ID); +- rpi_firmware_put(firmware); +- if (max_rate >= 550000000) +- hvs->vc5_hdmi_enable_hdmi_20 = true; +- +- if (max_rate >= 600000000) +- hvs->vc5_hdmi_enable_4096by2160 = true; +- +- hvs->max_core_rate = max_rate; +- +- ret = clk_prepare_enable(hvs->core_clk); +- if (ret) { +- dev_err(&pdev->dev, "Couldn't enable the core clock\n"); +- return ret; +- } +- } +- +- if (vc4->gen == VC4_GEN_4) +- hvs->dlist = hvs->regs + SCALER_DLIST_START; +- else +- hvs->dlist = hvs->regs + SCALER5_DLIST_START; +- +- /* Upload filter kernels. We only have the one for now, so we +- * keep it around for the lifetime of the driver. +- */ +- ret = vc4_hvs_upload_linear_kernel(hvs, +- &hvs->mitchell_netravali_filter, +- mitchell_netravali_1_3_1_3_kernel); +- if (ret) +- return ret; ++ struct vc4_dev *vc4 = hvs->vc4; ++ u32 dispctrl, reg; + + reg = HVS_READ(SCALER_DISPECTRL); + reg &= ~SCALER_DISPECTRL_DSP2_MUX_MASK; +@@ -1445,6 +1376,86 @@ static int vc4_hvs_bind(struct device *d + + HVS_WRITE(SCALER_DISPCTRL, dispctrl); + ++ return 0; ++} ++ ++static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct drm_device *drm = dev_get_drvdata(master); ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct vc4_hvs *hvs = NULL; ++ int ret; ++ u32 reg, top; ++ ++ hvs = __vc4_hvs_alloc(vc4, NULL); ++ if (IS_ERR(hvs)) ++ return PTR_ERR(hvs); ++ ++ hvs->regs = vc4_ioremap_regs(pdev, 0); ++ if (IS_ERR(hvs->regs)) ++ return PTR_ERR(hvs->regs); ++ ++ hvs->regset.base = hvs->regs; ++ hvs->regset.regs = hvs_regs; ++ hvs->regset.nregs = ARRAY_SIZE(hvs_regs); ++ ++ if (vc4->gen == VC4_GEN_5) { ++ struct rpi_firmware *firmware; ++ struct device_node *node; ++ unsigned int max_rate; ++ ++ node = rpi_firmware_find_node(); ++ if (!node) ++ return -EINVAL; ++ ++ firmware = rpi_firmware_get(node); ++ of_node_put(node); ++ if (!firmware) ++ return -EPROBE_DEFER; ++ ++ hvs->core_clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(hvs->core_clk)) { ++ dev_err(&pdev->dev, "Couldn't get core clock\n"); ++ return PTR_ERR(hvs->core_clk); ++ } ++ ++ max_rate = rpi_firmware_clk_get_max_rate(firmware, ++ RPI_FIRMWARE_CORE_CLK_ID); ++ rpi_firmware_put(firmware); ++ if (max_rate >= 550000000) ++ hvs->vc5_hdmi_enable_hdmi_20 = true; ++ ++ if (max_rate >= 600000000) ++ hvs->vc5_hdmi_enable_4096by2160 = true; ++ ++ hvs->max_core_rate = max_rate; ++ ++ ret = clk_prepare_enable(hvs->core_clk); ++ if (ret) { ++ dev_err(&pdev->dev, "Couldn't enable the core clock\n"); ++ return ret; ++ } ++ } ++ ++ if (vc4->gen == VC4_GEN_4) ++ hvs->dlist = hvs->regs + SCALER_DLIST_START; ++ else ++ hvs->dlist = hvs->regs + SCALER5_DLIST_START; ++ ++ /* Upload filter kernels. We only have the one for now, so we ++ * keep it around for the lifetime of the driver. ++ */ ++ ret = vc4_hvs_upload_linear_kernel(hvs, ++ &hvs->mitchell_netravali_filter, ++ mitchell_netravali_1_3_1_3_kernel); ++ if (ret) ++ return ret; ++ ++ ret = vc4_hvs_hw_init(hvs); ++ if (ret) ++ return ret; ++ + /* Recompute Composite Output Buffer (COB) allocations for the displays + */ + if (vc4->gen == VC4_GEN_4) { diff --git a/target/linux/bcm27xx/patches-6.1/950-0944-drm-vc4-hvs-Create-cob_init-function.patch b/target/linux/bcm27xx/patches-6.1/950-0944-drm-vc4-hvs-Create-cob_init-function.patch new file mode 100644 index 0000000000..5b2e9745e9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0944-drm-vc4-hvs-Create-cob_init-function.patch @@ -0,0 +1,167 @@ +From 99a13ce3a12303dfb54815637972627a7d207086 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:14:55 +0100 +Subject: [PATCH] drm/vc4: hvs: Create cob_init function + +Just like the HVS itself, the COB parameters will be fairly different in +the BCM2712. + +Let's move the COB parameters computation and its initialisation to a +separate function that will be easier to extend in the future. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 128 ++++++++++++++++++++-------------- + 1 file changed, 74 insertions(+), 54 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1379,6 +1379,77 @@ static int vc4_hvs_hw_init(struct vc4_hv + return 0; + } + ++static int vc4_hvs_cob_init(struct vc4_hvs *hvs) ++{ ++ struct vc4_dev *vc4 = hvs->vc4; ++ u32 reg, top; ++ ++ /* ++ * Recompute Composite Output Buffer (COB) allocations for the ++ * displays ++ */ ++ switch (vc4->gen) { ++ case VC4_GEN_4: ++ /* The COB is 20736 pixels, or just over 10 lines at 2048 wide. ++ * The bottom 2048 pixels are full 32bpp RGBA (intended for the ++ * TXP composing RGBA to memory), whilst the remainder are only ++ * 24bpp RGB. ++ * ++ * Assign 3 lines to channels 1 & 2, and just over 4 lines to ++ * channel 0. ++ */ ++ #define VC4_COB_SIZE 20736 ++ #define VC4_COB_LINE_WIDTH 2048 ++ #define VC4_COB_NUM_LINES 3 ++ reg = 0; ++ top = VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES; ++ reg |= (top - 1) << 16; ++ HVS_WRITE(SCALER_DISPBASE2, reg); ++ reg = top; ++ top += VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES; ++ reg |= (top - 1) << 16; ++ HVS_WRITE(SCALER_DISPBASE1, reg); ++ reg = top; ++ top = VC4_COB_SIZE; ++ reg |= (top - 1) << 16; ++ HVS_WRITE(SCALER_DISPBASE0, reg); ++ break; ++ ++ case VC4_GEN_5: ++ /* The COB is 44416 pixels, or 10.8 lines at 4096 wide. ++ * The bottom 4096 pixels are full RGBA (intended for the TXP ++ * composing RGBA to memory), whilst the remainder are only ++ * RGB. Addressing is always pixel wide. ++ * ++ * Assign 3 lines of 4096 to channels 1 & 2, and just over 4 ++ * lines. to channel 0. ++ */ ++ #define VC5_COB_SIZE 44416 ++ #define VC5_COB_LINE_WIDTH 4096 ++ #define VC5_COB_NUM_LINES 3 ++ reg = 0; ++ top = VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES; ++ reg |= top << 16; ++ HVS_WRITE(SCALER_DISPBASE2, reg); ++ top += 16; ++ reg = top; ++ top += VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES; ++ reg |= top << 16; ++ HVS_WRITE(SCALER_DISPBASE1, reg); ++ top += 16; ++ reg = top; ++ top = VC5_COB_SIZE; ++ reg |= top << 16; ++ HVS_WRITE(SCALER_DISPBASE0, reg); ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) + { + struct platform_device *pdev = to_platform_device(dev); +@@ -1386,7 +1457,6 @@ static int vc4_hvs_bind(struct device *d + struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_hvs *hvs = NULL; + int ret; +- u32 reg, top; + + hvs = __vc4_hvs_alloc(vc4, NULL); + if (IS_ERR(hvs)) +@@ -1456,59 +1526,9 @@ static int vc4_hvs_bind(struct device *d + if (ret) + return ret; + +- /* Recompute Composite Output Buffer (COB) allocations for the displays +- */ +- if (vc4->gen == VC4_GEN_4) { +- /* The COB is 20736 pixels, or just over 10 lines at 2048 wide. +- * The bottom 2048 pixels are full 32bpp RGBA (intended for the +- * TXP composing RGBA to memory), whilst the remainder are only +- * 24bpp RGB. +- * +- * Assign 3 lines to channels 1 & 2, and just over 4 lines to +- * channel 0. +- */ +- #define VC4_COB_SIZE 20736 +- #define VC4_COB_LINE_WIDTH 2048 +- #define VC4_COB_NUM_LINES 3 +- reg = 0; +- top = VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES; +- reg |= (top - 1) << 16; +- HVS_WRITE(SCALER_DISPBASE2, reg); +- reg = top; +- top += VC4_COB_LINE_WIDTH * VC4_COB_NUM_LINES; +- reg |= (top - 1) << 16; +- HVS_WRITE(SCALER_DISPBASE1, reg); +- reg = top; +- top = VC4_COB_SIZE; +- reg |= (top - 1) << 16; +- HVS_WRITE(SCALER_DISPBASE0, reg); +- } else { +- /* The COB is 44416 pixels, or 10.8 lines at 4096 wide. +- * The bottom 4096 pixels are full RGBA (intended for the TXP +- * composing RGBA to memory), whilst the remainder are only +- * RGB. Addressing is always pixel wide. +- * +- * Assign 3 lines of 4096 to channels 1 & 2, and just over 4 +- * lines. to channel 0. +- */ +- #define VC5_COB_SIZE 44416 +- #define VC5_COB_LINE_WIDTH 4096 +- #define VC5_COB_NUM_LINES 3 +- reg = 0; +- top = VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES; +- reg |= top << 16; +- HVS_WRITE(SCALER_DISPBASE2, reg); +- top += 16; +- reg = top; +- top += VC5_COB_LINE_WIDTH * VC5_COB_NUM_LINES; +- reg |= top << 16; +- HVS_WRITE(SCALER_DISPBASE1, reg); +- top += 16; +- reg = top; +- top = VC5_COB_SIZE; +- reg |= top << 16; +- HVS_WRITE(SCALER_DISPBASE0, reg); +- } ++ ret = vc4_hvs_cob_init(hvs); ++ if (ret) ++ return ret; + + ret = devm_request_irq(dev, platform_get_irq(pdev, 0), + vc4_hvs_irq_handler, 0, "vc4 hvs", drm); diff --git a/target/linux/bcm27xx/patches-6.1/950-0945-drm-vc4-hvs-Rename-hvs_regs-list.patch b/target/linux/bcm27xx/patches-6.1/950-0945-drm-vc4-hvs-Rename-hvs_regs-list.patch new file mode 100644 index 0000000000..4139d79f02 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0945-drm-vc4-hvs-Rename-hvs_regs-list.patch @@ -0,0 +1,38 @@ +From 7a1c157ac856384c47df38e1de2995f55a111b85 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:41:59 +0100 +Subject: [PATCH] drm/vc4: hvs: Rename hvs_regs list + +The HVS register set has been heavily modified in the BCM2712, and we'll +thus need a separate debugfs_reg32 array for it. + +The name hvs_regs is thus a bit too generic, so let's rename it to +something more specific. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -33,7 +33,7 @@ + #include "vc4_drv.h" + #include "vc4_regs.h" + +-static const struct debugfs_reg32 hvs_regs[] = { ++static const struct debugfs_reg32 vc4_hvs_regs[] = { + VC4_REG32(SCALER_DISPCTRL), + VC4_REG32(SCALER_DISPSTAT), + VC4_REG32(SCALER_DISPID), +@@ -1467,8 +1467,8 @@ static int vc4_hvs_bind(struct device *d + return PTR_ERR(hvs->regs); + + hvs->regset.base = hvs->regs; +- hvs->regset.regs = hvs_regs; +- hvs->regset.nregs = ARRAY_SIZE(hvs_regs); ++ hvs->regset.regs = vc4_hvs_regs; ++ hvs->regset.nregs = ARRAY_SIZE(vc4_hvs_regs); + + if (vc4->gen == VC4_GEN_5) { + struct rpi_firmware *firmware; diff --git a/target/linux/bcm27xx/patches-6.1/950-0946-drm-vc4-plane-Change-ptr0_offset-to-an-array.patch b/target/linux/bcm27xx/patches-6.1/950-0946-drm-vc4-plane-Change-ptr0_offset-to-an-array.patch new file mode 100644 index 0000000000..ed55f53fad --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0946-drm-vc4-plane-Change-ptr0_offset-to-an-array.patch @@ -0,0 +1,103 @@ +From 531f66804eb95323f807d240273087fbe162aeee Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 24 Mar 2023 09:56:31 +0100 +Subject: [PATCH] drm/vc4: plane: Change ptr0_offset to an array + +The BCM2712 will have a fairly different dlist, that will feature one +Pointer 0 word for each plane. + +Let's prepare by changing the ptr0_offset variable that holds the offset +in a dlist of the pointer 0 word to an array. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 3 ++- + drivers/gpu/drm/vc4/vc4_plane.c | 18 +++++++++--------- + 2 files changed, 11 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -430,7 +431,7 @@ struct vc4_plane_state { + */ + u32 pos0_offset; + u32 pos2_offset; +- u32 ptr0_offset; ++ u32 ptr0_offset[DRM_FORMAT_MAX_PLANES]; + u32 lbm_offset; + + /* Offset where the plane's dlist was last stored in the +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -1242,7 +1242,7 @@ static int vc4_plane_mode_set(struct drm + * + * The pointers may be any byte address. + */ +- vc4_state->ptr0_offset = vc4_state->dlist_count; ++ vc4_state->ptr0_offset[0] = vc4_state->dlist_count; + for (i = 0; i < num_planes; i++) + vc4_dlist_write(vc4_state, vc4_state->offsets[i]); + +@@ -1447,13 +1447,13 @@ void vc4_plane_async_set_fb(struct drm_p + * scanout will start from this address as soon as the FIFO + * needs to refill with pixels. + */ +- writel(addr, &vc4_state->hw_dlist[vc4_state->ptr0_offset]); ++ writel(addr, &vc4_state->hw_dlist[vc4_state->ptr0_offset[0]]); + + /* Also update the CPU-side dlist copy, so that any later + * atomic updates that don't do a new modeset on our plane + * also use our updated address. + */ +- vc4_state->dlist[vc4_state->ptr0_offset] = addr; ++ vc4_state->dlist[vc4_state->ptr0_offset[0]] = addr; + + drm_dev_exit(idx); + } +@@ -1517,8 +1517,8 @@ static void vc4_plane_atomic_async_updat + new_vc4_state->dlist[vc4_state->pos0_offset]; + vc4_state->dlist[vc4_state->pos2_offset] = + new_vc4_state->dlist[vc4_state->pos2_offset]; +- vc4_state->dlist[vc4_state->ptr0_offset] = +- new_vc4_state->dlist[vc4_state->ptr0_offset]; ++ vc4_state->dlist[vc4_state->ptr0_offset[0]] = ++ new_vc4_state->dlist[vc4_state->ptr0_offset[0]]; + + /* Note that we can't just call vc4_plane_write_dlist() + * because that would smash the context data that the HVS is +@@ -1528,8 +1528,8 @@ static void vc4_plane_atomic_async_updat + &vc4_state->hw_dlist[vc4_state->pos0_offset]); + writel(vc4_state->dlist[vc4_state->pos2_offset], + &vc4_state->hw_dlist[vc4_state->pos2_offset]); +- writel(vc4_state->dlist[vc4_state->ptr0_offset], +- &vc4_state->hw_dlist[vc4_state->ptr0_offset]); ++ writel(vc4_state->dlist[vc4_state->ptr0_offset[0]], ++ &vc4_state->hw_dlist[vc4_state->ptr0_offset[0]]); + + drm_dev_exit(idx); + } +@@ -1556,7 +1556,7 @@ static int vc4_plane_atomic_async_check( + if (old_vc4_state->dlist_count != new_vc4_state->dlist_count || + old_vc4_state->pos0_offset != new_vc4_state->pos0_offset || + old_vc4_state->pos2_offset != new_vc4_state->pos2_offset || +- old_vc4_state->ptr0_offset != new_vc4_state->ptr0_offset || ++ old_vc4_state->ptr0_offset[0] != new_vc4_state->ptr0_offset[0] || + vc4_lbm_size(plane->state) != vc4_lbm_size(new_plane_state)) + return -EINVAL; + +@@ -1566,7 +1566,7 @@ static int vc4_plane_atomic_async_check( + for (i = 0; i < new_vc4_state->dlist_count; i++) { + if (i == new_vc4_state->pos0_offset || + i == new_vc4_state->pos2_offset || +- i == new_vc4_state->ptr0_offset || ++ i == new_vc4_state->ptr0_offset[0] || + (new_vc4_state->lbm_offset && + i == new_vc4_state->lbm_offset)) + continue; diff --git a/target/linux/bcm27xx/patches-6.1/950-0947-drm-vc4-hvs-Rework-LBM-alignment.patch b/target/linux/bcm27xx/patches-6.1/950-0947-drm-vc4-hvs-Rework-LBM-alignment.patch new file mode 100644 index 0000000000..3a30b9ca85 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0947-drm-vc4-hvs-Rework-LBM-alignment.patch @@ -0,0 +1,45 @@ +From 2834b58a3b58198e551d8461a0786b75d3d76823 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 13 Apr 2023 10:12:19 +0200 +Subject: [PATCH] drm/vc4: hvs: Rework LBM alignment + +With the introduction of the support for BCM2712, the check of whether +we're running on vc5 or not to compute the LBM alignment requirement +doesn't work anymore. + +Moreover, the LBM size will need to be computed in words for the +BCM2712, while we've had sizes in bytes so far. + +Aligning on either 64 or 32 words is thus fairly harmful on BCM2712, so +let's just explicitly align the size when needed, and then call +drm_mm_insert_node_generic() with an alignment of 1. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_plane.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -744,6 +744,11 @@ static int vc4_plane_allocate_lbm(struct + if (!lbm_size) + return 0; + ++ if (vc4->gen == VC4_GEN_5) ++ lbm_size = ALIGN(lbm_size, 64); ++ else if (vc4->gen == VC4_GEN_4) ++ lbm_size = ALIGN(lbm_size, 32); ++ + drm_dbg_driver(drm, "[PLANE:%d:%s] LBM Allocation Size: %u\n", + plane->base.id, plane->name, lbm_size); + +@@ -759,8 +764,7 @@ static int vc4_plane_allocate_lbm(struct + spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags); + ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, + &vc4_state->lbm, +- lbm_size, +- vc4->gen == VC4_GEN_5 ? 64 : 32, ++ lbm_size, 1, + 0, 0); + spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0948-drm-vc4-hvs-Change-prototype-of-__vc4_hvs_alloc-to-p.patch b/target/linux/bcm27xx/patches-6.1/950-0948-drm-vc4-hvs-Change-prototype-of-__vc4_hvs_alloc-to-p.patch new file mode 100644 index 0000000000..2927a3e04e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0948-drm-vc4-hvs-Change-prototype-of-__vc4_hvs_alloc-to-p.patch @@ -0,0 +1,93 @@ +From 23cba2abd5ffbb7337e3f381c4724eaaf01cf5a1 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 24 Mar 2023 15:45:50 +0100 +Subject: [PATCH] drm/vc4: hvs: Change prototype of __vc4_hvs_alloc to pass + registers + +The BCM2712 HVS has registers to report the size of the various SRAM the +driver uses, and their size actually differ depending on the stepping. + +The initialisation of the memory pools happen in the __vc4_hvs_alloc() +function that also allocates the main HVS structure, that will then hold +the pointer to the memory mapping of the registers. + +This creates some kind of circular dependency that we can break by +passing the mapping pointer as an argument for __vc4_hvs_alloc() to use +to query to get the SRAM sizes and initialise the memory pools +accordingly. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 2 +- + drivers/gpu/drm/vc4/vc4_drv.h | 4 +++- + drivers/gpu/drm/vc4/vc4_hvs.c | 16 ++++++++++------ + 3 files changed, 14 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -173,7 +173,7 @@ static struct vc4_dev *__mock_device(str + vc4->dev = dev; + vc4->gen = gen; + +- vc4->hvs = __vc4_hvs_alloc(vc4, NULL); ++ vc4->hvs = __vc4_hvs_alloc(vc4, NULL, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4->hvs); + + drm = &vc4->base; +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -1092,7 +1092,9 @@ void vc4_irq_reset(struct drm_device *de + + /* vc4_hvs.c */ + extern struct platform_driver vc4_hvs_driver; +-struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, struct platform_device *pdev); ++struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, ++ void __iomem *regs, ++ struct platform_device *pdev); + void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int output); + int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output); + u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo); +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1248,7 +1248,9 @@ int vc4_hvs_debugfs_init(struct drm_mino + return 0; + } + +-struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, struct platform_device *pdev) ++struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, ++ void __iomem *regs, ++ struct platform_device *pdev) + { + struct drm_device *drm = &vc4->base; + struct vc4_hvs *hvs; +@@ -1258,6 +1260,7 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + return ERR_PTR(-ENOMEM); + + hvs->vc4 = vc4; ++ hvs->regs = regs; + hvs->pdev = pdev; + + spin_lock_init(&hvs->mm_lock); +@@ -1456,16 +1459,17 @@ static int vc4_hvs_bind(struct device *d + struct drm_device *drm = dev_get_drvdata(master); + struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_hvs *hvs = NULL; ++ void __iomem *regs; + int ret; + +- hvs = __vc4_hvs_alloc(vc4, NULL); ++ regs = vc4_ioremap_regs(pdev, 0); ++ if (IS_ERR(regs)) ++ return PTR_ERR(regs); ++ ++ hvs = __vc4_hvs_alloc(vc4, regs, pdev); + if (IS_ERR(hvs)) + return PTR_ERR(hvs); + +- hvs->regs = vc4_ioremap_regs(pdev, 0); +- if (IS_ERR(hvs->regs)) +- return PTR_ERR(hvs->regs); +- + hvs->regset.base = hvs->regs; + hvs->regset.regs = vc4_hvs_regs; + hvs->regset.nregs = ARRAY_SIZE(vc4_hvs_regs); diff --git a/target/linux/bcm27xx/patches-6.1/950-0949-drm-vc4-UV-planes-vertical-scaling-must-always-be-en.patch b/target/linux/bcm27xx/patches-6.1/950-0949-drm-vc4-UV-planes-vertical-scaling-must-always-be-en.patch new file mode 100644 index 0000000000..4a51862487 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0949-drm-vc4-UV-planes-vertical-scaling-must-always-be-en.patch @@ -0,0 +1,30 @@ +From 03e0e348df7b685439f2db61ec2d8c8da25d1217 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 23 Aug 2023 17:48:23 +0100 +Subject: [PATCH] drm/vc4: UV planes vertical scaling must always be enabled + +It has been observed that a YUV422 unity scaled plane isn't displayed. +Enabling vertical scaling on the UV planes solves this. There is +already a similar clause to always enable horizontal scaling on the +UV planes. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -522,6 +522,12 @@ static int vc4_plane_setup_clipping_and_ + */ + if (vc4_state->x_scaling[1] == VC4_SCALING_NONE) + vc4_state->x_scaling[1] = VC4_SCALING_PPF; ++ ++ /* Similarly UV needs vertical scaling to be enabled. ++ * Without this a 1:1 scaled YUV422 plane isn't rendered. ++ */ ++ if (vc4_state->y_scaling[1] == VC4_SCALING_NONE) ++ vc4_state->y_scaling[1] = VC4_SCALING_PPF; + } else { + vc4_state->is_yuv = false; + vc4_state->x_scaling[1] = VC4_SCALING_NONE; diff --git a/target/linux/bcm27xx/patches-6.1/950-0950-drm-vc4-hdmi-Avoid-hang-with-debug-registers-when-su.patch b/target/linux/bcm27xx/patches-6.1/950-0950-drm-vc4-hdmi-Avoid-hang-with-debug-registers-when-su.patch new file mode 100644 index 0000000000..8e36b79794 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0950-drm-vc4-hdmi-Avoid-hang-with-debug-registers-when-su.patch @@ -0,0 +1,39 @@ +From e5e7679d634b10e88df340c85cd8368c9f9989eb Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Tue, 5 Sep 2023 19:38:24 +0100 +Subject: [PATCH] drm/vc4: hdmi: Avoid hang with debug registers when suspended + +Trying to read /sys/kernel/debug/dri/1/hdmi1_regs +when the hdmi is disconnected results in a fatal system hang. + +This is due to the pm suspend code disabling the dvp clock. +That is just a gate of the 108MHz clock in DVP_HT_RPI_MISC_CONFIG, +which results in accesses hanging AXI bus. + +Protect against this. + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -193,6 +193,8 @@ static int vc4_hdmi_debugfs_regs(struct + if (!drm_dev_enter(drm, &idx)) + return -ENODEV; + ++ WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); ++ + drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); + drm_print_regset32(&p, &vc4_hdmi->hd_regset); + drm_print_regset32(&p, &vc4_hdmi->cec_regset); +@@ -202,6 +204,8 @@ static int vc4_hdmi_debugfs_regs(struct + drm_print_regset32(&p, &vc4_hdmi->ram_regset); + drm_print_regset32(&p, &vc4_hdmi->rm_regset); + ++ pm_runtime_put(&vc4_hdmi->pdev->dev); ++ + drm_dev_exit(idx); + + return 0; diff --git a/target/linux/bcm27xx/patches-6.1/950-0951-drm-vc4-Move-the-buffer-offset-out-of-the-vc4_plane_.patch b/target/linux/bcm27xx/patches-6.1/950-0951-drm-vc4-Move-the-buffer-offset-out-of-the-vc4_plane_.patch new file mode 100644 index 0000000000..eeb2a93b5c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0951-drm-vc4-Move-the-buffer-offset-out-of-the-vc4_plane_.patch @@ -0,0 +1,154 @@ +From 11cf37e741b439b26fe932750bde841a16a96828 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 25 Sep 2023 16:57:07 +0100 +Subject: [PATCH] drm/vc4: Move the buffer offset out of the vc4_plane_state + +The offset fields in vc4_plane_state are described as being +the offset for each buffer in the bo, however it is used to +store the complete DMA address that is then written into the +register. + +The DMA address including the fb ofset can be retrieved +using drm_fb_dma_get_gem_addr, and the offset adjustment due to +clipping is local to vc4_plane_mode_set. +Drop the offset field from the state, and compute the complete +DMA address in vc4_plane_mode_set. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_drv.h | 5 ---- + drivers/gpu/drm/vc4/vc4_plane.c | 51 +++++++++++++-------------------- + 2 files changed, 20 insertions(+), 36 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -451,11 +451,6 @@ struct vc4_plane_state { + bool is_unity; + bool is_yuv; + +- /* Offset to start scanning out from the start of the plane's +- * BO. +- */ +- u32 offsets[3]; +- + /* Our allocation in LBM for temporary storage during scaling. */ + struct drm_mm_node lbm; + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -450,12 +450,11 @@ static int vc4_plane_setup_clipping_and_ + { + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + struct drm_framebuffer *fb = state->fb; +- struct drm_gem_dma_object *bo; + int num_planes = fb->format->num_planes; + struct drm_crtc_state *crtc_state; + u32 h_subsample = fb->format->hsub; + u32 v_subsample = fb->format->vsub; +- int i, ret; ++ int ret; + + crtc_state = drm_atomic_get_existing_crtc_state(state->state, + state->crtc); +@@ -469,11 +468,6 @@ static int vc4_plane_setup_clipping_and_ + if (ret) + return ret; + +- for (i = 0; i < num_planes; i++) { +- bo = drm_fb_dma_get_gem_obj(fb, i); +- vc4_state->offsets[i] = bo->dma_addr + fb->offsets[i]; +- } +- + vc4_state->src_x = state->src.x1; + vc4_state->src_y = state->src.y1; + vc4_state->src_w[0] = state->src.x2 - vc4_state->src_x; +@@ -896,6 +890,7 @@ static int vc4_plane_mode_set(struct drm + u32 width, height; + u32 hvs_format = format->hvs; + unsigned int rotation; ++ u32 offsets[3] = { 0 }; + int ret, i; + + if (vc4_state->dlist_initialized) +@@ -943,13 +938,8 @@ static int vc4_plane_mode_set(struct drm + * out. + */ + for (i = 0; i < num_planes; i++) { +- vc4_state->offsets[i] += src_y / +- (i ? v_subsample : 1) * +- fb->pitches[i]; +- +- vc4_state->offsets[i] += src_x / +- (i ? h_subsample : 1) * +- fb->format->cpp[i]; ++ offsets[i] += src_y / (i ? v_subsample : 1) * fb->pitches[i]; ++ offsets[i] += src_x / (i ? h_subsample : 1) * fb->format->cpp[i]; + } + + break; +@@ -1004,19 +994,18 @@ static int vc4_plane_mode_set(struct drm + VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) | + VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) | + VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R)); +- vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift); +- vc4_state->offsets[0] += subtile_y << 8; +- vc4_state->offsets[0] += utile_y << 4; ++ offsets[0] += tiles_t * (tiles_w << tile_size_shift); ++ offsets[0] += subtile_y << 8; ++ offsets[0] += utile_y << 4; + + /* Rows of tiles alternate left-to-right and right-to-left. */ + if (tiles_t & 1) { + pitch0 |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR; +- vc4_state->offsets[0] += (tiles_w - tiles_l) << +- tile_size_shift; +- vc4_state->offsets[0] -= (1 + !tile_y) << 10; ++ offsets[0] += (tiles_w - tiles_l) << tile_size_shift; ++ offsets[0] -= (1 + !tile_y) << 10; + } else { +- vc4_state->offsets[0] += tiles_l << tile_size_shift; +- vc4_state->offsets[0] += tile_y << 10; ++ offsets[0] += tiles_l << tile_size_shift; ++ offsets[0] += tile_y << 10; + } + + break; +@@ -1105,11 +1094,9 @@ static int vc4_plane_mode_set(struct drm + + tile = src_x / pix_per_tile; + +- vc4_state->offsets[i] += param * tile_w * tile; +- vc4_state->offsets[i] += src_y / +- (i ? v_subsample : 1) * +- tile_w; +- vc4_state->offsets[i] += x_off & ~(i ? 1 : 0); ++ offsets[i] += param * tile_w * tile; ++ offsets[i] += src_y / (i ? v_subsample : 1) * tile_w; ++ offsets[i] += x_off & ~(i ? 1 : 0); + } + + pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT); +@@ -1253,8 +1240,12 @@ static int vc4_plane_mode_set(struct drm + * The pointers may be any byte address. + */ + vc4_state->ptr0_offset[0] = vc4_state->dlist_count; +- for (i = 0; i < num_planes; i++) +- vc4_dlist_write(vc4_state, vc4_state->offsets[i]); ++ ++ for (i = 0; i < num_planes; i++) { ++ dma_addr_t paddr = drm_fb_dma_get_gem_addr(fb, state, i); ++ ++ vc4_dlist_write(vc4_state, paddr + offsets[i]); ++ } + + /* Pointer Context Word 0/1/2: Written by the HVS */ + for (i = 0; i < num_planes; i++) +@@ -1518,8 +1509,6 @@ static void vc4_plane_atomic_async_updat + sizeof(vc4_state->y_scaling)); + vc4_state->is_unity = new_vc4_state->is_unity; + vc4_state->is_yuv = new_vc4_state->is_yuv; +- memcpy(vc4_state->offsets, new_vc4_state->offsets, +- sizeof(vc4_state->offsets)); + vc4_state->needs_bg_fill = new_vc4_state->needs_bg_fill; + + /* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0952-drm-vc4-Fix-dlist-debug-not-resetting-the-next-entry.patch b/target/linux/bcm27xx/patches-6.1/950-0952-drm-vc4-Fix-dlist-debug-not-resetting-the-next-entry.patch new file mode 100644 index 0000000000..01ad932415 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0952-drm-vc4-Fix-dlist-debug-not-resetting-the-next-entry.patch @@ -0,0 +1,33 @@ +From 3660abb4a8523e988f1345985e89149804e50ebe Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 24 Aug 2023 15:36:21 +0100 +Subject: [PATCH] drm/vc4: Fix dlist debug not resetting the next entry pointer + +The debug function to display the dlists didn't reset next_entry_start +when starting each display, so resulting in not stopping the +list at the correct place. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -110,7 +110,7 @@ static int vc4_hvs_debugfs_dlist(struct + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; + struct drm_printer p = drm_seq_file_printer(m); +- unsigned int next_entry_start = 0; ++ unsigned int next_entry_start; + unsigned int i, j; + u32 dlist_word, dispstat; + +@@ -124,6 +124,7 @@ static int vc4_hvs_debugfs_dlist(struct + } + + drm_printf(&p, "HVS chan %u:\n", i); ++ next_entry_start = 0; + + for (j = HVS_READ(SCALER_DISPLISTX(i)); j < 256; j++) { + dlist_word = readl((u32 __iomem *)vc4->hvs->dlist + j); diff --git a/target/linux/bcm27xx/patches-6.1/950-0953-drm-vc4-Remove-incorrect-limit-from-hvs_dlist-debugf.patch b/target/linux/bcm27xx/patches-6.1/950-0953-drm-vc4-Remove-incorrect-limit-from-hvs_dlist-debugf.patch new file mode 100644 index 0000000000..d41d53ecbe --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0953-drm-vc4-Remove-incorrect-limit-from-hvs_dlist-debugf.patch @@ -0,0 +1,57 @@ +From ebf11a4cfd9f1236fb9eeb7e32e87b18f5f56f16 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 1 Sep 2023 13:45:08 +0100 +Subject: [PATCH] drm: vc4: Remove incorrect limit from hvs_dlist debugfs + function + +The debugfs function to dump dlists aborted at 256 bytes, +when actually the dlist memory is generally significantly +larger but varies based on SoC. + +We already have the correct limit in __vc4_hvs_alloc, so +store it for use in the debugfs dlist function. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_hvs.c | 5 ++++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -341,6 +341,7 @@ struct vc4_hvs { + struct platform_device *pdev; + void __iomem *regs; + u32 __iomem *dlist; ++ unsigned int dlist_mem_size; + + struct clk *core_clk; + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -110,6 +110,7 @@ static int vc4_hvs_debugfs_dlist(struct + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; + struct drm_printer p = drm_seq_file_printer(m); ++ unsigned int dlist_mem_size = hvs->dlist_mem_size; + unsigned int next_entry_start; + unsigned int i, j; + u32 dlist_word, dispstat; +@@ -126,7 +127,7 @@ static int vc4_hvs_debugfs_dlist(struct + drm_printf(&p, "HVS chan %u:\n", i); + next_entry_start = 0; + +- for (j = HVS_READ(SCALER_DISPLISTX(i)); j < 256; j++) { ++ for (j = HVS_READ(SCALER_DISPLISTX(i)); j < dlist_mem_size; j++) { + dlist_word = readl((u32 __iomem *)vc4->hvs->dlist + j); + drm_printf(&p, "dlist: %02d: 0x%08x\n", j, + dlist_word); +@@ -1278,6 +1279,8 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + HVS_BOOTLOADER_DLIST_END, + (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END); + ++ hvs->dlist_mem_size = dlist_size; ++ + /* Set up the HVS LBM memory manager. We could have some more + * complicated data structure that allowed reuse of LBM areas + * between planes when they don't overlap on the screen, but diff --git a/target/linux/bcm27xx/patches-6.1/950-0954-drm-vc4-hvs-Remove-ABORT_ON_EMPTY-flag.patch b/target/linux/bcm27xx/patches-6.1/950-0954-drm-vc4-hvs-Remove-ABORT_ON_EMPTY-flag.patch new file mode 100644 index 0000000000..640b0ea757 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0954-drm-vc4-hvs-Remove-ABORT_ON_EMPTY-flag.patch @@ -0,0 +1,50 @@ +From 712bccec241e84e28ccb725fae87d3255d039f42 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Thu, 22 Jun 2023 14:06:40 +0100 +Subject: [PATCH] drm/vc4: hvs: Remove ABORT_ON_EMPTY flag + +ABORT_ON_EMPTY chooses whether the HVS abandons the current frame +when it experiences an underflow, or attempts to continue. + +In theory the frame should be black from the point of underflow, +compared to a shift of sebsequent pixels to the left. + +Unfortunately it seems to put the HVS is a bad state where it is not +possible to recover simply. This typically requires a reboot +following the 'flip done timed out message'. + +Discussion with Broadcom has suggested we don't use this flag. +All their testing is done with it disabled. + +Additionally setting BLANK_INSERT_EN causes the HDMI to output +blank pixels on an underflow which avoids it losing sync. + +After this change a 'flip done timed out' due to sdram bandwidth +starvation or too low a clock is recoverable once the situation improves. + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 1 + + drivers/gpu/drm/vc4/vc4_regs.h | 1 + + 2 files changed, 2 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -1866,6 +1866,7 @@ static void vc4_hdmi_encoder_post_crtc_e + VC4_HD_VID_CTL_CLRRGB | + VC4_HD_VID_CTL_UNDERFLOW_ENABLE | + VC4_HD_VID_CTL_FRAME_COUNTER_RESET | ++ VC4_HD_VID_CTL_BLANK_INSERT_EN | + (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | + (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); + +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -799,6 +799,7 @@ enum { + # define VC4_HD_VID_CTL_CLRSYNC BIT(24) + # define VC4_HD_VID_CTL_CLRRGB BIT(23) + # define VC4_HD_VID_CTL_BLANKPIX BIT(18) ++# define VC4_HD_VID_CTL_BLANK_INSERT_EN BIT(16) + + # define VC4_HD_CSC_CTL_ORDER_MASK VC4_MASK(7, 5) + # define VC4_HD_CSC_CTL_ORDER_SHIFT 5 diff --git a/target/linux/bcm27xx/patches-6.1/950-0955-drm-vc4-Enable-SCALER_CONTROL-early-in-HVS-init.patch b/target/linux/bcm27xx/patches-6.1/950-0955-drm-vc4-Enable-SCALER_CONTROL-early-in-HVS-init.patch new file mode 100644 index 0000000000..3060c0201f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0955-drm-vc4-Enable-SCALER_CONTROL-early-in-HVS-init.patch @@ -0,0 +1,59 @@ +From 542ba979b4fa1e07ff2ad2dabbdc12e92b80ed46 Mon Sep 17 00:00:00 2001 +From: Tim Gover +Date: Thu, 13 Jul 2023 17:47:22 +0100 +Subject: [PATCH] drm/vc4: Enable SCALER_CONTROL early in HVS init + +Always enable SCALER_CONTROL before attempting other HVS +operations. It's safe to write to some parts of the HVS but +in general it's dangerous to do this because it can cause bus +lockups. + +Signed-off-by: Tim Gover +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1303,6 +1303,10 @@ static int vc4_hvs_hw_init(struct vc4_hv + struct vc4_dev *vc4 = hvs->vc4; + u32 dispctrl, reg; + ++ dispctrl = HVS_READ(SCALER_DISPCTRL); ++ dispctrl |= SCALER_DISPCTRL_ENABLE; ++ HVS_WRITE(SCALER_DISPCTRL, dispctrl); ++ + reg = HVS_READ(SCALER_DISPECTRL); + reg &= ~SCALER_DISPECTRL_DSP2_MUX_MASK; + HVS_WRITE(SCALER_DISPECTRL, +@@ -1324,8 +1328,6 @@ static int vc4_hvs_hw_init(struct vc4_hv + reg | VC4_SET_FIELD(3, SCALER_DISPDITHER_DSP5_MUX)); + + dispctrl = HVS_READ(SCALER_DISPCTRL); +- +- dispctrl |= SCALER_DISPCTRL_ENABLE; + dispctrl |= SCALER_DISPCTRL_DISPEIRQ(0) | + SCALER_DISPCTRL_DISPEIRQ(1) | + SCALER_DISPCTRL_DISPEIRQ(2); +@@ -1521,6 +1523,10 @@ static int vc4_hvs_bind(struct device *d + else + hvs->dlist = hvs->regs + SCALER5_DLIST_START; + ++ ret = vc4_hvs_hw_init(hvs); ++ if (ret) ++ return ret; ++ + /* Upload filter kernels. We only have the one for now, so we + * keep it around for the lifetime of the driver. + */ +@@ -1530,10 +1536,6 @@ static int vc4_hvs_bind(struct device *d + if (ret) + return ret; + +- ret = vc4_hvs_hw_init(hvs); +- if (ret) +- return ret; +- + ret = vc4_hvs_cob_init(hvs); + if (ret) + return ret; diff --git a/target/linux/bcm27xx/patches-6.1/950-0956-dt-bindings-display-Add-BCM2712-HDMI-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0956-dt-bindings-display-Add-BCM2712-HDMI-bindings.patch new file mode 100644 index 0000000000..dab1fff2e3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0956-dt-bindings-display-Add-BCM2712-HDMI-bindings.patch @@ -0,0 +1,26 @@ +From aed3dadaa6fb4c38275b264ecc0ff5ebe0408b82 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:02 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 HDMI bindings + +The BCM2712 HDMI controller uses a slightly different HDMI controller +than the BCM2711, and a completely different PHY. + +Let's introduce a new compatible for it. + +Signed-off-by: Maxime Ripard +--- + .../devicetree/bindings/display/brcm,bcm2711-hdmi.yaml | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml +@@ -14,6 +14,8 @@ properties: + enum: + - brcm,bcm2711-hdmi0 + - brcm,bcm2711-hdmi1 ++ - brcm,bcm2712-hdmi0 ++ - brcm,bcm2712-hdmi1 + + reg: + items: diff --git a/target/linux/bcm27xx/patches-6.1/950-0957-dt-bindings-display-Add-BCM2712-HVS-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0957-dt-bindings-display-Add-BCM2712-HVS-bindings.patch new file mode 100644 index 0000000000..e28100734f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0957-dt-bindings-display-Add-BCM2712-HVS-bindings.patch @@ -0,0 +1,34 @@ +From 2f5a75f9687553d6e91fcc09b233f5f6176b3681 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:14 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 HVS bindings + +The BCM2712 has a completely different HVS than the previous +generations, so let's add a new compatible for it. + +Signed-off-by: Maxime Ripard +--- + .../devicetree/bindings/display/brcm,bcm2835-hvs.yaml | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml +@@ -13,6 +13,7 @@ properties: + compatible: + enum: + - brcm,bcm2711-hvs ++ - brcm,bcm2712-hvs + - brcm,bcm2835-hvs + + reg: +@@ -36,7 +37,9 @@ if: + properties: + compatible: + contains: +- const: brcm,bcm2711-hvs ++ enum: ++ - brcm,bcm2711-hvs ++ - brcm,bcm2712-hvs + + then: + required: diff --git a/target/linux/bcm27xx/patches-6.1/950-0958-dt-bindings-display-Add-BCM2712-PixelValve-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0958-dt-bindings-display-Add-BCM2712-PixelValve-bindings.patch new file mode 100644 index 0000000000..b37c1274ae --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0958-dt-bindings-display-Add-BCM2712-PixelValve-bindings.patch @@ -0,0 +1,28 @@ +From 9f26d5827745df2c59e5559fd59a5045a4ad7ce0 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:27 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 PixelValve bindings + +The BCM2712 has 3 different pixelvalves that are similar to the ones +found in the previous generations but with slightly different +capabilities. + +Express that using a new set of compatibles. + +Signed-off-by: Maxime Ripard +--- + .../devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml +@@ -20,6 +20,9 @@ properties: + - brcm,bcm2711-pixelvalve2 + - brcm,bcm2711-pixelvalve3 + - brcm,bcm2711-pixelvalve4 ++ - brcm,bcm2712-pixelvalve0 ++ - brcm,bcm2712-pixelvalve1 ++ - brcm,bcm2712-pixelvalve2 + + reg: + maxItems: 1 diff --git a/target/linux/bcm27xx/patches-6.1/950-0959-dt-bindings-display-Add-BCM2712-MOP-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0959-dt-bindings-display-Add-BCM2712-MOP-bindings.patch new file mode 100644 index 0000000000..ea537522cc --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0959-dt-bindings-display-Add-BCM2712-MOP-bindings.patch @@ -0,0 +1,28 @@ +From 07f90ad6a81d9ed923ee0da05541718baf49fb3c Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:36 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 MOP bindings + +The BCM2712 has a MOP controller which is basically a new revision of +the TXP. + +Express that by adding a new compatible for it. + +Signed-off-by: Maxime Ripard +--- + .../devicetree/bindings/display/brcm,bcm2835-txp.yaml | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml +@@ -11,7 +11,9 @@ maintainers: + + properties: + compatible: +- const: brcm,bcm2835-txp ++ enum: ++ - brcm,bcm2712-mop ++ - brcm,bcm2835-txp + + reg: + maxItems: 1 diff --git a/target/linux/bcm27xx/patches-6.1/950-0960-dt-bindings-display-Add-BCM2712-MOPLET-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0960-dt-bindings-display-Add-BCM2712-MOPLET-bindings.patch new file mode 100644 index 0000000000..97aaf5bb7a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0960-dt-bindings-display-Add-BCM2712-MOPLET-bindings.patch @@ -0,0 +1,25 @@ +From e4a3722d08c723f1212bfbdcb52710de8340720a Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:36 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 MOPLET bindings + +The BCM2712 has a MOPLET controller which is basically a TXP without the +transpose feature. + +Express that by adding a new compatible for it. + +Signed-off-by: Maxime Ripard +--- + Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml +@@ -13,6 +13,7 @@ properties: + compatible: + enum: + - brcm,bcm2712-mop ++ - brcm,bcm2712-moplet + - brcm,bcm2835-txp + + reg: diff --git a/target/linux/bcm27xx/patches-6.1/950-0961-dt-bindings-display-Add-BCM2712-KMS-driver-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-0961-dt-bindings-display-Add-BCM2712-KMS-driver-bindings.patch new file mode 100644 index 0000000000..420c66ce66 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0961-dt-bindings-display-Add-BCM2712-KMS-driver-bindings.patch @@ -0,0 +1,23 @@ +From e66d4b49a027257c347fa57ce6972f08747c0917 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:36:51 +0100 +Subject: [PATCH] dt-bindings: display: Add BCM2712 KMS driver bindings + +The BCM2712 SoC comes with a new variation of the videocore display +pipeline. Let's create a new compatible for it. + +Signed-off-by: Maxime Ripard +--- + Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml ++++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml +@@ -18,6 +18,7 @@ properties: + compatible: + enum: + - brcm,bcm2711-vc5 ++ - brcm,bcm2712-vc6 + - brcm,bcm2835-vc4 + - brcm,cygnus-vc4 + diff --git a/target/linux/bcm27xx/patches-6.1/950-0962-drm-vc4-drv-Support-BCM2712.patch b/target/linux/bcm27xx/patches-6.1/950-0962-drm-vc4-drv-Support-BCM2712.patch new file mode 100644 index 0000000000..57a797ce18 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0962-drm-vc4-drv-Support-BCM2712.patch @@ -0,0 +1,47 @@ +From 847ec495822ad512dd9f1a58a85dabea01534855 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:29:52 +0100 +Subject: [PATCH] drm/vc4: drv: Support BCM2712 + +The BCM2712 has an improved display pipeline, most notably with a +different HVS and only HDMI and writeback outputs. + +Let's introduce it as a new VideoCore generation and compatible. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.c | 5 ++++- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + 2 files changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -310,7 +310,9 @@ static int vc4_drm_bind(struct device *d + + dev->coherent_dma_mask = DMA_BIT_MASK(32); + +- if (of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5")) ++ if (of_device_is_compatible(dev->of_node, "brcm,bcm2712-vc6")) ++ gen = VC4_GEN_6; ++ else if (of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5")) + gen = VC4_GEN_5; + else + gen = VC4_GEN_4; +@@ -475,6 +477,7 @@ static int vc4_platform_drm_remove(struc + + static const struct of_device_id vc4_of_match[] = { + { .compatible = "brcm,bcm2711-vc5", }, ++ { .compatible = "brcm,bcm2712-vc6", }, + { .compatible = "brcm,bcm2835-vc4", }, + { .compatible = "brcm,cygnus-vc4", }, + {}, +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -84,6 +84,7 @@ struct vc4_perfmon { + enum vc4_gen { + VC4_GEN_4, + VC4_GEN_5, ++ VC4_GEN_6, + }; + + struct vc4_dev { diff --git a/target/linux/bcm27xx/patches-6.1/950-0963-drm-vc4-hvs-Support-BCM2712-HVS.patch b/target/linux/bcm27xx/patches-6.1/950-0963-drm-vc4-hvs-Support-BCM2712-HVS.patch new file mode 100644 index 0000000000..9659432294 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0963-drm-vc4-hvs-Support-BCM2712-HVS.patch @@ -0,0 +1,2139 @@ +From e84da235223d0209165183c430692dde5c69854c Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:25:16 +0100 +Subject: [PATCH] drm/vc4: hvs: Support BCM2712 HVS + +The HVS found in the BCM2712, while having a similar role, is very +different from the one found in the previous SoCs. Indeed, the register +layout is fairly different, and the DLIST format is new as well. + +Let's introduce the needed functions to support the new HVS. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 47 ++- + drivers/gpu/drm/vc4/vc4_drv.c | 8 +- + drivers/gpu/drm/vc4/vc4_drv.h | 18 + + drivers/gpu/drm/vc4/vc4_hvs.c | 626 ++++++++++++++++++++++++++++--- + drivers/gpu/drm/vc4/vc4_kms.c | 102 ++++- + drivers/gpu/drm/vc4/vc4_plane.c | 641 +++++++++++++++++++++++++++++++- + drivers/gpu/drm/vc4/vc4_regs.h | 181 +++++++++ + 7 files changed, 1540 insertions(+), 83 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -82,13 +82,22 @@ static unsigned int + vc4_crtc_get_cob_allocation(struct vc4_dev *vc4, unsigned int channel) + { + struct vc4_hvs *hvs = vc4->hvs; +- u32 dispbase = HVS_READ(SCALER_DISPBASEX(channel)); ++ u32 dispbase, top, base; ++ + /* Top/base are supposed to be 4-pixel aligned, but the + * Raspberry Pi firmware fills the low bits (which are + * presumably ignored). + */ +- u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3; +- u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3; ++ ++ if (vc4->gen >= VC4_GEN_6) { ++ dispbase = HVS_READ(SCALER6_DISPX_COB(channel)); ++ top = VC4_GET_FIELD(dispbase, SCALER6_DISPX_COB_TOP) & ~3; ++ base = VC4_GET_FIELD(dispbase, SCALER6_DISPX_COB_BASE) & ~3; ++ } else { ++ dispbase = HVS_READ(SCALER_DISPBASEX(channel)); ++ top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3; ++ base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3; ++ } + + return top - base + 4; + } +@@ -121,7 +130,10 @@ static bool vc4_crtc_get_scanout_positio + * Read vertical scanline which is currently composed for our + * pixelvalve by the HVS, and also the scaler status. + */ +- val = HVS_READ(SCALER_DISPSTATX(channel)); ++ if (vc4->gen >= VC4_GEN_6) ++ val = HVS_READ(SCALER6_DISPX_STATUS(channel)); ++ else ++ val = HVS_READ(SCALER_DISPSTATX(channel)); + + /* Get optional system timestamp after query. */ + if (etime) +@@ -130,7 +142,12 @@ static bool vc4_crtc_get_scanout_positio + /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ + + /* Vertical position of hvs composed scanline. */ +- *vpos = VC4_GET_FIELD(val, SCALER_DISPSTATX_LINE); ++ ++ if (vc4->gen >= VC4_GEN_6) ++ *vpos = VC4_GET_FIELD(val, SCALER6_DISPX_STATUS_YLINE); ++ else ++ *vpos = VC4_GET_FIELD(val, SCALER_DISPSTATX_LINE); ++ + *hpos = 0; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { +@@ -475,8 +492,10 @@ static void require_hvs_enabled(struct d + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; + +- WARN_ON_ONCE((HVS_READ(SCALER_DISPCTRL) & SCALER_DISPCTRL_ENABLE) != +- SCALER_DISPCTRL_ENABLE); ++ if (vc4->gen >= VC4_GEN_6) ++ WARN_ON_ONCE(!(HVS_READ(SCALER6_CONTROL) & SCALER6_CONTROL_HVS_EN)); ++ else ++ WARN_ON_ONCE(!(HVS_READ(SCALER_DISPCTRL) & SCALER_DISPCTRL_ENABLE)); + } + + static int vc4_crtc_disable(struct drm_crtc *crtc, +@@ -804,14 +823,21 @@ static void vc4_crtc_handle_page_flip(st + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; ++ unsigned int current_dlist; + u32 chan = vc4_crtc->current_hvs_channel; + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + spin_lock(&vc4_crtc->irq_lock); ++ ++ if (vc4->gen >= VC4_GEN_6) ++ current_dlist = VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_DL(chan)), ++ SCALER6_DISPX_DL_LACT); ++ else ++ current_dlist = HVS_READ(SCALER_DISPLACTX(chan)); ++ + if (vc4_crtc->event && +- (vc4_crtc->current_dlist == HVS_READ(SCALER_DISPLACTX(chan)) || +- vc4_crtc->feeds_txp)) { ++ (vc4_crtc->current_dlist == current_dlist || vc4_crtc->feeds_txp)) { + drm_crtc_send_vblank_event(crtc, vc4_crtc->event); + vc4_crtc->event = NULL; + drm_crtc_vblank_put(crtc); +@@ -822,7 +848,8 @@ static void vc4_crtc_handle_page_flip(st + * the CRTC and encoder already reconfigured, leading to + * underruns. This can be seen when reconfiguring the CRTC. + */ +- vc4_hvs_unmask_underrun(hvs, chan); ++ if (vc4->gen < VC4_GEN_6) ++ vc4_hvs_unmask_underrun(hvs, chan); + } + spin_unlock(&vc4_crtc->irq_lock); + spin_unlock_irqrestore(&dev->event_lock, flags); +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -277,6 +277,7 @@ static const struct of_device_id vc4_dma + { .compatible = "brcm,bcm2711-hvs" }, + { .compatible = "brcm,bcm2835-hvs" }, + { .compatible = "brcm,bcm2711-hvs" }, ++ { .compatible = "brcm,bcm2712-hvs" }, + { .compatible = "raspberrypi,rpi-firmware-kms" }, + { .compatible = "brcm,bcm2835-v3d" }, + { .compatible = "brcm,cygnus-v3d" }, +@@ -308,8 +309,6 @@ static int vc4_drm_bind(struct device *d + enum vc4_gen gen; + int ret = 0; + +- dev->coherent_dma_mask = DMA_BIT_MASK(32); +- + if (of_device_is_compatible(dev->of_node, "brcm,bcm2712-vc6")) + gen = VC4_GEN_6; + else if (of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5")) +@@ -322,6 +321,11 @@ static int vc4_drm_bind(struct device *d + else + driver = &vc4_drm_driver; + ++ if (gen >= VC4_GEN_6) ++ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36)); ++ else ++ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); ++ + node = of_find_matching_node_and_match(NULL, vc4_dma_range_matches, + NULL); + if (node) { +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -345,8 +345,10 @@ struct vc4_hvs { + unsigned int dlist_mem_size; + + struct clk *core_clk; ++ struct clk *disp_clk; + + struct { ++ unsigned int desc; + unsigned int enabled: 1; + } eof_irq[HVS_NUM_CHANNELS]; + +@@ -358,6 +360,11 @@ struct vc4_hvs { + struct drm_mm dlist_mm; + /* Memory manager for the LBM memory used by HVS scaling. */ + struct drm_mm lbm_mm; ++ ++ /* Memory manager for the UPM memory used for prefetching. */ ++ struct drm_mm upm_mm; ++ struct ida upm_handles; ++ + spinlock_t mm_lock; + + struct list_head stale_dlist_entries; +@@ -382,6 +389,8 @@ struct vc4_hvs { + bool vc5_hdmi_enable_4096by2160; + }; + ++#define HVS_UBM_WORD_SIZE 256 ++ + struct vc4_hvs_state { + struct drm_private_state base; + unsigned long core_clock_rate; +@@ -456,6 +465,15 @@ struct vc4_plane_state { + /* Our allocation in LBM for temporary storage during scaling. */ + struct drm_mm_node lbm; + ++ /* Our allocation in UPM for prefetching. */ ++ struct drm_mm_node upm[DRM_FORMAT_MAX_PLANES]; ++ ++ /* The Unified Pre-Fetcher Handle */ ++ unsigned int upm_handle[DRM_FORMAT_MAX_PLANES]; ++ ++ /* Number of lines to pre-fetch */ ++ unsigned int upm_buffer_lines; ++ + /* Set when the plane has per-pixel alpha content or does not cover + * the entire screen. This is a hint to the CRTC that it might need + * to enable background color fill. +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -67,6 +67,80 @@ static const struct debugfs_reg32 vc4_hv + VC4_REG32(SCALER_OLEDCOEF2), + }; + ++static const struct debugfs_reg32 vc6_hvs_regs[] = { ++ VC4_REG32(SCALER6_VERSION), ++ VC4_REG32(SCALER6_CXM_SIZE), ++ VC4_REG32(SCALER6_LBM_SIZE), ++ VC4_REG32(SCALER6_UBM_SIZE), ++ VC4_REG32(SCALER6_COBA_SIZE), ++ VC4_REG32(SCALER6_COB_SIZE), ++ VC4_REG32(SCALER6_CONTROL), ++ VC4_REG32(SCALER6_FETCHER_STATUS), ++ VC4_REG32(SCALER6_FETCH_STATUS), ++ VC4_REG32(SCALER6_HANDLE_ERROR), ++ VC4_REG32(SCALER6_DISP0_CTRL0), ++ VC4_REG32(SCALER6_DISP0_CTRL1), ++ VC4_REG32(SCALER6_DISP0_BGND), ++ VC4_REG32(SCALER6_DISP0_LPTRS), ++ VC4_REG32(SCALER6_DISP0_COB), ++ VC4_REG32(SCALER6_DISP0_STATUS), ++ VC4_REG32(SCALER6_DISP0_DL), ++ VC4_REG32(SCALER6_DISP0_RUN), ++ VC4_REG32(SCALER6_DISP1_CTRL0), ++ VC4_REG32(SCALER6_DISP1_CTRL1), ++ VC4_REG32(SCALER6_DISP1_BGND), ++ VC4_REG32(SCALER6_DISP1_LPTRS), ++ VC4_REG32(SCALER6_DISP1_COB), ++ VC4_REG32(SCALER6_DISP1_STATUS), ++ VC4_REG32(SCALER6_DISP1_DL), ++ VC4_REG32(SCALER6_DISP1_RUN), ++ VC4_REG32(SCALER6_DISP2_CTRL0), ++ VC4_REG32(SCALER6_DISP2_CTRL1), ++ VC4_REG32(SCALER6_DISP2_BGND), ++ VC4_REG32(SCALER6_DISP2_LPTRS), ++ VC4_REG32(SCALER6_DISP2_COB), ++ VC4_REG32(SCALER6_DISP2_STATUS), ++ VC4_REG32(SCALER6_DISP2_DL), ++ VC4_REG32(SCALER6_DISP2_RUN), ++ VC4_REG32(SCALER6_EOLN), ++ VC4_REG32(SCALER6_DL_STATUS), ++ VC4_REG32(SCALER6_BFG_MISC), ++ VC4_REG32(SCALER6_QOS0), ++ VC4_REG32(SCALER6_PROF0), ++ VC4_REG32(SCALER6_QOS1), ++ VC4_REG32(SCALER6_PROF1), ++ VC4_REG32(SCALER6_QOS2), ++ VC4_REG32(SCALER6_PROF2), ++ VC4_REG32(SCALER6_PRI_MAP0), ++ VC4_REG32(SCALER6_PRI_MAP1), ++ VC4_REG32(SCALER6_HISTCTRL), ++ VC4_REG32(SCALER6_HISTBIN0), ++ VC4_REG32(SCALER6_HISTBIN1), ++ VC4_REG32(SCALER6_HISTBIN2), ++ VC4_REG32(SCALER6_HISTBIN3), ++ VC4_REG32(SCALER6_HISTBIN4), ++ VC4_REG32(SCALER6_HISTBIN5), ++ VC4_REG32(SCALER6_HISTBIN6), ++ VC4_REG32(SCALER6_HISTBIN7), ++ VC4_REG32(SCALER6_HDR_CFG_REMAP), ++ VC4_REG32(SCALER6_COL_SPACE), ++ VC4_REG32(SCALER6_HVS_ID), ++ VC4_REG32(SCALER6_CFC1), ++ VC4_REG32(SCALER6_DISP_UPM_ISO0), ++ VC4_REG32(SCALER6_DISP_UPM_ISO1), ++ VC4_REG32(SCALER6_DISP_UPM_ISO2), ++ VC4_REG32(SCALER6_DISP_LBM_ISO0), ++ VC4_REG32(SCALER6_DISP_LBM_ISO1), ++ VC4_REG32(SCALER6_DISP_LBM_ISO2), ++ VC4_REG32(SCALER6_DISP_COB_ISO0), ++ VC4_REG32(SCALER6_DISP_COB_ISO1), ++ VC4_REG32(SCALER6_DISP_COB_ISO2), ++ VC4_REG32(SCALER6_BAD_COB), ++ VC4_REG32(SCALER6_BAD_LBM), ++ VC4_REG32(SCALER6_BAD_UPM), ++ VC4_REG32(SCALER6_BAD_AXI), ++}; ++ + void vc4_hvs_dump_state(struct vc4_hvs *hvs) + { + struct drm_device *drm = &hvs->vc4->base; +@@ -145,6 +219,55 @@ static int vc4_hvs_debugfs_dlist(struct + return 0; + } + ++static int vc6_hvs_debugfs_dlist(struct seq_file *m, void *data) ++{ ++ struct drm_info_node *node = m->private; ++ struct drm_device *dev = node->minor->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ struct vc4_hvs *hvs = vc4->hvs; ++ struct drm_printer p = drm_seq_file_printer(m); ++ unsigned int dlist_mem_size = hvs->dlist_mem_size; ++ unsigned int next_entry_start; ++ unsigned int i; ++ ++ for (i = 0; i < SCALER_CHANNELS_COUNT; i++) { ++ unsigned int active_dlist, dispstat; ++ unsigned int j; ++ ++ dispstat = VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_STATUS(i)), ++ SCALER6_DISPX_STATUS_MODE); ++ if (dispstat == SCALER6_DISPX_STATUS_MODE_DISABLED || ++ dispstat == SCALER6_DISPX_STATUS_MODE_EOF) { ++ drm_printf(&p, "HVS chan %u disabled\n", i); ++ continue; ++ } ++ ++ drm_printf(&p, "HVS chan %u:\n", i); ++ ++ active_dlist = VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_DL(i)), ++ SCALER6_DISPX_DL_LACT); ++ next_entry_start = 0; ++ ++ for (j = active_dlist; j < dlist_mem_size; j++) { ++ u32 dlist_word; ++ ++ dlist_word = readl((u32 __iomem *)vc4->hvs->dlist + j); ++ drm_printf(&p, "dlist: %02d: 0x%08x\n", j, ++ dlist_word); ++ if (!next_entry_start || ++ next_entry_start == j) { ++ if (dlist_word & SCALER_CTL0_END) ++ break; ++ next_entry_start = j + ++ VC4_GET_FIELD(dlist_word, ++ SCALER_CTL0_SIZE); ++ } ++ } ++ } ++ ++ return 0; ++} ++ + static int vc5_hvs_debugfs_gamma(struct seq_file *m, void *data) + { + struct drm_info_node *node = m->private; +@@ -435,6 +558,10 @@ static void vc4_hvs_irq_enable_eof(struc + SCALER5_DISPCTRL_DSPEIEOF(channel)); + break; + ++ case VC4_GEN_6: ++ enable_irq(hvs->eof_irq[channel].desc); ++ break; ++ + default: + break; + } +@@ -463,6 +590,10 @@ static void vc4_hvs_irq_clear_eof(struct + ~SCALER5_DISPCTRL_DSPEIEOF(channel)); + break; + ++ case VC4_GEN_6: ++ disable_irq_nosync(hvs->eof_irq[channel].desc); ++ break; ++ + default: + break; + } +@@ -622,26 +753,32 @@ static void vc4_hvs_dlist_free_work(stru + + u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + u8 field = 0; + int idx; + + if (!drm_dev_enter(drm, &idx)) + return 0; + +- switch (fifo) { +- case 0: +- field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), +- SCALER_DISPSTAT1_FRCNT0); +- break; +- case 1: +- field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), +- SCALER_DISPSTAT1_FRCNT1); +- break; +- case 2: +- field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT2), +- SCALER_DISPSTAT2_FRCNT2); +- break; ++ if (vc4->gen >= VC4_GEN_6) { ++ field = VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_STATUS(fifo)), ++ SCALER6_DISPX_STATUS_FRCNT); ++ } else { ++ switch (fifo) { ++ case 0: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), ++ SCALER_DISPSTAT1_FRCNT0); ++ break; ++ case 1: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), ++ SCALER_DISPSTAT1_FRCNT1); ++ break; ++ case 2: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT2), ++ SCALER_DISPSTAT2_FRCNT2); ++ break; ++ } + } + + drm_dev_exit(idx); +@@ -708,6 +845,23 @@ int vc4_hvs_get_fifo_from_output(struct + default: + return -EPIPE; + } ++ ++ case VC4_GEN_6: ++ switch (output) { ++ case 0: ++ return 0; ++ ++ case 2: ++ return 2; ++ ++ case 1: ++ case 3: ++ case 4: ++ return 1; ++ ++ default: ++ return -EPIPE; ++ } + } + + return -EPIPE; +@@ -782,7 +936,41 @@ static int vc4_hvs_init_channel(struct v + return 0; + } + +-void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) ++static int vc6_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc, ++ struct drm_display_mode *mode, bool oneshot) ++{ ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; ++ struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state); ++ unsigned int chan = vc4_crtc_state->assigned_channel; ++ bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; ++ u32 disp_ctrl1; ++ int idx; ++ ++ if (!drm_dev_enter(drm, &idx)) ++ return -ENODEV; ++ ++ HVS_WRITE(SCALER6_DISPX_CTRL0(chan), SCALER6_DISPX_CTRL0_RESET); ++ ++ disp_ctrl1 = HVS_READ(SCALER6_DISPX_CTRL1(chan)); ++ disp_ctrl1 &= ~SCALER6_DISPX_CTRL1_INTLACE; ++ HVS_WRITE(SCALER6_DISPX_CTRL1(chan), ++ disp_ctrl1 | (interlace ? SCALER6_DISPX_CTRL1_INTLACE : 0)); ++ ++ HVS_WRITE(SCALER6_DISPX_CTRL0(chan), ++ SCALER6_DISPX_CTRL0_ENB | ++ VC4_SET_FIELD(mode->hdisplay - 1, ++ SCALER6_DISPX_CTRL0_FWIDTH) | ++ (oneshot ? SCALER6_DISPX_CTRL0_ONESHOT : 0) | ++ VC4_SET_FIELD(mode->vdisplay - 1, ++ SCALER6_DISPX_CTRL0_LINES)); ++ ++ drm_dev_exit(idx); ++ ++ return 0; ++} ++ ++static void __vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) + { + struct drm_device *drm = &hvs->vc4->base; + int idx; +@@ -813,6 +1001,42 @@ out: + drm_dev_exit(idx); + } + ++static void __vc6_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) ++{ ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; ++ int idx; ++ ++ if (!drm_dev_enter(drm, &idx)) ++ return; ++ ++ if (HVS_READ(SCALER6_DISPX_CTRL0(chan)) & SCALER6_DISPX_CTRL0_ENB) ++ goto out; ++ ++ HVS_WRITE(SCALER6_DISPX_CTRL0(chan), ++ HVS_READ(SCALER6_DISPX_CTRL0(chan)) | SCALER6_DISPX_CTRL0_RESET); ++ ++ HVS_WRITE(SCALER6_DISPX_CTRL0(chan), ++ HVS_READ(SCALER6_DISPX_CTRL0(chan)) & ~SCALER6_DISPX_CTRL0_ENB); ++ ++ WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_STATUS(chan)), ++ SCALER6_DISPX_STATUS_MODE) != ++ SCALER6_DISPX_STATUS_MODE_DISABLED); ++ ++out: ++ drm_dev_exit(idx); ++} ++ ++void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) ++{ ++ struct vc4_dev *vc4 = hvs->vc4; ++ ++ if (vc4->gen >= VC4_GEN_6) ++ __vc6_hvs_stop_channel(hvs, chan); ++ else ++ __vc4_hvs_stop_channel(hvs, chan); ++} ++ + static int vc4_hvs_gamma_check(struct drm_crtc *crtc, + struct drm_atomic_state *state) + { +@@ -907,8 +1131,14 @@ static void vc4_hvs_install_dlist(struct + return; + + WARN_ON(!vc4_state->mm); +- HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel), +- vc4_state->mm->mm_node.start); ++ ++ if (vc4->gen >= VC4_GEN_6) ++ HVS_WRITE(SCALER6_DISPX_LPTRS(vc4_state->assigned_channel), ++ VC4_SET_FIELD(vc4_state->mm->mm_node.start, ++ SCALER6_DISPX_LPTRS_HEADE)); ++ else ++ HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel), ++ vc4_state->mm->mm_node.start); + + drm_dev_exit(idx); + } +@@ -965,7 +1195,11 @@ void vc4_hvs_atomic_enable(struct drm_cr + + vc4_hvs_install_dlist(crtc); + vc4_hvs_update_dlist(crtc); +- vc4_hvs_init_channel(vc4->hvs, crtc, mode, oneshot); ++ ++ if (vc4->gen >= VC4_GEN_6) ++ vc6_hvs_init_channel(vc4->hvs, crtc, mode, oneshot); ++ else ++ vc4_hvs_init_channel(vc4->hvs, crtc, mode, oneshot); + } + + void vc4_hvs_atomic_disable(struct drm_crtc *crtc, +@@ -1052,13 +1286,28 @@ void vc4_hvs_atomic_flush(struct drm_crt + WARN_ON(!vc4_state->mm); + WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm->mm_node.size); + +- if (enable_bg_fill) ++ if (enable_bg_fill) { + /* This sets a black background color fill, as is the case + * with other DRM drivers. + */ +- HVS_WRITE(SCALER_DISPBKGNDX(channel), +- HVS_READ(SCALER_DISPBKGNDX(channel)) | +- SCALER_DISPBKGND_FILL); ++ if (vc4->gen >= VC4_GEN_6) ++ HVS_WRITE(SCALER6_DISPX_CTRL1(channel), ++ HVS_READ(SCALER6_DISPX_CTRL1(channel)) | ++ SCALER6_DISPX_CTRL1_BGENB); ++ else ++ HVS_WRITE(SCALER_DISPBKGNDX(channel), ++ HVS_READ(SCALER_DISPBKGNDX(channel)) | ++ SCALER_DISPBKGND_FILL); ++ } else { ++ if (vc4->gen >= VC4_GEN_6) ++ HVS_WRITE(SCALER6_DISPX_CTRL1(channel), ++ HVS_READ(SCALER6_DISPX_CTRL1(channel)) & ++ ~SCALER6_DISPX_CTRL1_BGENB); ++ else ++ HVS_WRITE(SCALER_DISPBKGNDX(channel), ++ HVS_READ(SCALER_DISPBKGNDX(channel)) & ++ ~SCALER_DISPBKGND_FILL); ++ } + + /* Only update DISPLIST if the CRTC was already running and is not + * being disabled. +@@ -1210,6 +1459,27 @@ static irqreturn_t vc4_hvs_irq_handler(i + return irqret; + } + ++static irqreturn_t vc6_hvs_eof_irq_handler(int irq, void *data) ++{ ++ struct drm_device *dev = data; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ struct vc4_hvs *hvs = vc4->hvs; ++ unsigned int i; ++ ++ for (i = 0; i < HVS_NUM_CHANNELS; i++) { ++ if (!hvs->eof_irq[i].enabled) ++ continue; ++ ++ if (hvs->eof_irq[i].desc != irq) ++ continue; ++ ++ vc4_hvs_schedule_dlist_sweep(hvs, i); ++ return IRQ_HANDLED; ++ } ++ ++ return IRQ_NONE; ++} ++ + int vc4_hvs_debugfs_init(struct drm_minor *minor) + { + struct drm_device *drm = minor->dev; +@@ -1232,8 +1502,10 @@ int vc4_hvs_debugfs_init(struct drm_mino + NULL); + } + +- ret = vc4_debugfs_add_file(minor, "hvs_dlists", +- vc4_hvs_debugfs_dlist, NULL); ++ if (vc4->gen >= VC4_GEN_6) ++ ret = vc4_debugfs_add_file(minor, "hvs_dlists", vc6_hvs_debugfs_dlist, NULL); ++ else ++ ret = vc4_debugfs_add_file(minor, "hvs_dlists", vc4_hvs_debugfs_dlist, NULL); + if (ret) + return ret; + +@@ -1256,6 +1528,9 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + { + struct drm_device *drm = &vc4->base; + struct vc4_hvs *hvs; ++ unsigned int dlist_start; ++ size_t dlist_size; ++ size_t lbm_size; + + hvs = drmm_kzalloc(drm, sizeof(*hvs), GFP_KERNEL); + if (!hvs) +@@ -1270,14 +1545,39 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + INIT_LIST_HEAD(&hvs->stale_dlist_entries); + INIT_WORK(&hvs->free_dlist_work, vc4_hvs_dlist_free_work); + +- /* Set up the HVS display list memory manager. We never +- * overwrite the setup from the bootloader (just 128b out of +- * our 16K), since we don't want to scramble the screen when +- * transitioning from the firmware's boot setup to runtime. +- */ +- drm_mm_init(&hvs->dlist_mm, +- HVS_BOOTLOADER_DLIST_END, +- (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END); ++ switch (vc4->gen) { ++ case VC4_GEN_4: ++ case VC4_GEN_5: ++ /* Set up the HVS display list memory manager. We never ++ * overwrite the setup from the bootloader (just 128b ++ * out of our 16K), since we don't want to scramble the ++ * screen when transitioning from the firmware's boot ++ * setup to runtime. ++ */ ++ dlist_start = HVS_BOOTLOADER_DLIST_END; ++ dlist_size = (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END; ++ break; ++ ++ case VC4_GEN_6: ++ dlist_start = HVS_BOOTLOADER_DLIST_END; ++ ++ /* ++ * If we are running a test, it means that we can't ++ * access a register. Use a plausible size then. ++ */ ++ if (!kunit_get_current_test()) ++ dlist_size = HVS_READ(SCALER6_CXM_SIZE); ++ else ++ dlist_size = 4096; ++ ++ break; ++ ++ default: ++ drm_err(drm, "Unknown VC4 generation: %d", vc4->gen); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ drm_mm_init(&hvs->dlist_mm, dlist_start, dlist_size); + + hvs->dlist_mem_size = dlist_size; + +@@ -1286,12 +1586,46 @@ struct vc4_hvs *__vc4_hvs_alloc(struct v + * between planes when they don't overlap on the screen, but + * for now we just allocate globally. + */ +- if (vc4->gen == VC4_GEN_4) ++ ++ switch (vc4->gen) { ++ case VC4_GEN_4: + /* 48k words of 2x12-bit pixels */ +- drm_mm_init(&hvs->lbm_mm, 0, 48 * 1024); +- else ++ lbm_size = 48 * SZ_1K; ++ break; ++ ++ case VC4_GEN_5: + /* 60k words of 4x12-bit pixels */ +- drm_mm_init(&hvs->lbm_mm, 0, 60 * 1024); ++ lbm_size = 60 * SZ_1K; ++ break; ++ ++ case VC4_GEN_6: ++ /* ++ * If we are running a test, it means that we can't ++ * access a register. Use a plausible size then. ++ */ ++ lbm_size = 1024; ++ break; ++ ++ default: ++ drm_err(drm, "Unknown VC4 generation: %d", vc4->gen); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ drm_mm_init(&hvs->lbm_mm, 0, lbm_size); ++ ++ if (vc4->gen >= VC4_GEN_6) { ++ ida_init(&hvs->upm_handles); ++ ++ /* ++ * NOTE: On BCM2712, the size can also be read through ++ * the SCALER_UBM_SIZE register. We would need to do a ++ * register access though, which we can't do with kunit ++ * that also uses this function to create its mock ++ * device. ++ */ ++ drm_mm_init(&hvs->upm_mm, 0, 1024 * HVS_UBM_WORD_SIZE); ++ } ++ + + vc4->hvs = hvs; + +@@ -1388,10 +1722,124 @@ static int vc4_hvs_hw_init(struct vc4_hv + return 0; + } + ++#define CFC1_N_NL_CSC_CTRL(x) (0xa000 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C00(x) (0xa008 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C01(x) (0xa00c + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C02(x) (0xa010 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C03(x) (0xa014 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C04(x) (0xa018 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C10(x) (0xa01c + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C11(x) (0xa020 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C12(x) (0xa024 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C13(x) (0xa028 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C14(x) (0xa02c + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C20(x) (0xa030 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C21(x) (0xa034 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C22(x) (0xa038 + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C23(x) (0xa03c + ((x) * 0x3000)) ++#define CFC1_N_MA_CSC_COEFF_C24(x) (0xa040 + ((x) * 0x3000)) ++ ++/* 4 S2.22 multiplication factors, and 1 S9.15 addititive element for each of 3 ++ * output components ++ */ ++struct vc6_csc_coeff_entry { ++ u32 csc[3][5]; ++}; ++ ++static const struct vc6_csc_coeff_entry csc_coeffs[2][3] = { ++ [DRM_COLOR_YCBCR_LIMITED_RANGE] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ .csc = { ++ { 0x004A8542, 0x0, 0x0066254A, 0x0, 0xFF908A0D }, ++ { 0x004A8542, 0xFFE6ED5D, 0xFFCBF856, 0x0, 0x0043C9A3 }, ++ { 0x004A8542, 0x00811A54, 0x0, 0x0, 0xFF759502 } ++ } ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ .csc = { ++ { 0x004A8542, 0x0, 0x0072BC44, 0x0, 0xFF83F312 }, ++ { 0x004A8542, 0xFFF25A22, 0xFFDDE4D0, 0x0, 0x00267064 }, ++ { 0x004A8542, 0x00873197, 0x0, 0x0, 0xFF6F7DC0 } ++ } ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ .csc = { ++ { 0x004A8542, 0x0, 0x006B4A17, 0x0, 0xFF8B653F }, ++ { 0x004A8542, 0xFFF402D9, 0xFFDDE4D0, 0x0, 0x0024C7AE }, ++ { 0x004A8542, 0x008912CC, 0x0, 0x0, 0xFF6D9C8B } ++ } ++ } ++ }, ++ [DRM_COLOR_YCBCR_FULL_RANGE] = { ++ [DRM_COLOR_YCBCR_BT601] = { ++ .csc = { ++ { 0x00400000, 0x0, 0x0059BA5E, 0x0, 0xFFA645A1 }, ++ { 0x00400000, 0xFFE9F9AC, 0xFFD24B97, 0x0, 0x0043BABB }, ++ { 0x00400000, 0x00716872, 0x0, 0x0, 0xFF8E978D } ++ } ++ }, ++ [DRM_COLOR_YCBCR_BT709] = { ++ .csc = { ++ { 0x00400000, 0x0, 0x0064C985, 0x0, 0xFF9B367A }, ++ { 0x00400000, 0xFFF402E1, 0xFFE20A40, 0x0, 0x0029F2DE }, ++ { 0x00400000, 0x0076C226, 0x0, 0x0, 0xFF893DD9 } ++ } ++ }, ++ [DRM_COLOR_YCBCR_BT2020] = { ++ .csc = { ++ { 0x00400000, 0x0, 0x005E3F14, 0x0, 0xFFA1C0EB }, ++ { 0x00400000, 0xFFF577F6, 0xFFDB580F, 0x0, 0x002F2FFA }, ++ { 0x00400000, 0x007868DB, 0x0, 0x0, 0xFF879724 } ++ } ++ } ++ } ++}; ++ ++static int vc6_hvs_hw_init(struct vc4_hvs *hvs) ++{ ++ const struct vc6_csc_coeff_entry *coeffs; ++ unsigned int i; ++ ++ HVS_WRITE(SCALER6_CONTROL, ++ SCALER6_CONTROL_HVS_EN | ++ VC4_SET_FIELD(8, SCALER6_CONTROL_PF_LINES) | ++ VC4_SET_FIELD(15, SCALER6_CONTROL_MAX_REQS)); ++ ++ /* Set HVS arbiter priority to max */ ++ HVS_WRITE(SCALER6_PRI_MAP0, 0xffffffff); ++ HVS_WRITE(SCALER6_PRI_MAP1, 0xffffffff); ++ ++ for (i = 0; i < 6; i++) { ++ coeffs = &csc_coeffs[i / 3][i % 3]; ++ ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C00(i), coeffs->csc[0][0]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C01(i), coeffs->csc[0][1]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C02(i), coeffs->csc[0][2]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C03(i), coeffs->csc[0][3]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C04(i), coeffs->csc[0][4]); ++ ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C10(i), coeffs->csc[1][0]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C11(i), coeffs->csc[1][1]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C12(i), coeffs->csc[1][2]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C13(i), coeffs->csc[1][3]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C14(i), coeffs->csc[1][4]); ++ ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C20(i), coeffs->csc[2][0]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C21(i), coeffs->csc[2][1]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C22(i), coeffs->csc[2][2]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C23(i), coeffs->csc[2][3]); ++ HVS_WRITE(CFC1_N_MA_CSC_COEFF_C24(i), coeffs->csc[2][4]); ++ ++ HVS_WRITE(CFC1_N_NL_CSC_CTRL(i), BIT(15)); ++ } ++ ++ return 0; ++} ++ + static int vc4_hvs_cob_init(struct vc4_hvs *hvs) + { + struct vc4_dev *vc4 = hvs->vc4; +- u32 reg, top; ++ u32 reg, top, base; + + /* + * Recompute Composite Output Buffer (COB) allocations for the +@@ -1452,6 +1900,31 @@ static int vc4_hvs_cob_init(struct vc4_h + HVS_WRITE(SCALER_DISPBASE0, reg); + break; + ++ case VC4_GEN_6: ++ #define VC6_COB_LINE_WIDTH 3840 ++ #define VC6_COB_NUM_LINES 4 ++ reg = 0; ++ top = 3840; ++ ++ HVS_WRITE(SCALER6_DISP2_COB, ++ VC4_SET_FIELD(top, SCALER6_DISPX_COB_TOP) | ++ VC4_SET_FIELD(base, SCALER6_DISPX_COB_BASE)); ++ ++ base = top + 16; ++ top += VC6_COB_LINE_WIDTH * VC6_COB_NUM_LINES; ++ ++ HVS_WRITE(SCALER6_DISP1_COB, ++ VC4_SET_FIELD(top, SCALER6_DISPX_COB_TOP) | ++ VC4_SET_FIELD(base, SCALER6_DISPX_COB_BASE)); ++ ++ base = top + 16; ++ top += VC6_COB_LINE_WIDTH * VC6_COB_NUM_LINES; ++ ++ HVS_WRITE(SCALER6_DISP0_COB, ++ VC4_SET_FIELD(top, SCALER6_DISPX_COB_TOP) | ++ VC4_SET_FIELD(base, SCALER6_DISPX_COB_BASE)); ++ break; ++ + default: + return -EINVAL; + } +@@ -1477,10 +1950,16 @@ static int vc4_hvs_bind(struct device *d + return PTR_ERR(hvs); + + hvs->regset.base = hvs->regs; +- hvs->regset.regs = vc4_hvs_regs; +- hvs->regset.nregs = ARRAY_SIZE(vc4_hvs_regs); + +- if (vc4->gen == VC4_GEN_5) { ++ if (vc4->gen >= VC4_GEN_6) { ++ hvs->regset.regs = vc6_hvs_regs; ++ hvs->regset.nregs = ARRAY_SIZE(vc6_hvs_regs); ++ } else { ++ hvs->regset.regs = vc4_hvs_regs; ++ hvs->regset.nregs = ARRAY_SIZE(vc4_hvs_regs); ++ } ++ ++ if (vc4->gen >= VC4_GEN_5) { + struct rpi_firmware *firmware; + struct device_node *node; + unsigned int max_rate; +@@ -1494,12 +1973,20 @@ static int vc4_hvs_bind(struct device *d + if (!firmware) + return -EPROBE_DEFER; + +- hvs->core_clk = devm_clk_get(&pdev->dev, NULL); ++ hvs->core_clk = devm_clk_get(&pdev->dev, ++ (vc4->gen >= VC4_GEN_6) ? "core" : NULL); + if (IS_ERR(hvs->core_clk)) { + dev_err(&pdev->dev, "Couldn't get core clock\n"); + return PTR_ERR(hvs->core_clk); + } + ++ hvs->disp_clk = devm_clk_get(&pdev->dev, ++ (vc4->gen >= VC4_GEN_6) ? "disp" : NULL); ++ if (IS_ERR(hvs->disp_clk)) { ++ dev_err(&pdev->dev, "Couldn't get disp clock\n"); ++ return PTR_ERR(hvs->disp_clk); ++ } ++ + max_rate = rpi_firmware_clk_get_max_rate(firmware, + RPI_FIRMWARE_CORE_CLK_ID); + rpi_firmware_put(firmware); +@@ -1516,14 +2003,51 @@ static int vc4_hvs_bind(struct device *d + dev_err(&pdev->dev, "Couldn't enable the core clock\n"); + return ret; + } ++ ++ ret = clk_prepare_enable(hvs->disp_clk); ++ if (ret) { ++ dev_err(&pdev->dev, "Couldn't enable the disp clock\n"); ++ return ret; ++ } + } + +- if (vc4->gen == VC4_GEN_4) +- hvs->dlist = hvs->regs + SCALER_DLIST_START; +- else ++ if (vc4->gen >= VC4_GEN_6) { ++ unsigned int i; ++ ++ for (i = 0; i < HVS_NUM_CHANNELS; i++) { ++ char irq_name[16]; ++ int irq; ++ ++ snprintf(irq_name, sizeof(irq_name), "ch%u-eof", i); ++ ++ irq = platform_get_irq_byname(pdev, irq_name); ++ if (irq < 0) { ++ dev_err(&pdev->dev, ++ "Couldn't get %s interrupt: %d\n", ++ irq_name, irq); ++ return irq; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, ++ irq, ++ vc6_hvs_eof_irq_handler, ++ IRQF_NO_AUTOEN, ++ dev_name(&pdev->dev), ++ drm); ++ ++ hvs->eof_irq[i].desc = irq; ++ } ++ } ++ ++ if (vc4->gen >= VC4_GEN_5) + hvs->dlist = hvs->regs + SCALER5_DLIST_START; ++ else ++ hvs->dlist = hvs->regs + SCALER_DLIST_START; + +- ret = vc4_hvs_hw_init(hvs); ++ if (vc4->gen >= VC4_GEN_6) ++ ret = vc6_hvs_hw_init(hvs); ++ else ++ ret = vc4_hvs_hw_init(hvs); + if (ret) + return ret; + +@@ -1540,10 +2064,12 @@ static int vc4_hvs_bind(struct device *d + if (ret) + return ret; + +- ret = devm_request_irq(dev, platform_get_irq(pdev, 0), +- vc4_hvs_irq_handler, 0, "vc4 hvs", drm); +- if (ret) +- return ret; ++ if (vc4->gen < VC4_GEN_6) { ++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), ++ vc4_hvs_irq_handler, 0, "vc4 hvs", drm); ++ if (ret) ++ return ret; ++ } + + return 0; + } +@@ -1568,6 +2094,7 @@ static void vc4_hvs_unbind(struct device + drm_mm_remove_node(node); + drm_mm_takedown(&vc4->hvs->lbm_mm); + ++ clk_disable_unprepare(hvs->disp_clk); + clk_disable_unprepare(hvs->core_clk); + + vc4->hvs = NULL; +@@ -1591,6 +2118,7 @@ static int vc4_hvs_dev_remove(struct pla + + static const struct of_device_id vc4_hvs_dt_match[] = { + { .compatible = "brcm,bcm2711-hvs" }, ++ { .compatible = "brcm,bcm2712-hvs" }, + { .compatible = "brcm,bcm2835-hvs" }, + {} + }; +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -329,17 +329,59 @@ static void vc5_hvs_pv_muxing_commit(str + } + } + ++static void vc6_hvs_pv_muxing_commit(struct vc4_dev *vc4, ++ struct drm_atomic_state *state) ++{ ++ struct vc4_hvs *hvs = vc4->hvs; ++ struct drm_crtc_state *crtc_state; ++ struct drm_crtc *crtc; ++ unsigned int i; ++ ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_6); ++ ++ for_each_new_crtc_in_state(state, crtc, crtc_state, i) { ++ struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); ++ struct vc4_encoder *vc4_encoder; ++ struct drm_encoder *encoder; ++ unsigned char mux; ++ u32 reg; ++ ++ if (!vc4_state->update_muxing) ++ continue; ++ ++ if (vc4_state->assigned_channel != 1) ++ continue; ++ ++ encoder = vc4_get_crtc_encoder(crtc, crtc_state); ++ vc4_encoder = to_vc4_encoder(encoder); ++ switch (vc4_encoder->type) { ++ case VC4_ENCODER_TYPE_HDMI1: ++ mux = 0; ++ break; ++ ++ case VC4_ENCODER_TYPE_TXP: ++ mux = 2; ++ break; ++ ++ default: ++ break; ++ } ++ ++ reg = HVS_READ(SCALER6_CONTROL); ++ HVS_WRITE(SCALER6_CONTROL, ++ (reg & ~SCALER6_CONTROL_DSP1_TARGET_MASK) | ++ VC4_SET_FIELD(mux, SCALER6_CONTROL_DSP1_TARGET)); ++ } ++} ++ + static void vc4_atomic_commit_tail(struct drm_atomic_state *state) + { + struct drm_device *dev = state->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; +- struct drm_crtc_state *new_crtc_state; + struct vc4_hvs_state *new_hvs_state; +- struct drm_crtc *crtc; + struct vc4_hvs_state *old_hvs_state; + unsigned int channel; +- int i; + + old_hvs_state = vc4_hvs_get_old_global_state(state); + if (WARN_ON(IS_ERR(old_hvs_state))) +@@ -349,14 +391,23 @@ static void vc4_atomic_commit_tail(struc + if (WARN_ON(IS_ERR(new_hvs_state))) + return; + +- for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { +- struct vc4_crtc_state *vc4_crtc_state; ++ if (vc4->gen < VC4_GEN_6) { ++ struct drm_crtc_state *new_crtc_state; ++ struct drm_crtc *crtc; ++ int i; ++ ++ for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { ++ struct vc4_crtc_state *vc4_crtc_state; + +- if (!new_crtc_state->commit || vc4->firmware_kms) +- continue; ++ if (vc4->firmware_kms) ++ continue; + +- vc4_crtc_state = to_vc4_crtc_state(new_crtc_state); +- vc4_hvs_mask_underrun(hvs, vc4_crtc_state->assigned_channel); ++ if (!new_crtc_state->commit) ++ continue; ++ ++ vc4_crtc_state = to_vc4_crtc_state(new_crtc_state); ++ vc4_hvs_mask_underrun(hvs, vc4_crtc_state->assigned_channel); ++ } + } + + for (channel = 0; channel < HVS_NUM_CHANNELS; channel++) { +@@ -378,7 +429,7 @@ static void vc4_atomic_commit_tail(struc + old_hvs_state->fifo_state[channel].pending_commit = NULL; + } + +- if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { ++ if (vc4->gen >= VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long state_rate = max(old_hvs_state->core_clock_rate, + new_hvs_state->core_clock_rate); + unsigned long core_rate = clamp_t(unsigned long, state_rate, +@@ -391,17 +442,32 @@ static void vc4_atomic_commit_tail(struc + * modeset. + */ + WARN_ON(clk_set_min_rate(hvs->core_clk, core_rate)); ++ WARN_ON(clk_set_min_rate(hvs->disp_clk, core_rate)); + } + + drm_atomic_helper_commit_modeset_disables(dev, state); + +- vc4_ctm_commit(vc4, state); ++ if (vc4->gen <= VC4_GEN_5) ++ vc4_ctm_commit(vc4, state); + + if (!vc4->firmware_kms) { +- if (vc4->gen == VC4_GEN_5) +- vc5_hvs_pv_muxing_commit(vc4, state); +- else ++ switch (vc4->gen) { ++ case VC4_GEN_4: + vc4_hvs_pv_muxing_commit(vc4, state); ++ break; ++ ++ case VC4_GEN_5: ++ vc5_hvs_pv_muxing_commit(vc4, state); ++ break; ++ ++ case VC4_GEN_6: ++ vc6_hvs_pv_muxing_commit(vc4, state); ++ break; ++ ++ default: ++ drm_err(dev, "Unknown VC4 generation: %d", vc4->gen); ++ break; ++ } + } + + drm_atomic_helper_commit_planes(dev, state, +@@ -417,7 +483,7 @@ static void vc4_atomic_commit_tail(struc + + drm_atomic_helper_cleanup_planes(dev, state); + +- if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { ++ if (vc4->gen >= VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long core_rate = min_t(unsigned long, + hvs->max_core_rate, + new_hvs_state->core_clock_rate); +@@ -429,6 +495,7 @@ static void vc4_atomic_commit_tail(struc + * requirements. + */ + WARN_ON(clk_set_min_rate(hvs->core_clk, core_rate)); ++ WARN_ON(clk_set_min_rate(hvs->disp_clk, core_rate)); + + drm_dbg(dev, "Core clock actual rate: %lu Hz\n", + clk_get_rate(hvs->core_clk)); +@@ -1081,7 +1148,10 @@ int vc4_kms_load(struct drm_device *dev) + return ret; + } + +- if (vc4->gen == VC4_GEN_5) { ++ if (vc4->gen >= VC4_GEN_6) { ++ dev->mode_config.max_width = 8192; ++ dev->mode_config.max_height = 8192; ++ } else if (vc4->gen >= VC4_GEN_5) { + dev->mode_config.max_width = 7680; + dev->mode_config.max_height = 7680; + } else { +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -279,6 +279,7 @@ static bool plane_enabled(struct drm_pla + static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) + { + struct vc4_plane_state *vc4_state; ++ unsigned int i; + + if (WARN_ON(!plane->state)) + return NULL; +@@ -288,6 +289,11 @@ static struct drm_plane_state *vc4_plane + return NULL; + + memset(&vc4_state->lbm, 0, sizeof(vc4_state->lbm)); ++ memset(&vc4_state->upm, 0, sizeof(vc4_state->upm)); ++ ++ for (i = 0; i < DRM_FORMAT_MAX_PLANES; i++) ++ vc4_state->upm_handle[i] = 0; ++ + vc4_state->dlist_initialized = 0; + + __drm_atomic_helper_plane_duplicate_state(plane, &vc4_state->base); +@@ -310,14 +316,30 @@ static void vc4_plane_destroy_state(stru + struct drm_plane_state *state) + { + struct vc4_dev *vc4 = to_vc4_dev(plane->dev); ++ struct vc4_hvs *hvs = vc4->hvs; + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ unsigned int i; + + if (drm_mm_node_allocated(&vc4_state->lbm)) { + unsigned long irqflags; + +- spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags); ++ spin_lock_irqsave(&hvs->mm_lock, irqflags); + drm_mm_remove_node(&vc4_state->lbm); +- spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); ++ spin_unlock_irqrestore(&hvs->mm_lock, irqflags); ++ } ++ ++ for (i = 0; i < DRM_FORMAT_MAX_PLANES; i++) { ++ unsigned long irqflags; ++ ++ if (!drm_mm_node_allocated(&vc4_state->upm[i])) ++ continue; ++ ++ spin_lock_irqsave(&hvs->mm_lock, irqflags); ++ drm_mm_remove_node(&vc4_state->upm[i]); ++ spin_unlock_irqrestore(&hvs->mm_lock, irqflags); ++ ++ if (vc4_state->upm_handle[i] > 0) ++ ida_free(&hvs->upm_handles, vc4_state->upm_handle[i]); + } + + kfree(vc4_state->dlist); +@@ -543,6 +565,11 @@ static void vc4_write_tpz(struct vc4_pla + recip = ~0 / scale; + + vc4_dlist_write(vc4_state, ++ /* ++ * The BCM2712 is lacking BIT(31) compared to ++ * the previous generations, but we don't use ++ * it. ++ */ + VC4_SET_FIELD(scale, SCALER_TPZ0_SCALE) | + VC4_SET_FIELD(0, SCALER_TPZ0_IPHASE)); + vc4_dlist_write(vc4_state, +@@ -590,10 +617,15 @@ static void vc4_write_ppf(struct vc4_pla + vc4_dlist_write(vc4_state, + SCALER_PPF_AGC | + VC4_SET_FIELD(scale, SCALER_PPF_SCALE) | ++ /* ++ * The register layout documentation is slightly ++ * different to setup the phase in the BCM2712, ++ * but they seem equivalent. ++ */ + VC4_SET_FIELD(phase, SCALER_PPF_IPHASE)); + } + +-static u32 vc4_lbm_size(struct drm_plane_state *state) ++static u32 __vc4_lbm_size(struct drm_plane_state *state) + { + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + struct vc4_dev *vc4 = to_vc4_dev(state->plane->dev); +@@ -641,6 +673,131 @@ static u32 vc4_lbm_size(struct drm_plane + return lbm; + } + ++static unsigned int vc4_lbm_words_per_component(const struct drm_plane_state *state, ++ unsigned int channel) ++{ ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ ++ switch (vc4_state->y_scaling[channel]) { ++ case VC4_SCALING_PPF: ++ return 4; ++ ++ case VC4_SCALING_TPZ: ++ return 2; ++ ++ default: ++ return 0; ++ } ++} ++ ++static unsigned int vc4_lbm_components(const struct drm_plane_state *state, ++ unsigned int channel) ++{ ++ const struct drm_format_info *info = state->fb->format; ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ ++ if (vc4_state->y_scaling[channel] == VC4_SCALING_NONE) ++ return 0; ++ ++ if (info->is_yuv) ++ return channel ? 2 : 1; ++ ++ if (info->has_alpha) ++ return 4; ++ ++ return 3; ++} ++ ++static unsigned int vc4_lbm_channel_size(const struct drm_plane_state *state, ++ unsigned int channel) ++{ ++ const struct drm_format_info *info = state->fb->format; ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ unsigned int channels_scaled = 0; ++ unsigned int components, words, wpc; ++ unsigned int width, lines; ++ unsigned int i; ++ ++ /* LBM is meant to use the smaller of source or dest width, but there ++ * is a issue with UV scaling that the size required for the second ++ * channel is based on the source width only. ++ */ ++ if (info->hsub > 1 && channel == 1) ++ width = state->src_w >> 16; ++ else ++ width = min(state->src_w >> 16, state->crtc_w); ++ width = round_up(width / info->hsub, 4); ++ ++ wpc = vc4_lbm_words_per_component(state, channel); ++ if (!wpc) ++ return 0; ++ ++ components = vc4_lbm_components(state, channel); ++ if (!components) ++ return 0; ++ ++ if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) ++ components -= 1; ++ ++ words = width * wpc * components; ++ ++ lines = DIV_ROUND_UP(words, 128 / info->hsub); ++ ++ for (i = 0; i < 2; i++) ++ if (vc4_state->y_scaling[channel] != VC4_SCALING_NONE) ++ channels_scaled++; ++ ++ if (channels_scaled == 1) ++ lines = lines / 2; ++ ++ return lines; ++} ++ ++static unsigned int __vc6_lbm_size(const struct drm_plane_state *state) ++{ ++ const struct drm_format_info *info = state->fb->format; ++ ++ if (info->hsub > 1) ++ return max(vc4_lbm_channel_size(state, 0), ++ vc4_lbm_channel_size(state, 1)); ++ else ++ return vc4_lbm_channel_size(state, 0); ++} ++ ++u32 vc4_lbm_size(struct drm_plane_state *state) ++{ ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ struct vc4_dev *vc4 = to_vc4_dev(state->plane->dev); ++ ++ /* LBM is not needed when there's no vertical scaling. */ ++ if (vc4_state->y_scaling[0] == VC4_SCALING_NONE && ++ vc4_state->y_scaling[1] == VC4_SCALING_NONE) ++ return 0; ++ ++ if (vc4->gen >= VC4_GEN_6) ++ return __vc6_lbm_size(state); ++ else ++ return __vc4_lbm_size(state); ++} ++ ++static size_t vc6_upm_size(const struct drm_plane_state *state, ++ unsigned int plane) ++{ ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ unsigned int stride = state->fb->pitches[plane]; ++ ++ /* ++ * TODO: This only works for raster formats, and is sub-optimal ++ * for buffers with a stride aligned on 32 bytes. ++ */ ++ unsigned int words_per_line = (stride + 62) / 32; ++ unsigned int fetch_region_size = words_per_line * 32; ++ unsigned int buffer_lines = 2 << vc4_state->upm_buffer_lines; ++ unsigned int buffer_size = fetch_region_size * buffer_lines; ++ ++ return ALIGN(buffer_size, HVS_UBM_WORD_SIZE); ++} ++ + static void vc4_write_scaling_parameters(struct drm_plane_state *state, + int channel) + { +@@ -744,6 +901,10 @@ static int vc4_plane_allocate_lbm(struct + if (!lbm_size) + return 0; + ++ /* ++ * NOTE: BCM2712 doesn't need to be aligned, since the size ++ * returned by vc4_lbm_size() is in words already. ++ */ + if (vc4->gen == VC4_GEN_5) + lbm_size = ALIGN(lbm_size, 64); + else if (vc4->gen == VC4_GEN_4) +@@ -781,6 +942,57 @@ static int vc4_plane_allocate_lbm(struct + return 0; + } + ++static int vc6_plane_allocate_upm(struct drm_plane_state *state) ++{ ++ const struct drm_format_info *info = state->fb->format; ++ struct drm_device *drm = state->plane->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct vc4_hvs *hvs = vc4->hvs; ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ unsigned int i; ++ int ret; ++ ++ WARN_ON_ONCE(vc4->gen < VC4_GEN_6); ++ ++ vc4_state->upm_buffer_lines = SCALER6_PTR0_UPM_BUFF_SIZE_2_LINES; ++ ++ for (i = 0; i < info->num_planes; i++) { ++ unsigned long irqflags; ++ size_t upm_size; ++ ++ upm_size = vc6_upm_size(state, i); ++ if (!upm_size) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&hvs->mm_lock, irqflags); ++ ret = drm_mm_insert_node_generic(&hvs->upm_mm, ++ &vc4_state->upm[i], ++ upm_size, HVS_UBM_WORD_SIZE, ++ 0, 0); ++ spin_unlock_irqrestore(&hvs->mm_lock, irqflags); ++ if (ret) { ++ drm_err(drm, "Failed to allocate UPM entry: %d\n", ret); ++ return ret; ++ } ++ ++ ret = ida_alloc_range(&hvs->upm_handles, 1, 32, GFP_KERNEL); ++ if (ret < 0) ++ return ret; ++ ++ vc4_state->upm_handle[i] = ret; ++ ++ vc4_state->dlist[vc4_state->ptr0_offset[i]] |= ++ VC4_SET_FIELD(vc4_state->upm[i].start / HVS_UBM_WORD_SIZE, ++ SCALER6_PTR0_UPM_BASE) | ++ VC4_SET_FIELD(vc4_state->upm_handle[i] - 1, ++ SCALER6_PTR0_UPM_HANDLE) | ++ VC4_SET_FIELD(vc4_state->upm_buffer_lines, ++ SCALER6_PTR0_UPM_BUFF_SIZE); ++ } ++ ++ return 0; ++} ++ + /* + * The colorspace conversion matrices are held in 3 entries in the dlist. + * Create an array of them, with entries for each full and limited mode, and +@@ -1355,6 +1567,413 @@ static int vc4_plane_mode_set(struct drm + return 0; + } + ++static u32 vc6_plane_get_csc_mode(struct vc4_plane_state *vc4_state) ++{ ++ struct drm_plane_state *state = &vc4_state->base; ++ u32 ret = 0; ++ ++ if (vc4_state->is_yuv) { ++ enum drm_color_encoding color_encoding = state->color_encoding; ++ enum drm_color_range color_range = state->color_range; ++ ++ ret |= SCALER6_CTL2_CSC_ENABLE; ++ ++ /* CSC pre-loaded with: ++ * 0 = BT601 limited range ++ * 1 = BT709 limited range ++ * 2 = BT2020 limited range ++ * 3 = BT601 full range ++ * 4 = BT709 full range ++ * 5 = BT2020 full range ++ */ ++ if (color_encoding > DRM_COLOR_YCBCR_BT2020) ++ color_encoding = DRM_COLOR_YCBCR_BT601; ++ if (color_range > DRM_COLOR_YCBCR_FULL_RANGE) ++ color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; ++ ++ ret |= VC4_SET_FIELD(color_encoding + (color_range * 3), ++ SCALER6_CTL2_BRCM_CFC_CONTROL); ++ } ++ ++ return ret; ++} ++ ++static int vc6_plane_mode_set(struct drm_plane *plane, ++ struct drm_plane_state *state) ++{ ++ struct drm_device *drm = plane->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); ++ struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); ++ struct drm_framebuffer *fb = state->fb; ++ const struct hvs_format *format = vc4_get_hvs_format(fb->format->format); ++ u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier); ++ int num_planes = fb->format->num_planes; ++ u32 h_subsample = fb->format->hsub; ++ u32 v_subsample = fb->format->vsub; ++ bool mix_plane_alpha; ++ bool covers_screen; ++ u32 scl0, scl1, pitch0; ++ u32 tiling, src_x, src_y; ++ u32 width, height; ++ u32 hvs_format = format->hvs; ++ u32 offsets[3] = { 0 }; ++ unsigned int rotation; ++ int ret, i; ++ ++ if (vc4_state->dlist_initialized) ++ return 0; ++ ++ ret = vc4_plane_setup_clipping_and_scaling(state); ++ if (ret) ++ return ret; ++ ++ width = vc4_state->src_w[0] >> 16; ++ height = vc4_state->src_h[0] >> 16; ++ ++ /* SCL1 is used for Cb/Cr scaling of planar formats. For RGB ++ * and 4:4:4, scl1 should be set to scl0 so both channels of ++ * the scaler do the same thing. For YUV, the Y plane needs ++ * to be put in channel 1 and Cb/Cr in channel 0, so we swap ++ * the scl fields here. ++ */ ++ if (num_planes == 1) { ++ scl0 = vc4_get_scl_field(state, 0); ++ scl1 = scl0; ++ } else { ++ scl0 = vc4_get_scl_field(state, 1); ++ scl1 = vc4_get_scl_field(state, 0); ++ } ++ ++ rotation = drm_rotation_simplify(state->rotation, ++ DRM_MODE_ROTATE_0 | ++ DRM_MODE_REFLECT_X | ++ DRM_MODE_REFLECT_Y); ++ ++ /* We must point to the last line when Y reflection is enabled. */ ++ src_y = vc4_state->src_y >> 16; ++ if (rotation & DRM_MODE_REFLECT_Y) ++ src_y += height - 1; ++ ++ src_x = vc4_state->src_x >> 16; ++ ++ switch (base_format_mod) { ++ case DRM_FORMAT_MOD_LINEAR: ++ tiling = SCALER6_CTL0_ADDR_MODE_LINEAR; ++ ++ /* Adjust the base pointer to the first pixel to be scanned ++ * out. ++ */ ++ for (i = 0; i < num_planes; i++) { ++ offsets[i] += src_y / (i ? v_subsample : 1) * fb->pitches[i]; ++ offsets[i] += src_x / (i ? h_subsample : 1) * fb->format->cpp[i]; ++ } ++ ++ break; ++ ++ case DRM_FORMAT_MOD_BROADCOM_SAND128: ++ case DRM_FORMAT_MOD_BROADCOM_SAND256: { ++ uint32_t param = fourcc_mod_broadcom_param(fb->modifier); ++ u32 components_per_word; ++ u32 starting_offset; ++ u32 fetch_count; ++ ++ if (param > SCALER_TILE_HEIGHT_MASK) { ++ DRM_DEBUG_KMS("SAND height too large (%d)\n", ++ param); ++ return -EINVAL; ++ } ++ ++ if (fb->format->format == DRM_FORMAT_P030) { ++ hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT; ++ tiling = SCALER6_CTL0_ADDR_MODE_128B; ++ } else { ++ hvs_format = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE; ++ ++ switch (base_format_mod) { ++ case DRM_FORMAT_MOD_BROADCOM_SAND128: ++ tiling = SCALER6_CTL0_ADDR_MODE_128B; ++ break; ++ case DRM_FORMAT_MOD_BROADCOM_SAND256: ++ tiling = SCALER6_CTL0_ADDR_MODE_256B; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ /* Adjust the base pointer to the first pixel to be scanned ++ * out. ++ * ++ * For P030, y_ptr [31:4] is the 128bit word for the start pixel ++ * y_ptr [3:0] is the pixel (0-11) contained within that 128bit ++ * word that should be taken as the first pixel. ++ * Ditto uv_ptr [31:4] vs [3:0], however [3:0] contains the ++ * element within the 128bit word, eg for pixel 3 the value ++ * should be 6. ++ */ ++ for (i = 0; i < num_planes; i++) { ++ u32 tile_w, tile, x_off, pix_per_tile; ++ ++ if (fb->format->format == DRM_FORMAT_P030) { ++ /* ++ * Spec says: bits [31:4] of the given address ++ * should point to the 128-bit word containing ++ * the desired starting pixel, and bits[3:0] ++ * should be between 0 and 11, indicating which ++ * of the 12-pixels in that 128-bit word is the ++ * first pixel to be used ++ */ ++ u32 remaining_pixels = src_x % 96; ++ u32 aligned = remaining_pixels / 12; ++ u32 last_bits = remaining_pixels % 12; ++ ++ x_off = aligned * 16 + last_bits; ++ tile_w = 128; ++ pix_per_tile = 96; ++ } else { ++ switch (base_format_mod) { ++ case DRM_FORMAT_MOD_BROADCOM_SAND128: ++ tile_w = 128; ++ break; ++ case DRM_FORMAT_MOD_BROADCOM_SAND256: ++ tile_w = 256; ++ break; ++ default: ++ return -EINVAL; ++ } ++ pix_per_tile = tile_w / fb->format->cpp[0]; ++ x_off = (src_x % pix_per_tile) / ++ (i ? h_subsample : 1) * ++ fb->format->cpp[i]; ++ } ++ ++ tile = src_x / pix_per_tile; ++ ++ offsets[i] += param * tile_w * tile; ++ offsets[i] += src_y / (i ? v_subsample : 1) * tile_w; ++ offsets[i] += x_off & ~(i ? 1 : 0); ++ } ++ ++ components_per_word = fb->format->format == DRM_FORMAT_P030 ? 24 : 32; ++ starting_offset = src_x % components_per_word; ++ fetch_count = (width + starting_offset + components_per_word - 1) / ++ components_per_word; ++ ++ pitch0 = VC4_SET_FIELD(param, SCALER6_PTR2_PITCH) | ++ VC4_SET_FIELD(fetch_count - 1, SCALER6_PTR2_FETCH_COUNT); ++ break; ++ } ++ ++ default: ++ DRM_DEBUG_KMS("Unsupported FB tiling flag 0x%16llx", ++ (long long)fb->modifier); ++ return -EINVAL; ++ } ++ ++ /* fetch an extra pixel if we don't actually line up with the left edge. */ ++ if ((vc4_state->src_x & 0xffff) && vc4_state->src_x < (state->fb->width << 16)) ++ width++; ++ ++ /* same for the right side */ ++ if (((vc4_state->src_x + vc4_state->src_w[0]) & 0xffff) && ++ vc4_state->src_x + vc4_state->src_w[0] < (state->fb->width << 16)) ++ width++; ++ ++ /* now for the top */ ++ if ((vc4_state->src_y & 0xffff) && vc4_state->src_y < (state->fb->height << 16)) ++ height++; ++ ++ /* and the bottom */ ++ if (((vc4_state->src_y + vc4_state->src_h[0]) & 0xffff) && ++ vc4_state->src_y + vc4_state->src_h[0] < (state->fb->height << 16)) ++ height++; ++ ++ /* for YUV444 hardware wants double the width, otherwise it doesn't ++ * fetch full width of chroma ++ */ ++ if (format->drm == DRM_FORMAT_YUV444 || format->drm == DRM_FORMAT_YVU444) ++ width <<= 1; ++ ++ /* Don't waste cycles mixing with plane alpha if the set alpha ++ * is opaque or there is no per-pixel alpha information. ++ * In any case we use the alpha property value as the fixed alpha. ++ */ ++ mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE && ++ fb->format->has_alpha; ++ ++ /* Control Word 0: Scaling Configuration & Element Validity*/ ++ vc4_dlist_write(vc4_state, ++ SCALER6_CTL0_VALID | ++ VC4_SET_FIELD(tiling, SCALER6_CTL0_ADDR_MODE) | ++ VC4_SET_FIELD(0, SCALER6_CTL0_ALPHA_MASK) | ++ (vc4_state->is_unity ? SCALER6_CTL0_UNITY : 0) | ++ VC4_SET_FIELD(format->pixel_order_hvs5, SCALER6_CTL0_ORDERRGBA) | ++ VC4_SET_FIELD(scl1, SCALER6_CTL0_SCL1_MODE) | ++ VC4_SET_FIELD(scl0, SCALER6_CTL0_SCL0_MODE) | ++ VC4_SET_FIELD(hvs_format, SCALER6_CTL0_PIXEL_FORMAT)); ++ ++ /* Position Word 0: Image Position */ ++ vc4_state->pos0_offset = vc4_state->dlist_count; ++ vc4_dlist_write(vc4_state, ++ VC4_SET_FIELD(vc4_state->crtc_y, SCALER6_POS0_START_Y) | ++ (rotation & DRM_MODE_REFLECT_X ? SCALER6_POS0_HFLIP : 0) | ++ VC4_SET_FIELD(vc4_state->crtc_x, SCALER6_POS0_START_X)); ++ ++ /* Control Word 2: Alpha Value & CSC */ ++ vc4_dlist_write(vc4_state, ++ vc6_plane_get_csc_mode(vc4_state) | ++ vc4_hvs5_get_alpha_blend_mode(state) | ++ (mix_plane_alpha ? SCALER6_CTL2_ALPHA_MIX : 0) | ++ VC4_SET_FIELD(state->alpha >> 4, SCALER5_CTL2_ALPHA)); ++ ++ /* Position Word 1: Scaled Image Dimensions */ ++ if (!vc4_state->is_unity) ++ vc4_dlist_write(vc4_state, ++ VC4_SET_FIELD(vc4_state->crtc_h - 1, ++ SCALER6_POS1_SCL_LINES) | ++ VC4_SET_FIELD(vc4_state->crtc_w - 1, ++ SCALER6_POS1_SCL_WIDTH)); ++ ++ /* Position Word 2: Source Image Size */ ++ vc4_state->pos2_offset = vc4_state->dlist_count; ++ vc4_dlist_write(vc4_state, ++ VC4_SET_FIELD(height - 1, ++ SCALER6_POS2_SRC_LINES) | ++ VC4_SET_FIELD(width - 1, ++ SCALER6_POS2_SRC_WIDTH)); ++ ++ /* Position Word 3: Context */ ++ vc4_dlist_write(vc4_state, 0xc0c0c0c0); ++ ++ /* ++ * TODO: This only covers Raster Scan Order planes ++ */ ++ for (i = 0; i < num_planes; i++) { ++ dma_addr_t paddr = drm_fb_dma_get_gem_addr(fb, state, i); ++ ++ paddr += offsets[i]; ++ ++ /* Pointer Word 0 */ ++ vc4_state->ptr0_offset[i] = vc4_state->dlist_count; ++ vc4_dlist_write(vc4_state, ++ (rotation & DRM_MODE_REFLECT_Y ? SCALER6_PTR0_VFLIP : 0) | ++ /* ++ * The UPM buffer will be allocated in ++ * vc6_plane_allocate_upm(). ++ */ ++ VC4_SET_FIELD(upper_32_bits(paddr) & 0xf, ++ SCALER6_PTR0_UPPER_ADDR)); ++ ++ /* Pointer Word 1 */ ++ vc4_dlist_write(vc4_state, lower_32_bits(paddr)); ++ ++ /* Pointer Word 2 */ ++ if (base_format_mod != DRM_FORMAT_MOD_BROADCOM_SAND128 && ++ base_format_mod != DRM_FORMAT_MOD_BROADCOM_SAND256) { ++ vc4_dlist_write(vc4_state, ++ VC4_SET_FIELD(fb->pitches[i], ++ SCALER6_PTR2_PITCH)); ++ } else { ++ vc4_dlist_write(vc4_state, pitch0); ++ } ++ } ++ ++ /* ++ * Palette Word 0 ++ * TODO: We're not using the palette mode ++ */ ++ ++ /* ++ * Trans Word 0 ++ * TODO: It's only relevant if we set the trans_rgb bit in the ++ * control word 0, and we don't at the moment. ++ */ ++ ++ vc4_state->lbm_offset = 0; ++ ++ if (!vc4_state->is_unity || fb->format->is_yuv) { ++ /* ++ * Reserve a slot for the LBM Base Address. The real value will ++ * be set when calling vc4_plane_allocate_lbm(). ++ */ ++ if (vc4_state->y_scaling[0] != VC4_SCALING_NONE || ++ vc4_state->y_scaling[1] != VC4_SCALING_NONE) { ++ vc4_state->lbm_offset = vc4_state->dlist_count; ++ vc4_dlist_counter_increment(vc4_state); ++ } ++ ++ if (vc4_state->x_scaling[0] != VC4_SCALING_NONE || ++ vc4_state->x_scaling[1] != VC4_SCALING_NONE || ++ vc4_state->y_scaling[0] != VC4_SCALING_NONE || ++ vc4_state->y_scaling[1] != VC4_SCALING_NONE) { ++ if (num_planes > 1) ++ /* ++ * Emit Cb/Cr as channel 0 and Y as channel ++ * 1. This matches how we set up scl0/scl1 ++ * above. ++ */ ++ vc4_write_scaling_parameters(state, 1); ++ ++ vc4_write_scaling_parameters(state, 0); ++ } ++ ++ /* ++ * If any PPF setup was done, then all the kernel ++ * pointers get uploaded. ++ */ ++ if (vc4_state->x_scaling[0] == VC4_SCALING_PPF || ++ vc4_state->y_scaling[0] == VC4_SCALING_PPF || ++ vc4_state->x_scaling[1] == VC4_SCALING_PPF || ++ vc4_state->y_scaling[1] == VC4_SCALING_PPF) { ++ u32 kernel = ++ VC4_SET_FIELD(vc4->hvs->mitchell_netravali_filter.start, ++ SCALER_PPF_KERNEL_OFFSET); ++ ++ /* HPPF plane 0 */ ++ vc4_dlist_write(vc4_state, kernel); ++ /* VPPF plane 0 */ ++ vc4_dlist_write(vc4_state, kernel); ++ /* HPPF plane 1 */ ++ vc4_dlist_write(vc4_state, kernel); ++ /* VPPF plane 1 */ ++ vc4_dlist_write(vc4_state, kernel); ++ } ++ } ++ ++ vc4_dlist_write(vc4_state, SCALER6_CTL0_END); ++ ++ vc4_state->dlist[0] |= ++ VC4_SET_FIELD(vc4_state->dlist_count, SCALER6_CTL0_NEXT); ++ ++ /* crtc_* are already clipped coordinates. */ ++ covers_screen = vc4_state->crtc_x == 0 && vc4_state->crtc_y == 0 && ++ vc4_state->crtc_w == state->crtc->mode.hdisplay && ++ vc4_state->crtc_h == state->crtc->mode.vdisplay; ++ ++ /* ++ * Background fill might be necessary when the plane has per-pixel ++ * alpha content or a non-opaque plane alpha and could blend from the ++ * background or does not cover the entire screen. ++ */ ++ vc4_state->needs_bg_fill = fb->format->has_alpha || !covers_screen || ++ state->alpha != DRM_BLEND_ALPHA_OPAQUE; ++ ++ /* ++ * Flag the dlist as initialized to avoid checking it twice in case ++ * the async update check already called vc4_plane_mode_set() and ++ * decided to fallback to sync update because async update was not ++ * possible. ++ */ ++ vc4_state->dlist_initialized = 1; ++ ++ vc4_plane_calc_load(state); ++ ++ drm_dbg_driver(drm, "[PLANE:%d:%s] Computed DLIST size: %u\n", ++ plane->base.id, plane->name, vc4_state->dlist_count); ++ ++ return 0; ++} ++ + /* If a modeset involves changing the setup of a plane, the atomic + * infrastructure will call this to validate a proposed plane setup. + * However, if a plane isn't getting updated, this (and the +@@ -1365,6 +1984,7 @@ static int vc4_plane_mode_set(struct drm + static int vc4_plane_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *state) + { ++ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, + plane); + struct vc4_plane_state *vc4_state = to_vc4_plane_state(new_plane_state); +@@ -1375,7 +1995,10 @@ static int vc4_plane_atomic_check(struct + if (!plane_enabled(new_plane_state)) + return 0; + +- ret = vc4_plane_mode_set(plane, new_plane_state); ++ if (vc4->gen >= VC4_GEN_6) ++ ret = vc6_plane_mode_set(plane, new_plane_state); ++ else ++ ret = vc4_plane_mode_set(plane, new_plane_state); + if (ret) + return ret; + +@@ -1383,6 +2006,12 @@ static int vc4_plane_atomic_check(struct + if (ret) + return ret; + ++ if (vc4->gen >= VC4_GEN_6) { ++ ret = vc6_plane_allocate_upm(new_plane_state); ++ if (ret) ++ return ret; ++ } ++ + return 0; + } + +@@ -1716,7 +2345,7 @@ struct drm_plane *vc4_plane_init(struct + }; + + for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { +- if (!hvs_formats[i].hvs5_only || vc4->gen == VC4_GEN_5) { ++ if (!hvs_formats[i].hvs5_only || vc4->gen >= VC4_GEN_5) { + formats[num_formats] = hvs_formats[i].drm; + num_formats++; + } +@@ -1731,7 +2360,7 @@ struct drm_plane *vc4_plane_init(struct + return ERR_CAST(vc4_plane); + plane = &vc4_plane->base; + +- if (vc4->gen == VC4_GEN_5) ++ if (vc4->gen >= VC4_GEN_5) + drm_plane_helper_add(plane, &vc5_plane_helper_funcs); + else + drm_plane_helper_add(plane, &vc4_plane_helper_funcs); +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -536,6 +536,130 @@ + + #define SCALER5_DLIST_START 0x00004000 + ++#define SCALER6_VERSION 0x00000000 ++#define SCALER6_CXM_SIZE 0x00000004 ++#define SCALER6_LBM_SIZE 0x00000008 ++#define SCALER6_UBM_SIZE 0x0000000c ++#define SCALER6_COBA_SIZE 0x00000010 ++#define SCALER6_COB_SIZE 0x00000014 ++ ++#define SCALER6_CONTROL 0x00000020 ++# define SCALER6_CONTROL_HVS_EN BIT(31) ++# define SCALER6_CONTROL_PF_LINES_MASK VC4_MASK(22, 18) ++# define SCALER6_CONTROL_ABORT_ON_EMPTY BIT(16) ++# define SCALER6_CONTROL_DSP1_TARGET_MASK VC4_MASK(13, 12) ++# define SCALER6_CONTROL_MAX_REQS_MASK VC4_MASK(7, 4) ++ ++#define SCALER6_FETCHER_STATUS 0x00000024 ++#define SCALER6_FETCH_STATUS 0x00000028 ++#define SCALER6_HANDLE_ERROR 0x0000002c ++ ++#define SCALER6_DISP0_CTRL0 0x00000030 ++#define SCALER6_DISPX_CTRL0(x) \ ++ (SCALER6_DISP0_CTRL0 + ((x) * (SCALER6_DISP1_CTRL0 - SCALER6_DISP0_CTRL0))) ++# define SCALER6_DISPX_CTRL0_ENB BIT(31) ++# define SCALER6_DISPX_CTRL0_RESET BIT(30) ++# define SCALER6_DISPX_CTRL0_FWIDTH_MASK VC4_MASK(28, 16) ++# define SCALER6_DISPX_CTRL0_ONESHOT BIT(15) ++# define SCALER6_DISPX_CTRL0_ONECTX_MASK VC4_MASK(14, 13) ++# define SCALER6_DISPX_CTRL0_LINES_MASK VC4_MASK(12, 0) ++ ++#define SCALER6_DISP0_CTRL1 0x00000034 ++#define SCALER6_DISPX_CTRL1(x) \ ++ (SCALER6_DISP0_CTRL1 + ((x) * (SCALER6_DISP1_CTRL1 - SCALER6_DISP0_CTRL1))) ++# define SCALER6_DISPX_CTRL1_BGENB BIT(8) ++# define SCALER6_DISPX_CTRL1_INTLACE BIT(0) ++ ++#define SCALER6_DISP0_BGND 0x00000038 ++#define SCALER6_DISPX_BGND(x) \ ++ (SCALER6_DISP0_BGND + ((x) * (SCALER6_DISP1_BGND - SCALER6_DISP0_BGND))) ++ ++#define SCALER6_DISP0_LPTRS 0x0000003c ++#define SCALER6_DISPX_LPTRS(x) \ ++ (SCALER6_DISP0_LPTRS + ((x) * (SCALER6_DISP1_LPTRS - SCALER6_DISP0_LPTRS))) ++# define SCALER6_DISPX_LPTRS_HEADE_MASK VC4_MASK(11, 0) ++ ++#define SCALER6_DISP0_COB 0x00000040 ++#define SCALER6_DISPX_COB(x) \ ++ (SCALER6_DISP0_COB + ((x) * (SCALER6_DISP1_COB - SCALER6_DISP0_COB))) ++# define SCALER6_DISPX_COB_TOP_MASK VC4_MASK(31, 16) ++# define SCALER6_DISPX_COB_BASE_MASK VC4_MASK(15, 0) ++ ++#define SCALER6_DISP0_STATUS 0x00000044 ++ ++#define SCALER6_DISPX_STATUS(x) \ ++ (SCALER6_DISP0_STATUS + ((x) * (SCALER6_DISP1_STATUS - SCALER6_DISP0_STATUS))) ++# define SCALER6_DISPX_STATUS_EMPTY BIT(22) ++# define SCALER6_DISPX_STATUS_FRCNT_MASK VC4_MASK(21, 16) ++# define SCALER6_DISPX_STATUS_OFIELD BIT(15) ++# define SCALER6_DISPX_STATUS_MODE_MASK VC4_MASK(14, 13) ++# define SCALER6_DISPX_STATUS_MODE_DISABLED 0 ++# define SCALER6_DISPX_STATUS_MODE_INIT 1 ++# define SCALER6_DISPX_STATUS_MODE_RUN 2 ++# define SCALER6_DISPX_STATUS_MODE_EOF 3 ++# define SCALER6_DISPX_STATUS_YLINE_MASK VC4_MASK(12, 0) ++ ++#define SCALER6_DISP0_DL 0x00000048 ++ ++#define SCALER6_DISPX_DL(x) \ ++ (SCALER6_DISP0_DL + ((x) * (SCALER6_DISP1_DL - SCALER6_DISP0_DL))) ++# define SCALER6_DISPX_DL_LACT_MASK VC4_MASK(11, 0) ++ ++#define SCALER6_DISP0_RUN 0x0000004c ++#define SCALER6_DISP1_CTRL0 0x00000050 ++#define SCALER6_DISP1_CTRL1 0x00000054 ++#define SCALER6_DISP1_BGND 0x00000058 ++#define SCALER6_DISP1_LPTRS 0x0000005c ++#define SCALER6_DISP1_COB 0x00000060 ++#define SCALER6_DISP1_STATUS 0x00000064 ++#define SCALER6_DISP1_DL 0x00000068 ++#define SCALER6_DISP1_RUN 0x0000006c ++#define SCALER6_DISP2_CTRL0 0x00000070 ++#define SCALER6_DISP2_CTRL1 0x00000074 ++#define SCALER6_DISP2_BGND 0x00000078 ++#define SCALER6_DISP2_LPTRS 0x0000007c ++#define SCALER6_DISP2_COB 0x00000080 ++#define SCALER6_DISP2_STATUS 0x00000084 ++#define SCALER6_DISP2_DL 0x00000088 ++#define SCALER6_DISP2_RUN 0x0000008c ++#define SCALER6_EOLN 0x00000090 ++#define SCALER6_DL_STATUS 0x00000094 ++#define SCALER6_BFG_MISC 0x0000009c ++#define SCALER6_QOS0 0x000000a0 ++#define SCALER6_PROF0 0x000000a4 ++#define SCALER6_QOS1 0x000000a8 ++#define SCALER6_PROF1 0x000000ac ++#define SCALER6_QOS2 0x000000b0 ++#define SCALER6_PROF2 0x000000b4 ++#define SCALER6_PRI_MAP0 0x000000b8 ++#define SCALER6_PRI_MAP1 0x000000bc ++#define SCALER6_HISTCTRL 0x000000c0 ++#define SCALER6_HISTBIN0 0x000000c4 ++#define SCALER6_HISTBIN1 0x000000c8 ++#define SCALER6_HISTBIN2 0x000000cc ++#define SCALER6_HISTBIN3 0x000000d0 ++#define SCALER6_HISTBIN4 0x000000d4 ++#define SCALER6_HISTBIN5 0x000000d8 ++#define SCALER6_HISTBIN6 0x000000dc ++#define SCALER6_HISTBIN7 0x000000e0 ++#define SCALER6_HDR_CFG_REMAP 0x000000f4 ++#define SCALER6_COL_SPACE 0x000000f8 ++#define SCALER6_HVS_ID 0x000000fc ++#define SCALER6_CFC1 0x00000100 ++#define SCALER6_DISP_UPM_ISO0 0x00000200 ++#define SCALER6_DISP_UPM_ISO1 0x00000204 ++#define SCALER6_DISP_UPM_ISO2 0x00000208 ++#define SCALER6_DISP_LBM_ISO0 0x0000020c ++#define SCALER6_DISP_LBM_ISO1 0x00000210 ++#define SCALER6_DISP_LBM_ISO2 0x00000214 ++#define SCALER6_DISP_COB_ISO0 0x00000218 ++#define SCALER6_DISP_COB_ISO1 0x0000021c ++#define SCALER6_DISP_COB_ISO2 0x00000220 ++#define SCALER6_BAD_COB 0x00000224 ++#define SCALER6_BAD_LBM 0x00000228 ++#define SCALER6_BAD_UPM 0x0000022c ++#define SCALER6_BAD_AXI 0x00000230 ++ + # define VC4_HDMI_SW_RESET_FORMAT_DETECT BIT(1) + # define VC4_HDMI_SW_RESET_HDMI BIT(0) + +@@ -1131,4 +1255,61 @@ enum hvs_pixel_format { + #define SCALER_PITCH0_TILE_WIDTH_R_MASK VC4_MASK(6, 0) + #define SCALER_PITCH0_TILE_WIDTH_R_SHIFT 0 + ++#define SCALER6_CTL0_END BIT(31) ++#define SCALER6_CTL0_VALID BIT(30) ++#define SCALER6_CTL0_NEXT_MASK VC4_MASK(29, 24) ++#define SCALER6_CTL0_RGB_TRANS BIT(23) ++#define SCALER6_CTL0_ADDR_MODE_MASK VC4_MASK(22, 20) ++#define SCALER6_CTL0_ADDR_MODE_LINEAR 0 ++#define SCALER6_CTL0_ADDR_MODE_128B 1 ++#define SCALER6_CTL0_ADDR_MODE_256B 2 ++#define SCALER6_CTL0_ADDR_MODE_MAP8 3 ++#define SCALER6_CTL0_ADDR_MODE_UIF 4 ++ ++#define SCALER6_CTL0_ALPHA_MASK_MASK VC4_MASK(19, 18) ++#define SCALER6_CTL0_UNITY BIT(15) ++#define SCALER6_CTL0_ORDERRGBA_MASK VC4_MASK(14, 13) ++#define SCALER6_CTL0_SCL1_MODE_MASK VC4_MASK(10, 8) ++#define SCALER6_CTL0_SCL0_MODE_MASK VC4_MASK(7, 5) ++#define SCALER6_CTL0_PIXEL_FORMAT_MASK VC4_MASK(4, 0) ++ ++#define SCALER6_POS0_START_Y_MASK VC4_MASK(28, 16) ++#define SCALER6_POS0_HFLIP BIT(15) ++#define SCALER6_POS0_START_X_MASK VC4_MASK(12, 0) ++ ++#define SCALER6_CTL2_ALPHA_MODE_MASK VC4_MASK(31, 30) ++#define SCALER6_CTL2_ALPHA_PREMULT BIT(29) ++#define SCALER6_CTL2_ALPHA_MIX BIT(28) ++#define SCALER6_CTL2_BFG BIT(26) ++#define SCALER6_CTL2_CSC_ENABLE BIT(25) ++#define SCALER6_CTL2_BRCM_CFC_CONTROL_MASK VC4_MASK(18, 16) ++#define SCALER6_CTL2_ALPHA_MASK VC4_MASK(15, 4) ++ ++#define SCALER6_POS1_SCL_LINES_MASK VC4_MASK(28, 16) ++#define SCALER6_POS1_SCL_WIDTH_MASK VC4_MASK(12, 0) ++ ++#define SCALER6_POS2_SRC_LINES_MASK VC4_MASK(28, 16) ++#define SCALER6_POS2_SRC_WIDTH_MASK VC4_MASK(12, 0) ++ ++#define SCALER6_PTR0_VFLIP BIT(31) ++#define SCALER6_PTR0_UPM_BASE_MASK VC4_MASK(28, 16) ++#define SCALER6_PTR0_UPM_HANDLE_MASK VC4_MASK(14, 10) ++#define SCALER6_PTR0_UPM_BUFF_SIZE_MASK VC4_MASK(9, 8) ++#define SCALER6_PTR0_UPM_BUFF_SIZE_16_LINES 3 ++#define SCALER6_PTR0_UPM_BUFF_SIZE_8_LINES 2 ++#define SCALER6_PTR0_UPM_BUFF_SIZE_4_LINES 1 ++#define SCALER6_PTR0_UPM_BUFF_SIZE_2_LINES 0 ++#define SCALER6_PTR0_UPPER_ADDR_MASK VC4_MASK(7, 0) ++ ++#define SCALER6_PTR2_ALPHA_BPP_MASK VC4_MASK(31, 31) ++#define SCALER6_PTR2_ALPHA_BPP_1BPP 1 ++#define SCALER6_PTR2_ALPHA_BPP_8BPP 0 ++#define SCALER6_PTR2_ALPHA_ORDER_MASK VC4_MASK(30, 30) ++#define SCALER6_PTR2_ALPHA_ORDER_MSB_TO_LSB 1 ++#define SCALER6_PTR2_ALPHA_ORDER_LSB_TO_MSB 0 ++#define SCALER6_PTR2_ALPHA_OFFS_MASK VC4_MASK(29, 27) ++#define SCALER6_PTR2_LSKIP_MASK VC4_MASK(26, 24) ++#define SCALER6_PTR2_PITCH_MASK VC4_MASK(16, 0) ++#define SCALER6_PTR2_FETCH_COUNT_MASK VC4_MASK(26, 16) ++ + #endif /* VC4_REGS_H */ diff --git a/target/linux/bcm27xx/patches-6.1/950-0964-drm-vc4-crtc-Add-support-for-BCM2712-PixelValves.patch b/target/linux/bcm27xx/patches-6.1/950-0964-drm-vc4-crtc-Add-support-for-BCM2712-PixelValves.patch new file mode 100644 index 0000000000..1870158e06 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0964-drm-vc4-crtc-Add-support-for-BCM2712-PixelValves.patch @@ -0,0 +1,144 @@ +From 000f1b7d4dc5b515c755ee25db301e26bded00e1 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:33:23 +0100 +Subject: [PATCH] drm/vc4: crtc: Add support for BCM2712 PixelValves + +The PixelValves found on the BCM2712 are similar to the ones found in +the previous generation. + +Compared to BCM2711, the pixelvalves only drive one HDMI controller each +and HDMI1 PixelValve has a FIFO long enough to support 4k at 60Hz. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 53 ++++++++++++++++++++++++++++++++-- + drivers/gpu/drm/vc4/vc4_drv.h | 2 ++ + drivers/gpu/drm/vc4/vc4_regs.h | 5 ++++ + 3 files changed, 58 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -239,6 +239,11 @@ static u32 vc4_get_fifo_full_level(struc + const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc); + const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc); + struct vc4_dev *vc4 = to_vc4_dev(vc4_crtc->base.dev); ++ ++ /* ++ * NOTE: Could we use register 0x68 (PV_HW_CFG1) to get the FIFO ++ * size? ++ */ + u32 fifo_len_bytes = pv_data->fifo_depth; + + /* +@@ -393,6 +398,12 @@ static void vc4_crtc_config_pv(struct dr + + vc4_crtc_pixelvalve_reset(crtc); + ++ /* ++ * NOTE: The BCM2712 has a H_OTE (Horizontal Odd Timing Enable) ++ * bit that, when set, will allow to specify the timings in ++ * pixels instead of cycles, thus allowing to specify odd ++ * timings. ++ */ + CRTC_WRITE(PV_HORZA, + VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc, + PV_HORZA_HBP) | +@@ -462,11 +473,17 @@ static void vc4_crtc_config_pv(struct dr + if (is_dsi) + CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); + +- if (vc4->gen == VC4_GEN_5) ++ if (vc4->gen >= VC4_GEN_5) + CRTC_WRITE(PV_MUX_CFG, + VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP, + PV_MUX_CFG_RGB_PIXEL_MUX_MODE)); + ++ if (vc4->gen >= VC4_GEN_6) ++ CRTC_WRITE(PV_PIPE_INIT_CTRL, ++ VC4_SET_FIELD(1, PV_PIPE_INIT_CTRL_PV_INIT_WIDTH) | ++ VC4_SET_FIELD(1, PV_PIPE_INIT_CTRL_PV_INIT_IDLE) | ++ PV_PIPE_INIT_CTRL_PV_INIT_EN); ++ + CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR | + vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) | + VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | +@@ -565,7 +582,11 @@ int vc4_crtc_disable_at_boot(struct drm_ + if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node, + "brcm,bcm2711-pixelvalve2") || + of_device_is_compatible(vc4_crtc->pdev->dev.of_node, +- "brcm,bcm2711-pixelvalve4"))) ++ "brcm,bcm2711-pixelvalve4") || ++ of_device_is_compatible(vc4_crtc->pdev->dev.of_node, ++ "brcm,bcm2712-pixelvalve0") || ++ of_device_is_compatible(vc4_crtc->pdev->dev.of_node, ++ "brcm,bcm2712-pixelvalve1"))) + return 0; + + if (!(CRTC_READ(PV_CONTROL) & PV_CONTROL_EN)) +@@ -1304,6 +1325,32 @@ const struct vc4_pv_data bcm2711_pv4_dat + }, + }; + ++const struct vc4_pv_data bcm2712_pv0_data = { ++ .base = { ++ .debugfs_name = "crtc0_regs", ++ .hvs_available_channels = BIT(0), ++ .hvs_output = 0, ++ }, ++ .fifo_depth = 64, ++ .pixels_per_clock = 2, ++ .encoder_types = { ++ [0] = VC4_ENCODER_TYPE_HDMI0, ++ }, ++}; ++ ++const struct vc4_pv_data bcm2712_pv1_data = { ++ .base = { ++ .debugfs_name = "crtc1_regs", ++ .hvs_available_channels = BIT(1), ++ .hvs_output = 1, ++ }, ++ .fifo_depth = 64, ++ .pixels_per_clock = 2, ++ .encoder_types = { ++ [0] = VC4_ENCODER_TYPE_HDMI1, ++ }, ++}; ++ + static const struct of_device_id vc4_crtc_dt_match[] = { + { .compatible = "brcm,bcm2835-pixelvalve0", .data = &bcm2835_pv0_data }, + { .compatible = "brcm,bcm2835-pixelvalve1", .data = &bcm2835_pv1_data }, +@@ -1313,6 +1360,8 @@ static const struct of_device_id vc4_crt + { .compatible = "brcm,bcm2711-pixelvalve2", .data = &bcm2711_pv2_data }, + { .compatible = "brcm,bcm2711-pixelvalve3", .data = &bcm2711_pv3_data }, + { .compatible = "brcm,bcm2711-pixelvalve4", .data = &bcm2711_pv4_data }, ++ { .compatible = "brcm,bcm2712-pixelvalve0", .data = &bcm2712_pv0_data }, ++ { .compatible = "brcm,bcm2712-pixelvalve1", .data = &bcm2712_pv1_data }, + {} + }; + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -583,6 +583,8 @@ extern const struct vc4_pv_data bcm2711_ + extern const struct vc4_pv_data bcm2711_pv2_data; + extern const struct vc4_pv_data bcm2711_pv3_data; + extern const struct vc4_pv_data bcm2711_pv4_data; ++extern const struct vc4_pv_data bcm2712_pv0_data; ++extern const struct vc4_pv_data bcm2712_pv1_data; + + struct vc5_gamma_entry { + u32 x_c_terms; +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -215,6 +215,11 @@ + # define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_SHIFT 2 + # define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP 8 + ++#define PV_PIPE_INIT_CTRL 0x94 ++# define PV_PIPE_INIT_CTRL_PV_INIT_WIDTH_MASK VC4_MASK(11, 8) ++# define PV_PIPE_INIT_CTRL_PV_INIT_IDLE_MASK VC4_MASK(7, 4) ++# define PV_PIPE_INIT_CTRL_PV_INIT_EN BIT(0) ++ + #define SCALER_CHANNELS_COUNT 3 + + #define SCALER_DISPCTRL 0x00000000 diff --git a/target/linux/bcm27xx/patches-6.1/950-0965-drm-vc4-hdmi-Add-support-for-BCM2712-HDMI-controller.patch b/target/linux/bcm27xx/patches-6.1/950-0965-drm-vc4-hdmi-Add-support-for-BCM2712-HDMI-controller.patch new file mode 100644 index 0000000000..7cb4e5661d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0965-drm-vc4-hdmi-Add-support-for-BCM2712-HDMI-controller.patch @@ -0,0 +1,1057 @@ +From 1bb54596ae2a9a36f4aa9f8f2ba941320f463811 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 15:34:30 +0100 +Subject: [PATCH] drm/vc4: hdmi: Add support for BCM2712 HDMI controllers + +The HDMI controllers found in the BCM2712 are largely the ones found in +the BCM2711 with a different PHY. + +There's some difference with how timings are split between registers, +and HDMI1 is now able to run at 4k/60Hz. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 82 +++- + drivers/gpu/drm/vc4/vc4_hdmi.h | 4 + + drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 640 ++++++++++++++++++++++++++++ + drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 217 ++++++++++ + 4 files changed, 937 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -1127,6 +1127,7 @@ static void vc4_hdmi_encoder_post_crtc_d + { + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct drm_device *drm = vc4_hdmi->connector.dev; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); + unsigned long flags; + int idx; + +@@ -1143,14 +1144,25 @@ static void vc4_hdmi_encoder_post_crtc_d + + HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_CLRRGB); + ++ if (vc4->gen >= VC4_GEN_6) ++ HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | ++ VC4_HD_VID_CTL_BLANKPIX); ++ + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + + mdelay(1); + +- spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); +- HDMI_WRITE(HDMI_VID_CTL, +- HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); +- spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ /* ++ * TODO: This should work on BCM2712, but doesn't for some ++ * reason and result in a system lockup. ++ */ ++ if (vc4->gen < VC4_GEN_6) { ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ HDMI_WRITE(HDMI_VID_CTL, ++ HDMI_READ(HDMI_VID_CTL) & ++ ~VC4_HD_VID_CTL_ENABLE); ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++ } + + vc4_hdmi_disable_scrambling(encoder); + +@@ -1757,7 +1769,6 @@ static void vc4_hdmi_encoder_pre_crtc_co + goto err_put_runtime_pm; + } + +- + vc4_hdmi_cec_update_clk_div(vc4_hdmi); + + if (tmds_char_rate > 297000000) +@@ -1862,6 +1873,7 @@ static void vc4_hdmi_encoder_post_crtc_e + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); + + HDMI_WRITE(HDMI_VID_CTL, ++ HDMI_READ(HDMI_VID_CTL) | + VC4_HD_VID_CTL_ENABLE | + VC4_HD_VID_CTL_CLRRGB | + VC4_HD_VID_CTL_UNDERFLOW_ENABLE | +@@ -3796,7 +3808,9 @@ static int vc4_hdmi_bind(struct device * + return ret; + + if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") || +- of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) && ++ of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1") || ++ of_device_is_compatible(dev->of_node, "brcm,bcm2712-hdmi0") || ++ of_device_is_compatible(dev->of_node, "brcm,bcm2712-hdmi1")) && + HDMI_READ(HDMI_VID_CTL) & VC4_HD_VID_CTL_ENABLE) { + clk_prepare_enable(vc4_hdmi->pixel_clock); + clk_prepare_enable(vc4_hdmi->hsm_clock); +@@ -3931,10 +3945,66 @@ static const struct vc4_hdmi_variant bcm + .hp_detect = vc5_hdmi_hp_detect, + }; + ++static const struct vc4_hdmi_variant bcm2712_hdmi0_variant = { ++ .encoder_type = VC4_ENCODER_TYPE_HDMI0, ++ .debugfs_name = "hdmi0_regs", ++ .card_name = "vc4-hdmi-0", ++ .max_pixel_clock = 600000000, ++ .registers = vc6_hdmi_hdmi0_fields, ++ .num_registers = ARRAY_SIZE(vc6_hdmi_hdmi0_fields), ++ .phy_lane_mapping = { ++ PHY_LANE_0, ++ PHY_LANE_1, ++ PHY_LANE_2, ++ PHY_LANE_CK, ++ }, ++ .unsupported_odd_h_timings = true, ++ .external_irq_controller = true, ++ ++ .init_resources = vc5_hdmi_init_resources, ++ .csc_setup = vc5_hdmi_csc_setup, ++ .reset = vc5_hdmi_reset, ++ .set_timings = vc5_hdmi_set_timings, ++ .phy_init = vc6_hdmi_phy_init, ++ .phy_disable = vc6_hdmi_phy_disable, ++ .channel_map = vc5_hdmi_channel_map, ++ .supports_hdr = true, ++ .hp_detect = vc5_hdmi_hp_detect, ++}; ++ ++static const struct vc4_hdmi_variant bcm2712_hdmi1_variant = { ++ .encoder_type = VC4_ENCODER_TYPE_HDMI1, ++ .debugfs_name = "hdmi1_regs", ++ .card_name = "vc4-hdmi-1", ++ .max_pixel_clock = 600000000, ++ .registers = vc6_hdmi_hdmi1_fields, ++ .num_registers = ARRAY_SIZE(vc6_hdmi_hdmi1_fields), ++ .phy_lane_mapping = { ++ PHY_LANE_0, ++ PHY_LANE_1, ++ PHY_LANE_2, ++ PHY_LANE_CK, ++ }, ++ .unsupported_odd_h_timings = true, ++ .external_irq_controller = true, ++ ++ .init_resources = vc5_hdmi_init_resources, ++ .csc_setup = vc5_hdmi_csc_setup, ++ .reset = vc5_hdmi_reset, ++ .set_timings = vc5_hdmi_set_timings, ++ .phy_init = vc6_hdmi_phy_init, ++ .phy_disable = vc6_hdmi_phy_disable, ++ .channel_map = vc5_hdmi_channel_map, ++ .supports_hdr = true, ++ .hp_detect = vc5_hdmi_hp_detect, ++}; ++ + static const struct of_device_id vc4_hdmi_dt_match[] = { + { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant }, + { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant }, + { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant }, ++ { .compatible = "brcm,bcm2712-hdmi0", .data = &bcm2712_hdmi0_variant }, ++ { .compatible = "brcm,bcm2712-hdmi1", .data = &bcm2712_hdmi1_variant }, + {} + }; + +--- a/drivers/gpu/drm/vc4/vc4_hdmi.h ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.h +@@ -284,4 +284,8 @@ void vc5_hdmi_phy_disable(struct vc4_hdm + void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); + void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); + ++void vc6_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, ++ struct vc4_hdmi_connector_state *vc4_conn_state); ++void vc6_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); ++ + #endif /* _VC4_HDMI_H_ */ +--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c +@@ -125,6 +125,48 @@ + #define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT 24 + #define VC4_HDMI_RM_FORMAT_SHIFT_MASK VC4_MASK(25, 24) + ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BG_PWRUP BIT(8) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_LDO_PWRUP BIT(7) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BIAS_PWRUP BIT(6) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_RNDGEN_PWRUP BIT(4) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_CK_PWRUP BIT(3) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_2_PWRUP BIT(2) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_1_PWRUP BIT(1) ++#define VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_0_PWRUP BIT(0) ++ ++#define VC6_HDMI_TX_PHY_PLL_REFCLK_REFCLK_SEL_CMOS BIT(13) ++#define VC6_HDMI_TX_PHY_PLL_REFCLK_REFFRQ_MASK VC4_MASK(9, 0) ++ ++#define VC6_HDMI_TX_PHY_PLL_POST_KDIV_CLK0_SEL_MASK VC4_MASK(3, 2) ++#define VC6_HDMI_TX_PHY_PLL_POST_KDIV_KDIV_MASK VC4_MASK(1, 0) ++ ++#define VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV_EN BIT(10) ++#define VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV_MASK VC4_MASK(9, 0) ++ ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL_MASK VC4_MASK(31, 28) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE_MASK VC4_MASK(27, 27) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL_MASK VC4_MASK(26, 26) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN_MASK VC4_MASK(25, 25) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL_MASK VC4_MASK(24, 23) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN_MASK VC4_MASK(22, 22) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL_MASK VC4_MASK(21, 21) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN_MASK VC4_MASK(20, 20) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL_MASK VC4_MASK(19, 18) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN_MASK VC4_MASK(17, 17) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN_MASK VC4_MASK(16, 16) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL_MASK VC4_MASK(15, 12) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN_MASK VC4_MASK(11, 11) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT_MASK VC4_MASK(10, 8) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT_MASK VC4_MASK(7, 5) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING_MASK VC4_MASK(4, 3) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING_MASK VC4_MASK(2, 1) ++#define VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN_MASK VC4_MASK(0, 0) ++ ++#define VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_PLLPOST_RESETB BIT(1) ++#define VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_RESETB BIT(0) ++ ++#define VC6_HDMI_TX_PHY_PLL_POWERUP_CTL_PLL_PWRUP BIT(0) ++ + #define OSCILLATOR_FREQUENCY 54000000 + + void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, +@@ -558,3 +600,601 @@ void vc5_hdmi_phy_rng_disable(struct vc4 + VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + } ++ ++#define VC6_VCO_MIN_FREQ (8ULL * 1000 * 1000 * 1000) ++#define VC6_VCO_MAX_FREQ (12ULL * 1000 * 1000 * 1000) ++ ++static unsigned long long ++vc6_phy_get_vco_freq(unsigned long long tmds_rate, unsigned int *vco_div) ++{ ++ unsigned int min_div; ++ unsigned int max_div; ++ unsigned int div; ++ ++ div = 0; ++ while (tmds_rate * div * 10 < VC6_VCO_MIN_FREQ) ++ div++; ++ min_div = div; ++ ++ while (tmds_rate * (div + 1) * 10 < VC6_VCO_MAX_FREQ) ++ div++; ++ max_div = div; ++ ++ div = min_div + (max_div - min_div) / 2; ++ ++ *vco_div = div; ++ return tmds_rate * div * 10; ++} ++ ++struct vc6_phy_lane_settings { ++ unsigned int ext_current_ctl:4; ++ unsigned int ffe_enable:1; ++ unsigned int slew_rate_ctl:1; ++ unsigned int ffe_post_tap_en:1; ++ unsigned int ldmos_bias_ctl:2; ++ unsigned int com_mode_ldmos_en:1; ++ unsigned int edge_sel:1; ++ unsigned int ext_current_src_hs_en:1; ++ unsigned int term_ctl:2; ++ unsigned int ext_current_src_en:1; ++ unsigned int int_current_src_en:1; ++ unsigned int int_current_ctl:4; ++ unsigned int int_current_src_hs_en:1; ++ unsigned int main_tap_current_select:3; ++ unsigned int post_tap_current_select:3; ++ unsigned int slew_ctl_slow_loading:2; ++ unsigned int slew_ctl_slow_driving:2; ++ unsigned int ffe_pre_tap_en:1; ++}; ++ ++struct vc6_phy_settings { ++ unsigned long long min_rate; ++ unsigned long long max_rate; ++ struct vc6_phy_lane_settings channel[3]; ++ struct vc6_phy_lane_settings clock; ++}; ++ ++static const struct vc6_phy_settings vc6_hdmi_phy_settings[] = { ++ { ++ 0, 222000000, ++ { ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ }, ++ { ++ 222000001, 297000000, ++ { ++ { ++ /* 200mA and 180mA ?! */ ++ .ext_current_ctl = 12, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 100 Ohm */ ++ .term_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ }, ++ { ++ /* 200mA and 180mA ?! */ ++ .ext_current_ctl = 12, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 100 Ohm */ ++ .term_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ }, ++ { ++ /* 200mA and 180mA ?! */ ++ .ext_current_ctl = 12, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 100 Ohm */ ++ .term_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ }, ++ }, ++ { ++ /* 200mA and 180mA ?! */ ++ .ext_current_ctl = 12, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 100 Ohm */ ++ .term_ctl = 1, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ ++ /* Internal Current Source Half Swing Enable*/ ++ .int_current_src_hs_en = 1, ++ }, ++ }, ++ { ++ 297000001, 597000044, ++ { ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* Normal Slew Rate Control */ ++ .slew_rate_ctl = 1, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 50 Ohms */ ++ .term_ctl = 3, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* Normal Slew Rate Control */ ++ .slew_rate_ctl = 1, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 50 Ohms */ ++ .term_ctl = 3, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* Normal Slew Rate Control */ ++ .slew_rate_ctl = 1, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* 50 Ohms */ ++ .term_ctl = 3, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ }, ++ { ++ /* 200mA */ ++ .ext_current_ctl = 8, ++ ++ /* Normal Slew Rate Control */ ++ .slew_rate_ctl = 1, ++ ++ /* 0.85V */ ++ .ldmos_bias_ctl = 1, ++ ++ /* External Current Source Half Swing Enable*/ ++ .ext_current_src_hs_en = 1, ++ ++ /* 50 Ohms */ ++ .term_ctl = 3, ++ ++ /* Enable External Current Source */ ++ .ext_current_src_en = 1, ++ ++ /* Enable Internal Current Source */ ++ .int_current_src_en = 1, ++ ++ /* 200mA */ ++ .int_current_ctl = 8, ++ ++ /* Internal Current Source Half Swing Enable*/ ++ .int_current_src_hs_en = 1, ++ ++ /* 17.6 mA */ ++ .main_tap_current_select = 7, ++ }, ++ }, ++}; ++ ++static const struct vc6_phy_settings * ++vc6_phy_get_settings(unsigned long long tmds_rate) ++{ ++ unsigned int count = ARRAY_SIZE(vc6_hdmi_phy_settings); ++ unsigned int i; ++ ++ for (i = 0; i < count; i++) { ++ const struct vc6_phy_settings *s = &vc6_hdmi_phy_settings[i]; ++ ++ if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate) ++ return s; ++ } ++ ++ /* ++ * If the pixel clock exceeds our max setting, try the max ++ * setting anyway. ++ */ ++ return &vc6_hdmi_phy_settings[count - 1]; ++} ++ ++static const struct vc6_phy_lane_settings * ++vc6_phy_get_channel_settings(enum vc4_hdmi_phy_channel chan, ++ unsigned long long tmds_rate) ++{ ++ const struct vc6_phy_settings *settings = vc6_phy_get_settings(tmds_rate); ++ ++ if (chan == PHY_LANE_CK) ++ return &settings->clock; ++ ++ return &settings->channel[chan]; ++} ++ ++static void vc6_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi) ++{ ++ lockdep_assert_held(&vc4_hdmi->hw_lock); ++ ++ HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0); ++ HDMI_WRITE(HDMI_TX_PHY_POWERUP_CTL, 0); ++} ++ ++void vc6_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, ++ struct vc4_hdmi_connector_state *conn_state) ++{ ++ const struct vc6_phy_lane_settings *chan0_settings; ++ const struct vc6_phy_lane_settings *chan1_settings; ++ const struct vc6_phy_lane_settings *chan2_settings; ++ const struct vc6_phy_lane_settings *clock_settings; ++ const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; ++ unsigned long long pixel_freq = conn_state->tmds_char_rate; ++ unsigned long long vco_freq; ++ unsigned char word_sel; ++ unsigned long flags; ++ unsigned int vco_div; ++ ++ vco_freq = vc6_phy_get_vco_freq(pixel_freq, &vco_div); ++ ++ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); ++ ++ vc6_hdmi_reset_phy(vc4_hdmi); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_0, 0x810c6000); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_1, 0x00b8c451); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_2, 0x46402e31); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_3, 0x00b8c005); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_4, 0x42410261); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_5, 0xcc021001); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_6, 0xc8301c80); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_7, 0xb0804444); ++ HDMI_WRITE(HDMI_TX_PHY_PLL_MISC_8, 0xf80f8000); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_REFCLK, ++ VC6_HDMI_TX_PHY_PLL_REFCLK_REFCLK_SEL_CMOS | ++ VC4_SET_FIELD(54, VC6_HDMI_TX_PHY_PLL_REFCLK_REFFRQ)); ++ ++ HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x7f); ++ ++ HDMI_WRITE(HDMI_RM_OFFSET, ++ VC4_HDMI_RM_OFFSET_ONLY | ++ VC4_SET_FIELD(phy_get_rm_offset(vco_freq), ++ VC4_HDMI_RM_OFFSET_OFFSET)); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_VCOCLK_DIV, ++ VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV_EN | ++ VC4_SET_FIELD(vco_div, ++ VC6_HDMI_TX_PHY_PLL_VCOCLK_DIV_VCODIV)); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_CFG, ++ VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CFG_PDIV)); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_POST_KDIV, ++ VC4_SET_FIELD(2, VC6_HDMI_TX_PHY_PLL_POST_KDIV_CLK0_SEL) | ++ VC4_SET_FIELD(1, VC6_HDMI_TX_PHY_PLL_POST_KDIV_KDIV)); ++ ++ chan0_settings = ++ vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0], ++ pixel_freq); ++ HDMI_WRITE(HDMI_TX_PHY_CTL_0, ++ VC4_SET_FIELD(chan0_settings->ext_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan0_settings->ffe_enable, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) | ++ VC4_SET_FIELD(chan0_settings->slew_rate_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) | ++ VC4_SET_FIELD(chan0_settings->ffe_post_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) | ++ VC4_SET_FIELD(chan0_settings->ldmos_bias_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) | ++ VC4_SET_FIELD(chan0_settings->com_mode_ldmos_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) | ++ VC4_SET_FIELD(chan0_settings->edge_sel, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) | ++ VC4_SET_FIELD(chan0_settings->ext_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan0_settings->term_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) | ++ VC4_SET_FIELD(chan0_settings->ext_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan0_settings->int_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan0_settings->int_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan0_settings->int_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan0_settings->main_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan0_settings->post_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan0_settings->slew_ctl_slow_loading, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) | ++ VC4_SET_FIELD(chan0_settings->slew_ctl_slow_driving, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) | ++ VC4_SET_FIELD(chan0_settings->ffe_pre_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN)); ++ ++ chan1_settings = ++ vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1], ++ pixel_freq); ++ HDMI_WRITE(HDMI_TX_PHY_CTL_1, ++ VC4_SET_FIELD(chan1_settings->ext_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan1_settings->ffe_enable, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) | ++ VC4_SET_FIELD(chan1_settings->slew_rate_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) | ++ VC4_SET_FIELD(chan1_settings->ffe_post_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) | ++ VC4_SET_FIELD(chan1_settings->ldmos_bias_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) | ++ VC4_SET_FIELD(chan1_settings->com_mode_ldmos_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) | ++ VC4_SET_FIELD(chan1_settings->edge_sel, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) | ++ VC4_SET_FIELD(chan1_settings->ext_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan1_settings->term_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) | ++ VC4_SET_FIELD(chan1_settings->ext_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan1_settings->int_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan1_settings->int_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan1_settings->int_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan1_settings->main_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan1_settings->post_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan1_settings->slew_ctl_slow_loading, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) | ++ VC4_SET_FIELD(chan1_settings->slew_ctl_slow_driving, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) | ++ VC4_SET_FIELD(chan1_settings->ffe_pre_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN)); ++ ++ chan2_settings = ++ vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2], ++ pixel_freq); ++ HDMI_WRITE(HDMI_TX_PHY_CTL_2, ++ VC4_SET_FIELD(chan2_settings->ext_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan2_settings->ffe_enable, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) | ++ VC4_SET_FIELD(chan2_settings->slew_rate_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) | ++ VC4_SET_FIELD(chan2_settings->ffe_post_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) | ++ VC4_SET_FIELD(chan2_settings->ldmos_bias_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) | ++ VC4_SET_FIELD(chan2_settings->com_mode_ldmos_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) | ++ VC4_SET_FIELD(chan2_settings->edge_sel, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) | ++ VC4_SET_FIELD(chan2_settings->ext_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan2_settings->term_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) | ++ VC4_SET_FIELD(chan2_settings->ext_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan2_settings->int_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(chan2_settings->int_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) | ++ VC4_SET_FIELD(chan2_settings->int_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(chan2_settings->main_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan2_settings->post_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(chan2_settings->slew_ctl_slow_loading, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) | ++ VC4_SET_FIELD(chan2_settings->slew_ctl_slow_driving, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) | ++ VC4_SET_FIELD(chan2_settings->ffe_pre_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN)); ++ ++ clock_settings = ++ vc6_phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK], ++ pixel_freq); ++ HDMI_WRITE(HDMI_TX_PHY_CTL_CK, ++ VC4_SET_FIELD(clock_settings->ext_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_CTL) | ++ VC4_SET_FIELD(clock_settings->ffe_enable, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_ENABLE) | ++ VC4_SET_FIELD(clock_settings->slew_rate_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_RATE_CTL) | ++ VC4_SET_FIELD(clock_settings->ffe_post_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_POST_TAP_EN) | ++ VC4_SET_FIELD(clock_settings->ldmos_bias_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_LDMOS_BIAS_CTL) | ++ VC4_SET_FIELD(clock_settings->com_mode_ldmos_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_COM_MODE_LDMOS_EN) | ++ VC4_SET_FIELD(clock_settings->edge_sel, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EDGE_SEL) | ++ VC4_SET_FIELD(clock_settings->ext_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(clock_settings->term_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_TERM_CTL) | ++ VC4_SET_FIELD(clock_settings->ext_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_EXT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(clock_settings->int_current_src_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_EN) | ++ VC4_SET_FIELD(clock_settings->int_current_ctl, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_CTL) | ++ VC4_SET_FIELD(clock_settings->int_current_src_hs_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_INT_CURRENT_SRC_HS_EN) | ++ VC4_SET_FIELD(clock_settings->main_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_MAIN_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(clock_settings->post_tap_current_select, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_POST_TAP_CURRENT_SELECT) | ++ VC4_SET_FIELD(clock_settings->slew_ctl_slow_loading, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_LOADING) | ++ VC4_SET_FIELD(clock_settings->slew_ctl_slow_driving, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_SLEW_CTL_SLOW_DRIVING) | ++ VC4_SET_FIELD(clock_settings->ffe_pre_tap_en, ++ VC6_HDMI_TX_PHY_HDMI_CTRL_CHX_FFE_PRE_TAP_EN)); ++ ++ if (pixel_freq >= 340000000) ++ word_sel = 3; ++ else ++ word_sel = 0; ++ HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel); ++ ++ HDMI_WRITE(HDMI_TX_PHY_POWERUP_CTL, ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BG_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_LDO_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_BIAS_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_CK_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_2_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_1_PWRUP | ++ VC6_HDMI_TX_PHY_HDMI_POWERUP_CTL_TX_0_PWRUP); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_POWERUP_CTL, ++ VC6_HDMI_TX_PHY_PLL_POWERUP_CTL_PLL_PWRUP); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_RESET_CTL, ++ HDMI_READ(HDMI_TX_PHY_PLL_RESET_CTL) & ++ ~VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_RESETB); ++ ++ HDMI_WRITE(HDMI_TX_PHY_PLL_RESET_CTL, ++ HDMI_READ(HDMI_TX_PHY_PLL_RESET_CTL) | ++ VC6_HDMI_TX_PHY_PLL_RESET_CTL_PLL_RESETB); ++ ++ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); ++} ++ ++void vc6_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) ++{ ++} +--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +@@ -111,13 +111,30 @@ enum vc4_hdmi_field { + HDMI_TX_PHY_CTL_1, + HDMI_TX_PHY_CTL_2, + HDMI_TX_PHY_CTL_3, ++ HDMI_TX_PHY_CTL_CK, + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, + HDMI_TX_PHY_PLL_CFG, ++ HDMI_TX_PHY_PLL_CFG_PDIV, + HDMI_TX_PHY_PLL_CTL_0, + HDMI_TX_PHY_PLL_CTL_1, ++ HDMI_TX_PHY_PLL_MISC_0, ++ HDMI_TX_PHY_PLL_MISC_1, ++ HDMI_TX_PHY_PLL_MISC_2, ++ HDMI_TX_PHY_PLL_MISC_3, ++ HDMI_TX_PHY_PLL_MISC_4, ++ HDMI_TX_PHY_PLL_MISC_5, ++ HDMI_TX_PHY_PLL_MISC_6, ++ HDMI_TX_PHY_PLL_MISC_7, ++ HDMI_TX_PHY_PLL_MISC_8, ++ HDMI_TX_PHY_PLL_POST_KDIV, ++ HDMI_TX_PHY_PLL_POWERUP_CTL, ++ HDMI_TX_PHY_PLL_REFCLK, ++ HDMI_TX_PHY_PLL_RESET_CTL, ++ HDMI_TX_PHY_PLL_VCOCLK_DIV, + HDMI_TX_PHY_POWERDOWN_CTL, ++ HDMI_TX_PHY_POWERUP_CTL, + HDMI_TX_PHY_RESET_CTL, + HDMI_TX_PHY_TMDS_CLK_WORD_SEL, + HDMI_VEC_INTERFACE_CFG, +@@ -383,6 +400,206 @@ static const struct vc4_hdmi_register __ + + VC5_RM_REG(HDMI_RM_CONTROL, 0x000), + VC5_RM_REG(HDMI_RM_OFFSET, 0x018), ++ VC5_RM_REG(HDMI_RM_FORMAT, 0x01c), ++ ++ VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000), ++ ++ VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044), ++ ++ VC5_CSC_REG(HDMI_CSC_CTL, 0x000), ++ VC5_CSC_REG(HDMI_CSC_12_11, 0x004), ++ VC5_CSC_REG(HDMI_CSC_14_13, 0x008), ++ VC5_CSC_REG(HDMI_CSC_22_21, 0x00c), ++ VC5_CSC_REG(HDMI_CSC_24_23, 0x010), ++ VC5_CSC_REG(HDMI_CSC_32_31, 0x014), ++ VC5_CSC_REG(HDMI_CSC_34_33, 0x018), ++ VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c), ++}; ++ ++static const struct vc4_hdmi_register __maybe_unused vc6_hdmi_hdmi0_fields[] = { ++ VC4_HD_REG(HDMI_DVP_CTL, 0x0000), ++ VC4_HD_REG(HDMI_MAI_CTL, 0x0010), ++ VC4_HD_REG(HDMI_MAI_THR, 0x0014), ++ VC4_HD_REG(HDMI_MAI_FMT, 0x0018), ++ VC4_HD_REG(HDMI_MAI_DATA, 0x001c), ++ VC4_HD_REG(HDMI_MAI_SMP, 0x0020), ++ VC4_HD_REG(HDMI_VID_CTL, 0x0044), ++ VC4_HD_REG(HDMI_FRAME_COUNT, 0x0060), ++ ++ VC4_HDMI_REG(HDMI_FIFO_CTL, 0x07c), ++ VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0c0), ++ VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0c4), ++ VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0cc), ++ VC4_HDMI_REG(HDMI_CRP_CFG, 0x0d0), ++ VC4_HDMI_REG(HDMI_CTS_0, 0x0d4), ++ VC4_HDMI_REG(HDMI_CTS_1, 0x0d8), ++ VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e8), ++ VC4_HDMI_REG(HDMI_HORZA, 0x0ec), ++ VC4_HDMI_REG(HDMI_HORZB, 0x0f0), ++ VC4_HDMI_REG(HDMI_VERTA0, 0x0f4), ++ VC4_HDMI_REG(HDMI_VERTB0, 0x0f8), ++ VC4_HDMI_REG(HDMI_VERTA1, 0x100), ++ VC4_HDMI_REG(HDMI_VERTB1, 0x104), ++ VC4_HDMI_REG(HDMI_MISC_CONTROL, 0x114), ++ VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x0a4), ++ VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a8), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_1, 0x148), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_2, 0x14c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_3, 0x150), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_4, 0x158), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_5, 0x15c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_6, 0x160), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_7, 0x164), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_8, 0x168), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_9, 0x16c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_10, 0x170), ++ VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x18c), ++ VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x194), ++ VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x198), ++ VC4_HDMI_REG(HDMI_HOTPLUG, 0x1c8), ++ VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1e4), ++ ++ VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0f0), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f4), ++ ++ VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), ++ VC5_PHY_REG(HDMI_TX_PHY_POWERUP_CTL, 0x004), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_CK, 0x014), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_REFCLK, 0x01c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_POST_KDIV, 0x028), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_VCOCLK_DIV, 0x02c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x044), ++ VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x054), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_0, 0x060), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_1, 0x064), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_2, 0x068), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_3, 0x06c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_4, 0x070), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_5, 0x074), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_6, 0x078), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_7, 0x07c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_8, 0x080), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_RESET_CTL, 0x190), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_POWERUP_CTL, 0x194), ++ ++ VC5_RM_REG(HDMI_RM_CONTROL, 0x000), ++ VC5_RM_REG(HDMI_RM_OFFSET, 0x018), ++ VC5_RM_REG(HDMI_RM_FORMAT, 0x01c), ++ ++ VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000), ++ ++ VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c), ++ VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030), ++ VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040), ++ VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044), ++ ++ VC5_CSC_REG(HDMI_CSC_CTL, 0x000), ++ VC5_CSC_REG(HDMI_CSC_12_11, 0x004), ++ VC5_CSC_REG(HDMI_CSC_14_13, 0x008), ++ VC5_CSC_REG(HDMI_CSC_22_21, 0x00c), ++ VC5_CSC_REG(HDMI_CSC_24_23, 0x010), ++ VC5_CSC_REG(HDMI_CSC_32_31, 0x014), ++ VC5_CSC_REG(HDMI_CSC_34_33, 0x018), ++ VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c), ++}; ++ ++static const struct vc4_hdmi_register __maybe_unused vc6_hdmi_hdmi1_fields[] = { ++ VC4_HD_REG(HDMI_DVP_CTL, 0x0000), ++ VC4_HD_REG(HDMI_MAI_CTL, 0x0030), ++ VC4_HD_REG(HDMI_MAI_THR, 0x0034), ++ VC4_HD_REG(HDMI_MAI_FMT, 0x0038), ++ VC4_HD_REG(HDMI_MAI_DATA, 0x003c), ++ VC4_HD_REG(HDMI_MAI_SMP, 0x0040), ++ VC4_HD_REG(HDMI_VID_CTL, 0x0048), ++ VC4_HD_REG(HDMI_FRAME_COUNT, 0x0064), ++ ++ VC4_HDMI_REG(HDMI_FIFO_CTL, 0x07c), ++ VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0c0), ++ VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0c4), ++ VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0cc), ++ VC4_HDMI_REG(HDMI_CRP_CFG, 0x0d0), ++ VC4_HDMI_REG(HDMI_CTS_0, 0x0d4), ++ VC4_HDMI_REG(HDMI_CTS_1, 0x0d8), ++ VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e8), ++ VC4_HDMI_REG(HDMI_HORZA, 0x0ec), ++ VC4_HDMI_REG(HDMI_HORZB, 0x0f0), ++ VC4_HDMI_REG(HDMI_VERTA0, 0x0f4), ++ VC4_HDMI_REG(HDMI_VERTB0, 0x0f8), ++ VC4_HDMI_REG(HDMI_VERTA1, 0x100), ++ VC4_HDMI_REG(HDMI_VERTB1, 0x104), ++ VC4_HDMI_REG(HDMI_MISC_CONTROL, 0x114), ++ VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x0a4), ++ VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a8), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_1, 0x148), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_2, 0x14c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_3, 0x150), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_4, 0x158), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_5, 0x15c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_6, 0x160), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_7, 0x164), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_8, 0x168), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_9, 0x16c), ++ VC4_HDMI_REG(HDMI_FORMAT_DET_10, 0x170), ++ VC4_HDMI_REG(HDMI_DEEP_COLOR_CONFIG_1, 0x18c), ++ VC4_HDMI_REG(HDMI_GCP_CONFIG, 0x194), ++ VC4_HDMI_REG(HDMI_GCP_WORD_1, 0x198), ++ VC4_HDMI_REG(HDMI_HOTPLUG, 0x1c8), ++ VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1e4), ++ ++ VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0f0), ++ VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f4), ++ ++ VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), ++ VC5_PHY_REG(HDMI_TX_PHY_POWERUP_CTL, 0x004), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010), ++ VC5_PHY_REG(HDMI_TX_PHY_CTL_CK, 0x014), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_REFCLK, 0x01c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_POST_KDIV, 0x028), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_VCOCLK_DIV, 0x02c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x044), ++ VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x054), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_0, 0x060), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_1, 0x064), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_2, 0x068), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_3, 0x06c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_4, 0x070), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_5, 0x074), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_6, 0x078), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_7, 0x07c), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_MISC_8, 0x080), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_RESET_CTL, 0x190), ++ VC5_PHY_REG(HDMI_TX_PHY_PLL_POWERUP_CTL, 0x194), ++ ++ VC5_RM_REG(HDMI_RM_CONTROL, 0x000), ++ VC5_RM_REG(HDMI_RM_OFFSET, 0x018), + VC5_RM_REG(HDMI_RM_FORMAT, 0x01c), + + VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000), diff --git a/target/linux/bcm27xx/patches-6.1/950-0966-drm-vc4-txp-Introduce-structure-to-deal-with-revisio.patch b/target/linux/bcm27xx/patches-6.1/950-0966-drm-vc4-txp-Introduce-structure-to-deal-with-revisio.patch new file mode 100644 index 0000000000..c54ab0d360 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0966-drm-vc4-txp-Introduce-structure-to-deal-with-revisio.patch @@ -0,0 +1,117 @@ +From a68e8ffc3314612b0d00d491c8cdd61ae1d9af4e Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Tue, 25 Apr 2023 10:12:32 +0200 +Subject: [PATCH] drm/vc4: txp: Introduce structure to deal with revision + differences + +The BCM2712 will have several TXP with small differences. Let's add a +structure tied to the compatible to deal with those differences. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 4 ++-- + drivers/gpu/drm/vc4/vc4_drv.h | 6 +++++- + drivers/gpu/drm/vc4/vc4_txp.c | 23 ++++++++++++++++------- + 3 files changed, 23 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -51,7 +51,7 @@ struct vc4_mock_desc { + + static const struct vc4_mock_desc vc4_mock = + VC4_MOCK_DESC( +- VC4_MOCK_CRTC_DESC(&vc4_txp_crtc_data, ++ VC4_MOCK_CRTC_DESC(&vc4_txp_data.base, + VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), +@@ -77,7 +77,7 @@ static const struct vc4_mock_desc vc4_mo + + static const struct vc4_mock_desc vc5_mock = + VC4_MOCK_DESC( +- VC4_MOCK_CRTC_DESC(&vc4_txp_crtc_data, ++ VC4_MOCK_CRTC_DESC(&vc4_txp_data.base, + VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -561,7 +561,11 @@ struct vc4_crtc_data { + int hvs_output; + }; + +-extern const struct vc4_crtc_data vc4_txp_crtc_data; ++struct vc4_txp_data { ++ struct vc4_crtc_data base; ++}; ++ ++extern const struct vc4_txp_data vc4_txp_data; + + struct vc4_pv_data { + struct vc4_crtc_data base; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -159,6 +159,7 @@ + + struct vc4_txp { + struct vc4_crtc base; ++ const struct vc4_txp_data *data; + + struct platform_device *pdev; + +@@ -488,17 +489,20 @@ static irqreturn_t vc4_txp_interrupt(int + return IRQ_HANDLED; + } + +-const struct vc4_crtc_data vc4_txp_crtc_data = { +- .name = "txp", +- .debugfs_name = "txp_regs", +- .hvs_available_channels = BIT(2), +- .hvs_output = 2, ++const struct vc4_txp_data vc4_txp_data = { ++ .base = { ++ .name = "txp", ++ .debugfs_name = "txp_regs", ++ .hvs_available_channels = BIT(2), ++ .hvs_output = 2, ++ }, + }; + + static int vc4_txp_bind(struct device *dev, struct device *master, void *data) + { + struct platform_device *pdev = to_platform_device(dev); + struct drm_device *drm = dev_get_drvdata(master); ++ const struct vc4_txp_data *txp_data; + struct vc4_encoder *vc4_encoder; + struct drm_encoder *encoder; + struct vc4_crtc *vc4_crtc; +@@ -513,6 +517,11 @@ static int vc4_txp_bind(struct device *d + if (!txp) + return -ENOMEM; + ++ txp_data = of_device_get_match_data(dev); ++ if (!txp_data) ++ return -ENODEV; ++ ++ txp->data = txp_data; + txp->pdev = pdev; + txp->regs = vc4_ioremap_regs(pdev, 0); + if (IS_ERR(txp->regs)) +@@ -523,7 +532,7 @@ static int vc4_txp_bind(struct device *d + vc4_crtc->regset.regs = txp_regs; + vc4_crtc->regset.nregs = ARRAY_SIZE(txp_regs); + +- ret = vc4_crtc_init(drm, pdev, vc4_crtc, &vc4_txp_crtc_data, ++ ret = vc4_crtc_init(drm, pdev, vc4_crtc, &txp_data->base, + &vc4_txp_crtc_funcs, &vc4_txp_crtc_helper_funcs, true); + if (ret) + return ret; +@@ -584,7 +593,7 @@ static int vc4_txp_remove(struct platfor + } + + static const struct of_device_id vc4_txp_dt_match[] = { +- { .compatible = "brcm,bcm2835-txp" }, ++ { .compatible = "brcm,bcm2835-txp", .data = &vc4_txp_data }, + { /* sentinel */ }, + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0967-drm-vc4-txp-Rename-TXP-data-structure.patch b/target/linux/bcm27xx/patches-6.1/950-0967-drm-vc4-txp-Rename-TXP-data-structure.patch new file mode 100644 index 0000000000..9303f86734 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0967-drm-vc4-txp-Rename-TXP-data-structure.patch @@ -0,0 +1,66 @@ +From 7d345345b70f00bf4c673a68da7d1cf0faf5cc47 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Tue, 25 Apr 2023 10:21:53 +0200 +Subject: [PATCH] drm/vc4: txp: Rename TXP data structure + +The TXP data structure has a name too generic for the multiple variants +we'll have to support. Let's rename it to mention the SoC it applies to. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 4 ++-- + drivers/gpu/drm/vc4/vc4_drv.h | 2 +- + drivers/gpu/drm/vc4/vc4_txp.c | 4 ++-- + 3 files changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -51,7 +51,7 @@ struct vc4_mock_desc { + + static const struct vc4_mock_desc vc4_mock = + VC4_MOCK_DESC( +- VC4_MOCK_CRTC_DESC(&vc4_txp_data.base, ++ VC4_MOCK_CRTC_DESC(&bcm2835_txp_data.base, + VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), +@@ -77,7 +77,7 @@ static const struct vc4_mock_desc vc4_mo + + static const struct vc4_mock_desc vc5_mock = + VC4_MOCK_DESC( +- VC4_MOCK_CRTC_DESC(&vc4_txp_data.base, ++ VC4_MOCK_CRTC_DESC(&bcm2835_txp_data.base, + VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -565,7 +565,7 @@ struct vc4_txp_data { + struct vc4_crtc_data base; + }; + +-extern const struct vc4_txp_data vc4_txp_data; ++extern const struct vc4_txp_data bcm2835_txp_data; + + struct vc4_pv_data { + struct vc4_crtc_data base; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -489,7 +489,7 @@ static irqreturn_t vc4_txp_interrupt(int + return IRQ_HANDLED; + } + +-const struct vc4_txp_data vc4_txp_data = { ++const struct vc4_txp_data bcm2835_txp_data = { + .base = { + .name = "txp", + .debugfs_name = "txp_regs", +@@ -593,7 +593,7 @@ static int vc4_txp_remove(struct platfor + } + + static const struct of_device_id vc4_txp_dt_match[] = { +- { .compatible = "brcm,bcm2835-txp", .data = &vc4_txp_data }, ++ { .compatible = "brcm,bcm2835-txp", .data = &bcm2835_txp_data }, + { /* sentinel */ }, + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0968-drm-vc4-txp-Add-byte-enable-toggle-bit.patch b/target/linux/bcm27xx/patches-6.1/950-0968-drm-vc4-txp-Add-byte-enable-toggle-bit.patch new file mode 100644 index 0000000000..cea9062b19 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0968-drm-vc4-txp-Add-byte-enable-toggle-bit.patch @@ -0,0 +1,56 @@ +From e8dbad6d506b6fac992fdf74a7e3a66a38e554c3 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 09:30:33 +0200 +Subject: [PATCH] drm/vc4: txp: Add byte enable toggle bit + +The MOPLET doesn't have the BYTE_ENABLE field to set, but the TXP and +MOP do, so let's add a boolean to control whether or not we need to set +it. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_txp.c | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -563,6 +563,7 @@ struct vc4_crtc_data { + + struct vc4_txp_data { + struct vc4_crtc_data base; ++ unsigned int has_byte_enable:1; + }; + + extern const struct vc4_txp_data bcm2835_txp_data; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -291,6 +291,7 @@ static void vc4_txp_connector_atomic_com + struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, + conn); + struct vc4_txp *txp = connector_to_vc4_txp(conn); ++ const struct vc4_txp_data *txp_data = txp->data; + struct drm_gem_dma_object *gem; + struct drm_display_mode *mode; + struct drm_framebuffer *fb; +@@ -313,9 +314,11 @@ static void vc4_txp_connector_atomic_com + return; + + ctrl = TXP_GO | TXP_EI | +- VC4_SET_FIELD(0xf, TXP_BYTE_ENABLE) | + VC4_SET_FIELD(txp_fmts[i], TXP_FORMAT); + ++ if (txp_data->has_byte_enable) ++ ctrl |= VC4_SET_FIELD(0xf, TXP_BYTE_ENABLE); ++ + if (fb->format->has_alpha) + ctrl |= TXP_ALPHA_ENABLE; + else +@@ -496,6 +499,7 @@ const struct vc4_txp_data bcm2835_txp_da + .hvs_available_channels = BIT(2), + .hvs_output = 2, + }, ++ .has_byte_enable = true, + }; + + static int vc4_txp_bind(struct device *dev, struct device *master, void *data) diff --git a/target/linux/bcm27xx/patches-6.1/950-0969-drm-vc4-txp-Add-horizontal-and-vertical-size-offset-.patch b/target/linux/bcm27xx/patches-6.1/950-0969-drm-vc4-txp-Add-horizontal-and-vertical-size-offset-.patch new file mode 100644 index 0000000000..290473e834 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0969-drm-vc4-txp-Add-horizontal-and-vertical-size-offset-.patch @@ -0,0 +1,59 @@ +From a51e4acdab01540e1006e43f38e5befb40002de0 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 09:47:54 +0200 +Subject: [PATCH] drm/vc4: txp: Add horizontal and vertical size offset toggle + bit + +The new writeback controllers that can be found on the BCM2712 require +to have their horizontal and vertical size reduced by one. + +Let's tie that behaviour to the compatible so we can support both the +new and old controllers. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_txp.c | 14 ++++++++++++-- + 2 files changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -564,6 +564,7 @@ struct vc4_crtc_data { + struct vc4_txp_data { + struct vc4_crtc_data base; + unsigned int has_byte_enable:1; ++ unsigned int size_minus_one:1; + }; + + extern const struct vc4_txp_data bcm2835_txp_data; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -295,6 +295,8 @@ static void vc4_txp_connector_atomic_com + struct drm_gem_dma_object *gem; + struct drm_display_mode *mode; + struct drm_framebuffer *fb; ++ unsigned int hdisplay; ++ unsigned int vdisplay; + u32 ctrl; + int idx; + int i; +@@ -334,9 +336,17 @@ static void vc4_txp_connector_atomic_com + gem = drm_fb_dma_get_gem_obj(fb, 0); + TXP_WRITE(TXP_DST_PTR, gem->dma_addr + fb->offsets[0]); + TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]); ++ ++ hdisplay = mode->hdisplay ?: 1; ++ vdisplay = mode->vdisplay ?: 1; ++ if (txp_data->size_minus_one) { ++ hdisplay -= 1; ++ vdisplay -= 1; ++ } ++ + TXP_WRITE(TXP_DIM, +- VC4_SET_FIELD(mode->hdisplay, TXP_WIDTH) | +- VC4_SET_FIELD(mode->vdisplay, TXP_HEIGHT)); ++ VC4_SET_FIELD(hdisplay, TXP_WIDTH) | ++ VC4_SET_FIELD(vdisplay, TXP_HEIGHT)); + + TXP_WRITE(TXP_DST_CTRL, ctrl); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0970-drm-vc4-txp-Handle-40-bits-DMA-Addresses.patch b/target/linux/bcm27xx/patches-6.1/950-0970-drm-vc4-txp-Handle-40-bits-DMA-Addresses.patch new file mode 100644 index 0000000000..5d1fbcb119 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0970-drm-vc4-txp-Handle-40-bits-DMA-Addresses.patch @@ -0,0 +1,59 @@ +From ddb9aa80692ed5d35e4ee4688c36789620f78c5c Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 17:47:11 +0200 +Subject: [PATCH] drm/vc4: txp: Handle 40-bits DMA Addresses + +The BCM2712 MOP and MOPLET can handle addresses larger than 32bits +through an extra register. We can easily support it and make it +conditional based on the compatible through a boolean in our variant +structure. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_txp.c | 10 +++++++++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -565,6 +565,7 @@ struct vc4_txp_data { + struct vc4_crtc_data base; + unsigned int has_byte_enable:1; + unsigned int size_minus_one:1; ++ unsigned int supports_40bit_addresses:1; + }; + + extern const struct vc4_txp_data bcm2835_txp_data; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -145,6 +145,8 @@ + /* Number of lines received and committed to memory. */ + #define TXP_PROGRESS 0x10 + ++#define TXP_DST_PTR_HIGH 0x1c ++ + #define TXP_READ(offset) \ + ({ \ + kunit_fail_current_test("Accessing a register in a unit test!\n"); \ +@@ -297,6 +299,7 @@ static void vc4_txp_connector_atomic_com + struct drm_framebuffer *fb; + unsigned int hdisplay; + unsigned int vdisplay; ++ dma_addr_t addr; + u32 ctrl; + int idx; + int i; +@@ -334,7 +337,12 @@ static void vc4_txp_connector_atomic_com + return; + + gem = drm_fb_dma_get_gem_obj(fb, 0); +- TXP_WRITE(TXP_DST_PTR, gem->dma_addr + fb->offsets[0]); ++ addr = gem->dma_addr + fb->offsets[0]; ++ TXP_WRITE(TXP_DST_PTR, lower_32_bits(addr)); ++ ++ if (txp_data->supports_40bit_addresses) ++ TXP_WRITE(TXP_DST_PTR_HIGH, upper_32_bits(addr) & 0xff); ++ + TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]); + + hdisplay = mode->hdisplay ?: 1; diff --git a/target/linux/bcm27xx/patches-6.1/950-0971-drm-vc4-txp-Move-the-encoder-type-in-the-variant-str.patch b/target/linux/bcm27xx/patches-6.1/950-0971-drm-vc4-txp-Move-the-encoder-type-in-the-variant-str.patch new file mode 100644 index 0000000000..0445c4f509 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0971-drm-vc4-txp-Move-the-encoder-type-in-the-variant-str.patch @@ -0,0 +1,44 @@ +From 2e8f4fa23af4bb794e9b2284a53aa40bbfdd3cbb Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 11:26:10 +0200 +Subject: [PATCH] drm/vc4: txp: Move the encoder type in the variant structure + +We'll have multiple TXP instances in the BCM2712, so we can't use a +single encoder type anymore. Let's tie the encoder type to the +compatible. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_txp.c | 3 ++- + 2 files changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -563,6 +563,7 @@ struct vc4_crtc_data { + + struct vc4_txp_data { + struct vc4_crtc_data base; ++ enum vc4_encoder_type encoder_type; + unsigned int has_byte_enable:1; + unsigned int size_minus_one:1; + unsigned int supports_40bit_addresses:1; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -517,6 +517,7 @@ const struct vc4_txp_data bcm2835_txp_da + .hvs_available_channels = BIT(2), + .hvs_output = 2, + }, ++ .encoder_type = VC4_ENCODER_TYPE_TXP, + .has_byte_enable = true, + }; + +@@ -560,7 +561,7 @@ static int vc4_txp_bind(struct device *d + return ret; + + vc4_encoder = &txp->encoder; +- txp->encoder.type = VC4_ENCODER_TYPE_TXP; ++ txp->encoder.type = txp_data->encoder_type; + + encoder = &vc4_encoder->base; + encoder->possible_crtcs = drm_crtc_mask(&vc4_crtc->base); diff --git a/target/linux/bcm27xx/patches-6.1/950-0972-drm-vc4-txp-Add-a-new-TXP-encoder-type.patch b/target/linux/bcm27xx/patches-6.1/950-0972-drm-vc4-txp-Add-a-new-TXP-encoder-type.patch new file mode 100644 index 0000000000..f832fc1ed5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0972-drm-vc4-txp-Add-a-new-TXP-encoder-type.patch @@ -0,0 +1,475 @@ +From 68a00ca7b1d7809ac7be736c02238c142e629127 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 11:49:28 +0200 +Subject: [PATCH] drm/vc4: txp: Add a new TXP encoder type + +Starting with BCM2712, we'll have a two TXP. Let's follow the HDMI +example and add two encoder types for TXP: TXP0 and TXP1. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 4 +- + .../gpu/drm/vc4/tests/vc4_test_pv_muxing.c | 106 +++++++++--------- + drivers/gpu/drm/vc4/vc4_drv.h | 3 +- + drivers/gpu/drm/vc4/vc4_kms.c | 2 +- + drivers/gpu/drm/vc4/vc4_txp.c | 2 +- + 5 files changed, 59 insertions(+), 58 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -52,7 +52,7 @@ struct vc4_mock_desc { + static const struct vc4_mock_desc vc4_mock = + VC4_MOCK_DESC( + VC4_MOCK_CRTC_DESC(&bcm2835_txp_data.base, +- VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP0, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), + VC4_MOCK_PIXELVALVE_DESC(&bcm2835_pv0_data, +@@ -78,7 +78,7 @@ static const struct vc4_mock_desc vc4_mo + static const struct vc4_mock_desc vc5_mock = + VC4_MOCK_DESC( + VC4_MOCK_CRTC_DESC(&bcm2835_txp_data.base, +- VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP0, + DRM_MODE_ENCODER_VIRTUAL, + DRM_MODE_CONNECTOR_WRITEBACK)), + VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv0_data, +--- a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c +@@ -91,7 +91,7 @@ static const struct encoder_constraint v + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 1), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1), +- ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP, 2), ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP0, 2), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 2), + }; + +@@ -99,7 +99,7 @@ static const struct encoder_constraint v + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DPI, 0), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1), +- ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP, 0, 2), ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP0, 0, 2), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 0, 1, 2), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 0, 1, 2), + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI1, 0, 1, 2), +@@ -208,7 +208,7 @@ static const struct pv_muxing_param vc4_ + VC4_PV_MUXING_TEST("1 output: DSI1", + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("1 output: TXP", +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("2 outputs: DSI0, HDMI0", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_HDMI0), +@@ -220,7 +220,7 @@ static const struct pv_muxing_param vc4_ + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("2 outputs: DSI0, TXP", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("2 outputs: DPI, HDMI0", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_HDMI0), +@@ -232,19 +232,19 @@ static const struct pv_muxing_param vc4_ + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("2 outputs: DPI, TXP", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("2 outputs: HDMI0, DSI1", + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("2 outputs: HDMI0, TXP", + VC4_ENCODER_TYPE_HDMI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("2 outputs: VEC, DSI1", + VC4_ENCODER_TYPE_VEC, + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("2 outputs: VEC, TXP", + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, DSI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_HDMI0, +@@ -252,7 +252,7 @@ static const struct pv_muxing_param vc4_ + VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, TXP", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_HDMI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +@@ -260,7 +260,7 @@ static const struct pv_muxing_param vc4_ + VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, DSI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_HDMI0, +@@ -268,7 +268,7 @@ static const struct pv_muxing_param vc4_ + VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, TXP", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_HDMI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +@@ -276,7 +276,7 @@ static const struct pv_muxing_param vc4_ + VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + }; + + KUNIT_ARRAY_PARAM(vc4_test_pv_muxing, +@@ -288,7 +288,7 @@ static const struct pv_muxing_param vc4_ + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_DSI0), + VC4_PV_MUXING_TEST("TXP/DSI1 Conflict", +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1), + VC4_PV_MUXING_TEST("HDMI0/VEC Conflict", + VC4_ENCODER_TYPE_HDMI0, +@@ -297,22 +297,22 @@ static const struct pv_muxing_param vc4_ + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_DSI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, TXP", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, + VC4_ENCODER_TYPE_DSI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("More than 3 outputs: DPI, HDMI0, DSI1, TXP", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_DSI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC4_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, TXP", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, + VC4_ENCODER_TYPE_DSI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + }; + + KUNIT_ARRAY_PARAM(vc4_test_pv_muxing_invalid, +@@ -343,7 +343,7 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("2 outputs: DPI, TXP", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("2 outputs: DPI, VEC", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC), +@@ -361,7 +361,7 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("2 outputs: DSI0, TXP", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("2 outputs: DSI0, VEC", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC), +@@ -373,7 +373,7 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_VEC), + VC5_PV_MUXING_TEST("2 outputs: DSI1, TXP", + VC4_ENCODER_TYPE_DSI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("2 outputs: DSI1, HDMI0", + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0), +@@ -385,7 +385,7 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_VEC), + VC5_PV_MUXING_TEST("2 outputs: HDMI0, TXP", + VC4_ENCODER_TYPE_HDMI0, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("2 outputs: HDMI0, HDMI1", + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), +@@ -394,14 +394,14 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_VEC), + VC5_PV_MUXING_TEST("2 outputs: HDMI1, TXP", + VC4_ENCODER_TYPE_HDMI1, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("2 outputs: TXP, VEC", +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_VEC), + VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +@@ -416,15 +416,15 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, DSI1", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1), + VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI0", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI1", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("3 outputs: DPI, DSI1, HDMI0", + VC4_ENCODER_TYPE_DPI, +@@ -441,7 +441,7 @@ static const struct pv_muxing_param vc5_ + VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP), ++ VC4_ENCODER_TYPE_TXP0), + VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +@@ -456,15 +456,15 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, DSI1", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1), + VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI0", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI1", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("3 outputs: DSI0, DSI1, HDMI0", + VC4_ENCODER_TYPE_DSI0, +@@ -491,17 +491,17 @@ static const struct pv_muxing_param vc5_ + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0", + VC4_ENCODER_TYPE_DPI, +@@ -520,17 +520,17 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI1", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, DSI1, HDMI0, HDMI1", +@@ -541,19 +541,19 @@ static const struct pv_muxing_param vc5_ + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0, HDMI1", +@@ -564,24 +564,24 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0", + VC4_ENCODER_TYPE_DSI0, +@@ -600,17 +600,17 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI1", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, DSI1, HDMI0, HDMI1", +@@ -621,19 +621,19 @@ static const struct pv_muxing_param vc5_ + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0, HDMI1", +@@ -644,27 +644,27 @@ static const struct pv_muxing_param vc5_ + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DSI0, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: VEC, TXP, DSI1, HDMI0, HDMI1", + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DPI, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0, HDMI1", + VC4_ENCODER_TYPE_DSI0, + VC4_ENCODER_TYPE_VEC, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1), +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -511,7 +511,8 @@ enum vc4_encoder_type { + VC4_ENCODER_TYPE_DSI1, + VC4_ENCODER_TYPE_SMI, + VC4_ENCODER_TYPE_DPI, +- VC4_ENCODER_TYPE_TXP, ++ VC4_ENCODER_TYPE_TXP0, ++ VC4_ENCODER_TYPE_TXP1, + }; + + struct vc4_encoder { +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -359,7 +359,7 @@ static void vc6_hvs_pv_muxing_commit(str + mux = 0; + break; + +- case VC4_ENCODER_TYPE_TXP: ++ case VC4_ENCODER_TYPE_TXP0: + mux = 2; + break; + +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -517,7 +517,7 @@ const struct vc4_txp_data bcm2835_txp_da + .hvs_available_channels = BIT(2), + .hvs_output = 2, + }, +- .encoder_type = VC4_ENCODER_TYPE_TXP, ++ .encoder_type = VC4_ENCODER_TYPE_TXP0, + .has_byte_enable = true, + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-0973-drm-vc4-txp-Add-support-for-BCM2712-MOP.patch b/target/linux/bcm27xx/patches-6.1/950-0973-drm-vc4-txp-Add-support-for-BCM2712-MOP.patch new file mode 100644 index 0000000000..aec0753408 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0973-drm-vc4-txp-Add-support-for-BCM2712-MOP.patch @@ -0,0 +1,64 @@ +From 831c6e8c68a66678e8329a382823dc83c483dcc8 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Thu, 27 Apr 2023 09:30:49 +0200 +Subject: [PATCH] drm/vc4: txp: Add support for BCM2712 MOP + +The BCM2712 has an evolution of what used to be called TXP in the +earlier SoCs, but is now called MOP. + +There's a few differences still, so we can add a new compatible to deal +with them easily. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_txp.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -388,6 +388,7 @@ static const struct drm_connector_funcs + static void vc4_txp_encoder_disable(struct drm_encoder *encoder) + { + struct drm_device *drm = encoder->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_txp *txp = encoder_to_vc4_txp(encoder); + int idx; + +@@ -406,7 +407,8 @@ static void vc4_txp_encoder_disable(stru + WARN_ON(TXP_READ(TXP_DST_CTRL) & TXP_BUSY); + } + +- TXP_WRITE(TXP_DST_CTRL, TXP_POWERDOWN); ++ if (vc4->gen < VC4_GEN_6) ++ TXP_WRITE(TXP_DST_CTRL, TXP_POWERDOWN); + + drm_dev_exit(idx); + } +@@ -510,6 +512,19 @@ static irqreturn_t vc4_txp_interrupt(int + return IRQ_HANDLED; + } + ++const struct vc4_txp_data bcm2712_mop_data = { ++ .base = { ++ .name = "mop", ++ .debugfs_name = "mop_regs", ++ .hvs_available_channels = BIT(2), ++ .hvs_output = 2, ++ }, ++ .encoder_type = VC4_ENCODER_TYPE_TXP0, ++ .has_byte_enable = true, ++ .size_minus_one = true, ++ .supports_40bit_addresses = true, ++}; ++ + const struct vc4_txp_data bcm2835_txp_data = { + .base = { + .name = "txp", +@@ -616,6 +631,7 @@ static int vc4_txp_remove(struct platfor + } + + static const struct of_device_id vc4_txp_dt_match[] = { ++ { .compatible = "brcm,bcm2712-mop", .data = &bcm2712_mop_data }, + { .compatible = "brcm,bcm2835-txp", .data = &bcm2835_txp_data }, + { /* sentinel */ }, + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0974-drm-vc4-txp-Add-BCM2712-MOPLET-support.patch b/target/linux/bcm27xx/patches-6.1/950-0974-drm-vc4-txp-Add-BCM2712-MOPLET-support.patch new file mode 100644 index 0000000000..b2a28bd144 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0974-drm-vc4-txp-Add-BCM2712-MOPLET-support.patch @@ -0,0 +1,42 @@ +From b239fc6a68fea2b073c4cb48884fbb697014ac2b Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Mon, 20 Feb 2023 17:16:01 +0100 +Subject: [PATCH] drm/vc4: txp: Add BCM2712 MOPLET support + +The BCM2712 features a simpler TXP called MOPLET. Let's add support for +it. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_txp.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -525,6 +525,18 @@ const struct vc4_txp_data bcm2712_mop_da + .supports_40bit_addresses = true, + }; + ++const struct vc4_txp_data bcm2712_moplet_data = { ++ .base = { ++ .name = "moplet", ++ .debugfs_name = "moplet_regs", ++ .hvs_available_channels = BIT(1), ++ .hvs_output = 4, ++ }, ++ .encoder_type = VC4_ENCODER_TYPE_TXP1, ++ .size_minus_one = true, ++ .supports_40bit_addresses = true, ++}; ++ + const struct vc4_txp_data bcm2835_txp_data = { + .base = { + .name = "txp", +@@ -632,6 +644,7 @@ static int vc4_txp_remove(struct platfor + + static const struct of_device_id vc4_txp_dt_match[] = { + { .compatible = "brcm,bcm2712-mop", .data = &bcm2712_mop_data }, ++ { .compatible = "brcm,bcm2712-moplet", .data = &bcm2712_moplet_data }, + { .compatible = "brcm,bcm2835-txp", .data = &bcm2835_txp_data }, + { /* sentinel */ }, + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0975-drm-vc4-Add-additional-warn_on.patch b/target/linux/bcm27xx/patches-6.1/950-0975-drm-vc4-Add-additional-warn_on.patch new file mode 100644 index 0000000000..0fc95e5f6b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0975-drm-vc4-Add-additional-warn_on.patch @@ -0,0 +1,240 @@ +From bb05ccd66342643b1cd9a0a48cec3ebdc3eed511 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Tue, 21 Feb 2023 14:38:32 +0100 +Subject: [PATCH] drm/vc4: Add additional warn_on + +Some code path in vc4 are conditional to a generation and cannot be +executed on others. Let's put a WARN_ON if that ever happens. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 32 ++++++++++++++++++++++++++++++-- + drivers/gpu/drm/vc4/vc4_kms.c | 6 ++++++ + drivers/gpu/drm/vc4/vc4_plane.c | 19 +++++++++++++++++++ + 3 files changed, 55 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -417,12 +417,15 @@ static int vc4_hvs_upload_linear_kernel( + static void vc4_hvs_lut_load(struct vc4_hvs *hvs, + struct vc4_crtc *vc4_crtc) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + struct drm_crtc *crtc = &vc4_crtc->base; + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); + int idx; + u32 i; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_5); ++ + if (!drm_dev_enter(drm, &idx)) + return; + +@@ -758,6 +761,8 @@ u8 vc4_hvs_get_fifo_frame_count(struct v + u8 field = 0; + int idx; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + if (!drm_dev_enter(drm, &idx)) + return 0; + +@@ -791,6 +796,8 @@ int vc4_hvs_get_fifo_from_output(struct + u32 reg; + int ret; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + switch (vc4->gen) { + case VC4_GEN_4: + return output; +@@ -880,6 +887,8 @@ static int vc4_hvs_init_channel(struct v + u32 dispctrl; + int idx; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_5); ++ + if (!drm_dev_enter(drm, &idx)) + return -ENODEV; + +@@ -947,6 +956,8 @@ static int vc6_hvs_init_channel(struct v + u32 disp_ctrl1; + int idx; + ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_6); ++ + if (!drm_dev_enter(drm, &idx)) + return -ENODEV; + +@@ -972,9 +983,12 @@ static int vc6_hvs_init_channel(struct v + + static void __vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan) + { +- struct drm_device *drm = &hvs->vc4->base; ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; + int idx; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_5); ++ + if (!drm_dev_enter(drm, &idx)) + return; + +@@ -1007,6 +1021,8 @@ static void __vc6_hvs_stop_channel(struc + struct drm_device *drm = &vc4->base; + int idx; + ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_6); ++ + if (!drm_dev_enter(drm, &idx)) + return; + +@@ -1234,6 +1250,8 @@ void vc4_hvs_atomic_flush(struct drm_crt + bool found = false; + int idx; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + if (!drm_dev_enter(dev, &idx)) { + vc4_crtc_send_vblank(crtc); + return; +@@ -1324,6 +1342,8 @@ void vc4_hvs_atomic_flush(struct drm_crt + if (crtc->state->color_mgmt_changed) { + u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(channel)); + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_5); ++ + if (crtc->state->gamma_lut) { + if (vc4->gen == VC4_GEN_4) { + vc4_hvs_update_gamma_lut(hvs, vc4_crtc); +@@ -1363,6 +1383,8 @@ void vc4_hvs_mask_underrun(struct vc4_hv + u32 dispctrl; + int idx; + ++ WARN_ON(vc4->gen > VC4_GEN_5); ++ + if (!drm_dev_enter(drm, &idx)) + return; + +@@ -1383,6 +1405,8 @@ void vc4_hvs_unmask_underrun(struct vc4_ + u32 dispctrl; + int idx; + ++ WARN_ON(vc4->gen > VC4_GEN_5); ++ + if (!drm_dev_enter(drm, &idx)) + return; + +@@ -1417,6 +1441,8 @@ static irqreturn_t vc4_hvs_irq_handler(i + u32 status; + u32 dspeislur; + ++ WARN_ON(vc4->gen > VC4_GEN_5); ++ + /* + * NOTE: We don't need to protect the register access using + * drm_dev_enter() there because the interrupt handler lifetime +@@ -1466,6 +1492,8 @@ static irqreturn_t vc6_hvs_eof_irq_handl + struct vc4_hvs *hvs = vc4->hvs; + unsigned int i; + ++ WARN_ON(vc4->gen < VC4_GEN_6); ++ + for (i = 0; i < HVS_NUM_CHANNELS; i++) { + if (!hvs->eof_irq[i].enabled) + continue; +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -147,6 +147,8 @@ vc4_ctm_commit(struct vc4_dev *vc4, stru + if (vc4->firmware_kms) + return; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_5); ++ + if (ctm_state->fifo) { + HVS_WRITE(SCALER_OLEDCOEF2, + VC4_SET_FIELD(vc4_ctm_s31_32_to_s0_9(ctm->matrix[0]), +@@ -222,6 +224,8 @@ static void vc4_hvs_pv_muxing_commit(str + struct drm_crtc *crtc; + unsigned int i; + ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_4); ++ + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); +@@ -265,6 +269,8 @@ static void vc5_hvs_pv_muxing_commit(str + unsigned int i; + u32 reg; + ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_5); ++ + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -555,8 +555,11 @@ static int vc4_plane_setup_clipping_and_ + + static void vc4_write_tpz(struct vc4_plane_state *vc4_state, u32 src, u32 dst) + { ++ struct vc4_dev *vc4 = to_vc4_dev(vc4_state->base.plane->dev); + u32 scale, recip; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + scale = src / dst; + + /* The specs note that while the reciprocal would be defined +@@ -581,10 +584,13 @@ static void vc4_write_tpz(struct vc4_pla + + static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst, u32 xy, int channel, int chroma_offset) + { ++ struct vc4_dev *vc4 = to_vc4_dev(vc4_state->base.plane->dev); + u32 scale = src / dst; + s32 offset, offset2; + s32 phase; + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + /* Start the phase at 1/2 pixel from the 1st pixel at src_x. + 1/4 pixel for YUV, plus the offset for chroma siting */ + if (channel) { +@@ -801,8 +807,11 @@ static size_t vc6_upm_size(const struct + static void vc4_write_scaling_parameters(struct drm_plane_state *state, + int channel) + { ++ struct vc4_dev *vc4 = to_vc4_dev(state->plane->dev); + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ + /* Ch0 H-PPF Word 0: Scaling Parameters */ + if (vc4_state->x_scaling[channel] == VC4_SCALING_PPF) { + vc4_write_ppf(vc4_state, +@@ -1040,6 +1049,11 @@ static const u32 colorspace_coeffs[2][DR + + static u32 vc4_hvs4_get_alpha_blend_mode(struct drm_plane_state *state) + { ++ struct drm_device *dev = state->state->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_4); ++ + if (!state->fb->format->has_alpha) + return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_FIXED, + SCALER_POS2_ALPHA_MODE); +@@ -1061,6 +1075,11 @@ static u32 vc4_hvs4_get_alpha_blend_mode + + static u32 vc4_hvs5_get_alpha_blend_mode(struct drm_plane_state *state) + { ++ struct drm_device *dev = state->state->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ ++ WARN_ON_ONCE(vc4->gen != VC4_GEN_5 && vc4->gen != VC4_GEN_6); ++ + if (!state->fb->format->has_alpha) + return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_FIXED, + SCALER5_CTL2_ALPHA_MODE); diff --git a/target/linux/bcm27xx/patches-6.1/950-0976-drm-vc4-tests-Switch-generation-mockup-to-a-switch.patch b/target/linux/bcm27xx/patches-6.1/950-0976-drm-vc4-tests-Switch-generation-mockup-to-a-switch.patch new file mode 100644 index 0000000000..0751d46536 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0976-drm-vc4-tests-Switch-generation-mockup-to-a-switch.patch @@ -0,0 +1,47 @@ +From 336917ca87807b8a4bb08855b4dcb0477289c765 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:35:16 +0100 +Subject: [PATCH] drm/vc4: tests: Switch generation mockup to a switch + +Testing whether the VideoCore generation we want to mock is vc5 or vc4 +worked so far, but will be difficult to extend to support BCM2712 (VC6). + +Convert to a switch. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -155,13 +155,27 @@ static int __build_mock(struct kunit *te + + static struct vc4_dev *__mock_device(struct kunit *test, enum vc4_gen gen) + { ++ const struct vc4_mock_desc *desc; ++ const struct drm_driver *drv; + struct drm_device *drm; +- const struct drm_driver *drv = (gen == VC4_GEN_5) ? &vc5_drm_driver : &vc4_drm_driver; +- const struct vc4_mock_desc *desc = (gen == VC4_GEN_5) ? &vc5_mock : &vc4_mock; + struct vc4_dev *vc4; + struct device *dev; + int ret; + ++ switch (gen) { ++ case VC4_GEN_4: ++ drv = &vc4_drm_driver; ++ desc = &vc4_mock; ++ break; ++ case VC4_GEN_5: ++ drv = &vc5_drm_driver; ++ desc = &vc5_mock; ++ break; ++ ++ default: ++ return NULL; ++ } ++ + dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + diff --git a/target/linux/bcm27xx/patches-6.1/950-0977-drm-vc4-tests-Drop-drm-parameter-for-vc4_find_crtc_f.patch b/target/linux/bcm27xx/patches-6.1/950-0977-drm-vc4-tests-Drop-drm-parameter-for-vc4_find_crtc_f.patch new file mode 100644 index 0000000000..42c4be9b8b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0977-drm-vc4-tests-Drop-drm-parameter-for-vc4_find_crtc_f.patch @@ -0,0 +1,63 @@ +From 70e906d3c688491e181446afa27bea32ce241d6a Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 24 Mar 2023 09:58:15 +0100 +Subject: [PATCH] drm/vc4: tests: Drop drm parameter for + vc4_find_crtc_for_encoder + +The DRM device pointer and the DRM encoder pointer are redundant, since +the latter is attached to the former and we can just follow the +drm_encoder->dev pointer. + +Let's remove the drm_device pointer argument. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.h | 2 +- + drivers/gpu/drm/vc4/tests/vc4_mock_output.c | 4 ++-- + drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h +@@ -7,9 +7,9 @@ + + static inline + struct drm_crtc *vc4_find_crtc_for_encoder(struct kunit *test, +- struct drm_device *drm, + struct drm_encoder *encoder) + { ++ struct drm_device *drm = encoder->dev; + struct drm_crtc *crtc; + + KUNIT_ASSERT_EQ(test, hweight32(encoder->possible_crtcs), 1); +--- a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c +@@ -77,7 +77,7 @@ int vc4_mock_atomic_add_output(struct ku + encoder = vc4_find_encoder_by_type(drm, type); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder); + +- crtc = vc4_find_crtc_for_encoder(test, drm, encoder); ++ crtc = vc4_find_crtc_for_encoder(test, encoder); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc); + + output = container_of(encoder, struct vc4_dummy_output, encoder.base); +@@ -115,7 +115,7 @@ int vc4_mock_atomic_del_output(struct ku + encoder = vc4_find_encoder_by_type(drm, type); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder); + +- crtc = vc4_find_crtc_for_encoder(test, drm, encoder); ++ crtc = vc4_find_crtc_for_encoder(test, encoder); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc); + + crtc_state = drm_atomic_get_crtc_state(state, crtc); +--- a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c +@@ -132,7 +132,7 @@ get_vc4_crtc_state_for_encoder(struct ku + encoder = vc4_find_encoder_by_type(drm, type); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder); + +- crtc = vc4_find_crtc_for_encoder(test, drm, encoder); ++ crtc = vc4_find_crtc_for_encoder(test, encoder); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc); + + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); diff --git a/target/linux/bcm27xx/patches-6.1/950-0978-drm-vc4-tests-Return-the-allocated-output.patch b/target/linux/bcm27xx/patches-6.1/950-0978-drm-vc4-tests-Return-the-allocated-output.patch new file mode 100644 index 0000000000..6f49d52f32 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0978-drm-vc4-tests-Return-the-allocated-output.patch @@ -0,0 +1,174 @@ +From 14e97c5765579eaab3c8372701750ffa30e4c7da Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 24 Mar 2023 10:02:59 +0100 +Subject: [PATCH] drm/vc4: tests: Return the allocated output + +Some tests will need to retrieve the output that was just allocated by +vc4_mock_atomic_add_output(). + +Instead of making them look them up in the DRM device, we can simply +make vc4_mock_atomic_add_output() return an error pointer that holds the +allocated output instead of the error code. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.h | 7 ++-- + drivers/gpu/drm/vc4/tests/vc4_mock_output.c | 9 +++-- + .../gpu/drm/vc4/tests/vc4_test_pv_muxing.c | 37 +++++++++++-------- + 3 files changed, 30 insertions(+), 23 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h +@@ -53,9 +53,10 @@ struct vc4_dummy_output *vc4_dummy_outpu + struct vc4_dev *vc4_mock_device(struct kunit *test); + struct vc4_dev *vc5_mock_device(struct kunit *test); + +-int vc4_mock_atomic_add_output(struct kunit *test, +- struct drm_atomic_state *state, +- enum vc4_encoder_type type); ++struct vc4_dummy_output * ++vc4_mock_atomic_add_output(struct kunit *test, ++ struct drm_atomic_state *state, ++ enum vc4_encoder_type type); + int vc4_mock_atomic_del_output(struct kunit *test, + struct drm_atomic_state *state, + enum vc4_encoder_type type); +--- a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c +@@ -61,9 +61,10 @@ static const struct drm_display_mode def + DRM_SIMPLE_MODE(640, 480, 64, 48) + }; + +-int vc4_mock_atomic_add_output(struct kunit *test, +- struct drm_atomic_state *state, +- enum vc4_encoder_type type) ++struct vc4_dummy_output * ++vc4_mock_atomic_add_output(struct kunit *test, ++ struct drm_atomic_state *state, ++ enum vc4_encoder_type type) + { + struct drm_device *drm = state->dev; + struct drm_connector_state *conn_state; +@@ -96,7 +97,7 @@ int vc4_mock_atomic_add_output(struct ku + + crtc_state->active = true; + +- return 0; ++ return output; + } + + int vc4_mock_atomic_del_output(struct kunit *test, +--- a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c +@@ -683,10 +683,11 @@ static void drm_vc4_test_pv_muxing(struc + int ret; + + for (i = 0; i < params->nencoders; i++) { ++ struct vc4_dummy_output *output; + enum vc4_encoder_type enc_type = params->encoders[i]; + +- ret = vc4_mock_atomic_add_output(test, state, enc_type); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, enc_type); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + } + + ret = drm_atomic_check_only(state); +@@ -712,10 +713,11 @@ static void drm_vc4_test_pv_muxing_inval + int ret; + + for (i = 0; i < params->nencoders; i++) { ++ struct vc4_dummy_output *output; + enum vc4_encoder_type enc_type = params->encoders[i]; + +- ret = vc4_mock_atomic_add_output(test, state, enc_type); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, enc_type); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + } + + ret = drm_atomic_check_only(state); +@@ -804,6 +806,7 @@ static void drm_test_vc5_pv_muxing_bugs_ + { + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; ++ struct vc4_dummy_output *output; + struct vc4_crtc_state *new_vc4_crtc_state; + struct vc4_hvs_state *new_hvs_state; + unsigned int hdmi0_channel; +@@ -823,8 +826,8 @@ static void drm_test_vc5_pv_muxing_bugs_ + + state->acquire_ctx = &ctx; + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); +@@ -850,8 +853,8 @@ static void drm_test_vc5_pv_muxing_bugs_ + + state->acquire_ctx = &ctx; + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); +@@ -880,6 +883,7 @@ static void drm_test_vc5_pv_muxing_bugs_ + { + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; ++ struct vc4_dummy_output *output; + struct vc4_crtc_state *new_vc4_crtc_state; + struct vc4_hvs_state *new_hvs_state; + unsigned int old_hdmi0_channel; +@@ -899,11 +903,11 @@ static void drm_test_vc5_pv_muxing_bugs_ + + state->acquire_ctx = &ctx; + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); +@@ -971,6 +975,7 @@ drm_test_vc5_pv_muxing_bugs_subsequent_c + { + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; ++ struct vc4_dummy_output *output; + struct vc4_crtc_state *new_vc4_crtc_state; + struct drm_device *drm; + struct vc4_dev *vc4; +@@ -987,8 +992,8 @@ drm_test_vc5_pv_muxing_bugs_subsequent_c + + state->acquire_ctx = &ctx; + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); +@@ -1003,8 +1008,8 @@ drm_test_vc5_pv_muxing_bugs_subsequent_c + + state->acquire_ctx = &ctx; + +- ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); +- KUNIT_ASSERT_EQ(test, ret, 0); ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); + + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); diff --git a/target/linux/bcm27xx/patches-6.1/950-0979-drm-vc4-tests-Add-BCM2712-mock-driver.patch b/target/linux/bcm27xx/patches-6.1/950-0979-drm-vc4-tests-Add-BCM2712-mock-driver.patch new file mode 100644 index 0000000000..8c12375284 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0979-drm-vc4-tests-Add-BCM2712-mock-driver.patch @@ -0,0 +1,87 @@ +From 04bec005b049604f862765b35ebd71c2a69b9e7c Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 17 Feb 2023 13:38:10 +0100 +Subject: [PATCH] drm/vc4: tests: Add BCM2712 mock driver + +The BCM2712 has a simpler pipeline that can only output to a writeback +connector and two HDMI controllers. + +Let's allow our kunit tests to create a mock of that pipeline. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.c | 29 ++++++++++++++++++++++++++++ + drivers/gpu/drm/vc4/tests/vc4_mock.h | 1 + + drivers/gpu/drm/vc4/vc4_drv.h | 2 ++ + 3 files changed, 32 insertions(+) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.c +@@ -106,6 +106,26 @@ static const struct vc4_mock_desc vc5_mo + DRM_MODE_CONNECTOR_HDMIA)), + ); + ++static const struct vc4_mock_desc vc6_mock = ++ VC4_MOCK_DESC( ++ VC4_MOCK_CRTC_DESC(&bcm2712_mop_data.base, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP0, ++ DRM_MODE_ENCODER_VIRTUAL, ++ DRM_MODE_CONNECTOR_WRITEBACK)), ++ VC4_MOCK_CRTC_DESC(&bcm2712_moplet_data.base, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP1, ++ DRM_MODE_ENCODER_VIRTUAL, ++ DRM_MODE_CONNECTOR_WRITEBACK)), ++ VC4_MOCK_PIXELVALVE_DESC(&bcm2712_pv0_data, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI0, ++ DRM_MODE_ENCODER_TMDS, ++ DRM_MODE_CONNECTOR_HDMIA)), ++ VC4_MOCK_PIXELVALVE_DESC(&bcm2712_pv1_data, ++ VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI1, ++ DRM_MODE_ENCODER_TMDS, ++ DRM_MODE_CONNECTOR_HDMIA)), ++); ++ + static int __build_one_pipe(struct kunit *test, struct drm_device *drm, + const struct vc4_mock_pipe_desc *pipe) + { +@@ -171,6 +191,10 @@ static struct vc4_dev *__mock_device(str + drv = &vc5_drm_driver; + desc = &vc5_mock; + break; ++ case VC4_GEN_6: ++ drv = &vc5_drm_driver; ++ desc = &vc6_mock; ++ break; + + default: + return NULL; +@@ -212,3 +236,8 @@ struct vc4_dev *vc5_mock_device(struct k + { + return __mock_device(test, VC4_GEN_5); + } ++ ++struct vc4_dev *vc6_mock_device(struct kunit *test) ++{ ++ return __mock_device(test, VC4_GEN_6); ++} +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h +@@ -52,6 +52,7 @@ struct vc4_dummy_output *vc4_dummy_outpu + + struct vc4_dev *vc4_mock_device(struct kunit *test); + struct vc4_dev *vc5_mock_device(struct kunit *test); ++struct vc4_dev *vc6_mock_device(struct kunit *test); + + struct vc4_dummy_output * + vc4_mock_atomic_add_output(struct kunit *test, +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -570,6 +570,8 @@ struct vc4_txp_data { + unsigned int supports_40bit_addresses:1; + }; + ++extern const struct vc4_txp_data bcm2712_mop_data; ++extern const struct vc4_txp_data bcm2712_moplet_data; + extern const struct vc4_txp_data bcm2835_txp_data; + + struct vc4_pv_data { diff --git a/target/linux/bcm27xx/patches-6.1/950-0980-drm-vc4-tests-Add-tests-for-BCM2712-PixelValve-Muxin.patch b/target/linux/bcm27xx/patches-6.1/950-0980-drm-vc4-tests-Add-tests-for-BCM2712-PixelValve-Muxin.patch new file mode 100644 index 0000000000..6c0db592c9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0980-drm-vc4-tests-Add-tests-for-BCM2712-PixelValve-Muxin.patch @@ -0,0 +1,138 @@ +From 77c14764ae164b7969e65437a87aca25b30d8b80 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 11:14:22 +0200 +Subject: [PATCH] drm/vc4: tests: Add tests for BCM2712 PixelValve Muxing + +The BCM2712 has a simpler pipeline than the BCM2711, and thus the muxing +requirements are different. Create some tests to make sure we get proper +muxing decisions. + +Signed-off-by: Maxime Ripard +--- + .../gpu/drm/vc4/tests/vc4_test_pv_muxing.c | 81 +++++++++++++++++++ + 1 file changed, 81 insertions(+) + +--- a/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c +@@ -105,6 +105,13 @@ static const struct encoder_constraint v + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI1, 0, 1, 2), + }; + ++static const struct encoder_constraint vc6_encoder_constraints[] = { ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 0), ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI1, 1), ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP1, 1), ++ ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP0, 2), ++}; ++ + static bool check_vc4_encoder_constraints(enum vc4_encoder_type type, unsigned int channel) + { + return __check_encoder_constraints(vc4_encoder_constraints, +@@ -119,6 +126,13 @@ static bool check_vc5_encoder_constraint + type, channel); + } + ++static bool check_vc6_encoder_constraints(enum vc4_encoder_type type, unsigned int channel) ++{ ++ return __check_encoder_constraints(vc6_encoder_constraints, ++ ARRAY_SIZE(vc6_encoder_constraints), ++ type, channel); ++} ++ + static struct vc4_crtc_state * + get_vc4_crtc_state_for_encoder(struct kunit *test, + const struct drm_atomic_state *state, +@@ -196,6 +210,9 @@ static void vc4_test_pv_muxing_desc(cons + #define VC5_PV_MUXING_TEST(_name, ...) \ + PV_MUXING_TEST(_name, vc5_mock_device, check_vc5_encoder_constraints, __VA_ARGS__) + ++#define VC6_PV_MUXING_TEST(_name, ...) \ ++ PV_MUXING_TEST(_name, vc6_mock_device, check_vc6_encoder_constraints, __VA_ARGS__) ++ + static const struct pv_muxing_param vc4_test_pv_muxing_params[] = { + VC4_PV_MUXING_TEST("1 output: DSI0", + VC4_ENCODER_TYPE_DSI0), +@@ -674,6 +691,54 @@ KUNIT_ARRAY_PARAM(vc5_test_pv_muxing_inv + vc5_test_pv_muxing_invalid_params, + vc4_test_pv_muxing_desc); + ++static const struct pv_muxing_param vc6_test_pv_muxing_params[] = { ++ VC6_PV_MUXING_TEST("1 output: HDMI0", ++ VC4_ENCODER_TYPE_HDMI0), ++ VC6_PV_MUXING_TEST("1 output: HDMI1", ++ VC4_ENCODER_TYPE_HDMI1), ++ VC6_PV_MUXING_TEST("1 output: MOPLET", ++ VC4_ENCODER_TYPE_TXP1), ++ VC6_PV_MUXING_TEST("1 output: MOP", ++ VC4_ENCODER_TYPE_TXP0), ++ VC6_PV_MUXING_TEST("2 outputs: HDMI0, HDMI1", ++ VC4_ENCODER_TYPE_HDMI0, ++ VC4_ENCODER_TYPE_HDMI1), ++ VC6_PV_MUXING_TEST("2 outputs: HDMI0, MOPLET", ++ VC4_ENCODER_TYPE_HDMI0, ++ VC4_ENCODER_TYPE_TXP1), ++ VC6_PV_MUXING_TEST("2 outputs: HDMI0, MOP", ++ VC4_ENCODER_TYPE_HDMI0, ++ VC4_ENCODER_TYPE_TXP0), ++ VC6_PV_MUXING_TEST("2 outputs: HDMI1, MOP", ++ VC4_ENCODER_TYPE_HDMI1, ++ VC4_ENCODER_TYPE_TXP0), ++ VC6_PV_MUXING_TEST("2 outputs: MOPLET, MOP", ++ VC4_ENCODER_TYPE_TXP1, ++ VC4_ENCODER_TYPE_TXP0), ++ VC6_PV_MUXING_TEST("3 outputs: HDMI0, HDMI1, MOP", ++ VC4_ENCODER_TYPE_HDMI0, ++ VC4_ENCODER_TYPE_HDMI1, ++ VC4_ENCODER_TYPE_TXP0), ++ VC6_PV_MUXING_TEST("3 outputs: HDMI0, MOPLET, MOP", ++ VC4_ENCODER_TYPE_HDMI0, ++ VC4_ENCODER_TYPE_TXP1, ++ VC4_ENCODER_TYPE_TXP0), ++}; ++ ++KUNIT_ARRAY_PARAM(vc6_test_pv_muxing, ++ vc6_test_pv_muxing_params, ++ vc4_test_pv_muxing_desc); ++ ++static const struct pv_muxing_param vc6_test_pv_muxing_invalid_params[] = { ++ VC6_PV_MUXING_TEST("HDMI1/MOPLET Conflict", ++ VC4_ENCODER_TYPE_HDMI1, ++ VC4_ENCODER_TYPE_TXP1), ++}; ++ ++KUNIT_ARRAY_PARAM(vc6_test_pv_muxing_invalid, ++ vc6_test_pv_muxing_invalid_params, ++ vc4_test_pv_muxing_desc); ++ + static void drm_vc4_test_pv_muxing(struct kunit *test) + { + const struct pv_muxing_param *params = test->param_value; +@@ -797,6 +862,21 @@ static struct kunit_suite vc5_pv_muxing_ + .test_cases = vc5_pv_muxing_tests, + }; + ++static struct kunit_case vc6_pv_muxing_tests[] = { ++ KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing, ++ vc6_test_pv_muxing_gen_params), ++ KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid, ++ vc6_test_pv_muxing_invalid_gen_params), ++ {} ++}; ++ ++static struct kunit_suite vc6_pv_muxing_test_suite = { ++ .name = "vc6-pv-muxing-combinations", ++ .init = vc4_pv_muxing_test_init, ++ .exit = vc4_pv_muxing_test_exit, ++ .test_cases = vc6_pv_muxing_tests, ++}; ++ + /* See + * https://lore.kernel.org/all/3e113525-aa89-b1e2-56b7-ca55bd41d057@samsung.com/ + * and +@@ -1040,5 +1120,6 @@ static struct kunit_suite vc5_pv_muxing_ + kunit_test_suites( + &vc4_pv_muxing_test_suite, + &vc5_pv_muxing_test_suite, ++ &vc6_pv_muxing_test_suite, + &vc5_pv_muxing_bugs_test_suite + ); diff --git a/target/linux/bcm27xx/patches-6.1/950-0981-drm-vc4-fkms-Rename-plane-related-functions.patch b/target/linux/bcm27xx/patches-6.1/950-0981-drm-vc4-fkms-Rename-plane-related-functions.patch new file mode 100644 index 0000000000..455c64ad2e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0981-drm-vc4-fkms-Rename-plane-related-functions.patch @@ -0,0 +1,64 @@ +From 3d849ab48cecab55862a4f2742f11937d66ba54b Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 11:21:34 +0200 +Subject: [PATCH] drm/vc4: fkms: Rename plane related functions + +The name collide with the Full KMS functions that are going to be made +public. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/vc4_firmware_kms.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c +@@ -670,8 +670,8 @@ static int vc4_plane_to_mb(struct drm_pl + return 0; + } + +-static int vc4_plane_atomic_check(struct drm_plane *plane, +- struct drm_atomic_state *state) ++static int vc4_fkms_plane_atomic_check(struct drm_plane *plane, ++ struct drm_atomic_state *state) + { + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, + plane); +@@ -728,7 +728,7 @@ static int vc4_plane_atomic_async_check( + } + + /* Called during init to allocate the plane's atomic state. */ +-static void vc4_plane_reset(struct drm_plane *plane) ++static void vc4_fkms_plane_reset(struct drm_plane *plane) + { + struct vc4_plane_state *vc4_state; + +@@ -788,7 +788,7 @@ static bool vc4_fkms_format_mod_supporte + } + } + +-static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) ++static struct drm_plane_state *vc4_fkms_plane_duplicate_state(struct drm_plane *plane) + { + struct vc4_plane_state *vc4_state; + +@@ -809,8 +809,8 @@ static const struct drm_plane_funcs vc4_ + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = vc4_plane_destroy, + .set_property = NULL, +- .reset = vc4_plane_reset, +- .atomic_duplicate_state = vc4_plane_duplicate_state, ++ .reset = vc4_fkms_plane_reset, ++ .atomic_duplicate_state = vc4_fkms_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, + .format_mod_supported = vc4_fkms_format_mod_supported, + }; +@@ -818,7 +818,7 @@ static const struct drm_plane_funcs vc4_ + static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { + .prepare_fb = drm_gem_plane_helper_prepare_fb, + .cleanup_fb = NULL, +- .atomic_check = vc4_plane_atomic_check, ++ .atomic_check = vc4_fkms_plane_atomic_check, + .atomic_update = vc4_plane_atomic_update, + .atomic_disable = vc4_plane_atomic_disable, + .atomic_async_check = vc4_plane_atomic_async_check, diff --git a/target/linux/bcm27xx/patches-6.1/950-0982-drm-vc4-tests-Use-custom-plane-state-for-mock.patch b/target/linux/bcm27xx/patches-6.1/950-0982-drm-vc4-tests-Use-custom-plane-state-for-mock.patch new file mode 100644 index 0000000000..0105753a91 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0982-drm-vc4-tests-Use-custom-plane-state-for-mock.patch @@ -0,0 +1,95 @@ +From 14fe42ff341741d60ba338c401855dee7fb68754 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 11:24:37 +0200 +Subject: [PATCH] drm/vc4: tests: Use custom plane state for mock + +The current mock planes were just using the regular drm_plane_state, +while the driver expect struct vc4_plane_state that subclasses +drm_plane_state. + +Hook the proper implementations of reset, duplicate_state, destroy and +atomic_check to create vc4_plane_state. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock_plane.c | 7 ++++--- + drivers/gpu/drm/vc4/vc4_drv.h | 6 ++++++ + drivers/gpu/drm/vc4/vc4_plane.c | 12 ++++++------ + 3 files changed, 16 insertions(+), 9 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c +@@ -10,12 +10,13 @@ + #include "vc4_mock.h" + + static const struct drm_plane_helper_funcs vc4_dummy_plane_helper_funcs = { ++ .atomic_check = vc4_plane_atomic_check, + }; + + static const struct drm_plane_funcs vc4_dummy_plane_funcs = { +- .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +- .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, +- .reset = drm_atomic_helper_plane_reset, ++ .atomic_destroy_state = vc4_plane_destroy_state, ++ .atomic_duplicate_state = vc4_plane_duplicate_state, ++ .reset = vc4_plane_reset, + }; + + static const uint32_t vc4_dummy_plane_formats[] = { +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -1145,6 +1145,12 @@ int vc4_kms_load(struct drm_device *dev) + struct drm_plane *vc4_plane_init(struct drm_device *dev, + enum drm_plane_type type, + uint32_t possible_crtcs); ++void vc4_plane_reset(struct drm_plane *plane); ++void vc4_plane_destroy_state(struct drm_plane *plane, ++ struct drm_plane_state *state); ++struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane); ++int vc4_plane_atomic_check(struct drm_plane *plane, ++ struct drm_atomic_state *state); + int vc4_plane_create_additional_planes(struct drm_device *dev); + u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist); + u32 vc4_plane_dlist_size(const struct drm_plane_state *state); +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -276,7 +276,7 @@ static bool plane_enabled(struct drm_pla + return state->fb && !WARN_ON(!state->crtc); + } + +-static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) ++struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane) + { + struct vc4_plane_state *vc4_state; + unsigned int i; +@@ -312,8 +312,8 @@ static struct drm_plane_state *vc4_plane + return &vc4_state->base; + } + +-static void vc4_plane_destroy_state(struct drm_plane *plane, +- struct drm_plane_state *state) ++void vc4_plane_destroy_state(struct drm_plane *plane, ++ struct drm_plane_state *state) + { + struct vc4_dev *vc4 = to_vc4_dev(plane->dev); + struct vc4_hvs *hvs = vc4->hvs; +@@ -348,7 +348,7 @@ static void vc4_plane_destroy_state(stru + } + + /* Called during init to allocate the plane's atomic state. */ +-static void vc4_plane_reset(struct drm_plane *plane) ++void vc4_plane_reset(struct drm_plane *plane) + { + struct vc4_plane_state *vc4_state; + +@@ -2000,8 +2000,8 @@ static int vc6_plane_mode_set(struct drm + * compute the dlist here and have all active plane dlists get updated + * in the CRTC's flush. + */ +-static int vc4_plane_atomic_check(struct drm_plane *plane, +- struct drm_atomic_state *state) ++int vc4_plane_atomic_check(struct drm_plane *plane, ++ struct drm_atomic_state *state) + { + struct vc4_dev *vc4 = to_vc4_dev(plane->dev); + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, diff --git a/target/linux/bcm27xx/patches-6.1/950-0983-drm-vc4-tests-Add-function-to-lookup-a-plane-for-a-C.patch b/target/linux/bcm27xx/patches-6.1/950-0983-drm-vc4-tests-Add-function-to-lookup-a-plane-for-a-C.patch new file mode 100644 index 0000000000..ebab218cf3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0983-drm-vc4-tests-Add-function-to-lookup-a-plane-for-a-C.patch @@ -0,0 +1,36 @@ +From 3320e449e40eeb49b601dcbbd4bd72b8cb8f3054 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 11:26:58 +0200 +Subject: [PATCH] drm/vc4: tests: Add function to lookup a plane for a CRTC + +Some tests will need to find a plane to run a test on for a given CRTC. +Let's create a small helper to do that. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.h | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h +@@ -21,6 +21,20 @@ struct drm_crtc *vc4_find_crtc_for_encod + return NULL; + } + ++static inline ++struct drm_plane *vc4_mock_find_plane_for_crtc(struct kunit *test, ++ struct drm_crtc *crtc) ++{ ++ struct drm_device *drm = crtc->dev; ++ struct drm_plane *plane; ++ ++ drm_for_each_plane(plane, drm) ++ if (plane->possible_crtcs & drm_crtc_mask(crtc)) ++ return plane; ++ ++ return NULL; ++} ++ + struct vc4_dummy_plane { + struct vc4_plane plane; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0984-drm-vc4-tests-Add-helper-to-add-a-new-plane-to-a-sta.patch b/target/linux/bcm27xx/patches-6.1/950-0984-drm-vc4-tests-Add-helper-to-add-a-new-plane-to-a-sta.patch new file mode 100644 index 0000000000..7d230294fc --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0984-drm-vc4-tests-Add-helper-to-add-a-new-plane-to-a-sta.patch @@ -0,0 +1,62 @@ +From a2f912c44b98acb6c10c977db105e199011c09b5 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 12:57:53 +0200 +Subject: [PATCH] drm/vc4: tests: Add helper to add a new plane to a state + +We'll start to add some tests for the plane state logic, so let's create +a helper to add a plane to an existing atomic state. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock.h | 4 ++++ + drivers/gpu/drm/vc4/tests/vc4_mock_plane.c | 22 ++++++++++++++++++++++ + 2 files changed, 26 insertions(+) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock.h ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h +@@ -42,6 +42,10 @@ struct vc4_dummy_plane { + struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test, + struct drm_device *drm, + enum drm_plane_type type); ++struct drm_plane * ++vc4_mock_atomic_add_plane(struct kunit *test, ++ struct drm_atomic_state *state, ++ struct drm_crtc *crtc); + + struct vc4_dummy_crtc { + struct vc4_crtc crtc; +--- a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 + + #include ++#include + #include + #include + #include +@@ -46,3 +47,24 @@ struct vc4_dummy_plane *vc4_dummy_plane( + + return dummy_plane; + } ++ ++struct drm_plane * ++vc4_mock_atomic_add_plane(struct kunit *test, ++ struct drm_atomic_state *state, ++ struct drm_crtc *crtc) ++{ ++ struct drm_plane_state *plane_state; ++ struct drm_plane *plane; ++ int ret; ++ ++ plane = vc4_mock_find_plane_for_crtc(test, crtc); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane); ++ ++ plane_state = drm_atomic_get_plane_state(state, plane); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_state); ++ ++ ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); ++ KUNIT_EXPECT_EQ(test, ret, 0); ++ ++ return plane; ++} diff --git a/target/linux/bcm27xx/patches-6.1/950-0985-drm-vc4-tests-Support-a-few-more-plane-formats.patch b/target/linux/bcm27xx/patches-6.1/950-0985-drm-vc4-tests-Support-a-few-more-plane-formats.patch new file mode 100644 index 0000000000..191181dbb6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0985-drm-vc4-tests-Support-a-few-more-plane-formats.patch @@ -0,0 +1,26 @@ +From 418d2e0e652c3870c29dd2e462f052a88fa027da Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 12:59:05 +0200 +Subject: [PATCH] drm/vc4: tests: Support a few more plane formats + +We'll start testing our planes code in situations where we will use more +than XRGB8888, so let's add a few common pixel formats. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/tests/vc4_mock_plane.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_mock_plane.c +@@ -21,7 +21,10 @@ static const struct drm_plane_funcs vc4_ + }; + + static const uint32_t vc4_dummy_plane_formats[] = { ++ DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB8888, ++ DRM_FORMAT_YUV420, ++ DRM_FORMAT_YUV422, + }; + + struct vc4_dummy_plane *vc4_dummy_plane(struct kunit *test, diff --git a/target/linux/bcm27xx/patches-6.1/950-0986-drm-vc4-tests-Introduce-a-test-for-LBM-buffer-size.patch b/target/linux/bcm27xx/patches-6.1/950-0986-drm-vc4-tests-Introduce-a-test-for-LBM-buffer-size.patch new file mode 100644 index 0000000000..5902d141ef --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0986-drm-vc4-tests-Introduce-a-test-for-LBM-buffer-size.patch @@ -0,0 +1,358 @@ +From 39ae36d19bf6e59e3091f8f0ec6f4eac59aaf6f2 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Fri, 14 Apr 2023 13:43:32 +0200 +Subject: [PATCH] drm/vc4: tests: Introduce a test for LBM buffer size + +The BCM2712 comes with a different LBM size computation than the +previous generations, so let's add the few examples provided as kunit +tests to make sure we always satisfy those requirements. + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/vc4/Makefile | 3 +- + drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c | 327 ++++++++++++++++++ + 2 files changed, 329 insertions(+), 1 deletion(-) + create mode 100644 drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c + +--- a/drivers/gpu/drm/vc4/Makefile ++++ b/drivers/gpu/drm/vc4/Makefile +@@ -31,7 +31,8 @@ vc4-$(CONFIG_DRM_VC4_KUNIT_TEST) += \ + tests/vc4_mock_crtc.o \ + tests/vc4_mock_output.o \ + tests/vc4_mock_plane.o \ +- tests/vc4_test_pv_muxing.o ++ tests/vc4_test_pv_muxing.o \ ++ tests/vc4_test_lbm_size.o + + vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o + +--- /dev/null ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c +@@ -0,0 +1,327 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../../drm_crtc_internal.h" ++#include "../../drm_internal.h" ++ ++#include ++ ++#include "../vc4_drv.h" ++ ++#include "vc4_mock.h" ++ ++u32 vc4_lbm_size(struct drm_plane_state *state); ++ ++struct vc4_lbm_size_priv { ++ struct vc4_dev *vc4; ++ struct drm_file *file; ++ struct drm_modeset_acquire_ctx ctx; ++ struct drm_atomic_state *state; ++}; ++ ++struct vc4_lbm_size_param { ++ unsigned int src_w, src_h; ++ unsigned int crtc_w, crtc_h; ++ bool forced_alpha; ++ u32 fourcc; ++ enum vc4_scaling_mode expected_x_scaling[2]; ++ enum vc4_scaling_mode expected_y_scaling[2]; ++ unsigned int expected_lbm_size; ++}; ++ ++static const struct vc4_lbm_size_param vc4_test_lbm_size_params[] = { ++ { ++ .src_w = 256, ++ .crtc_w = 256, ++ .src_h = 256, ++ .crtc_h = 512, ++ .fourcc = DRM_FORMAT_ARGB8888, ++ .expected_x_scaling = { VC4_SCALING_NONE, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 32, ++ }, ++ { ++ .src_w = 256, ++ .crtc_w = 179, ++ .src_h = 256, ++ .crtc_h = 512, ++ .fourcc = DRM_FORMAT_ARGB8888, ++ .expected_x_scaling = { VC4_SCALING_PPF, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 23, ++ }, ++ { ++ .src_w = 256, ++ .crtc_w = 256, ++ .src_h = 256, ++ .crtc_h = 512, ++ .fourcc = DRM_FORMAT_XRGB8888, ++ .expected_x_scaling = { VC4_SCALING_NONE, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 24, ++ }, ++ { ++ .src_w = 100, ++ .crtc_w = 73, ++ .src_h = 100, ++ .crtc_h = 73, ++ .fourcc = DRM_FORMAT_XRGB8888, ++ .expected_x_scaling = { VC4_SCALING_PPF, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 8, ++ }, ++ { ++ .src_w = 256, ++ .crtc_w = 256, ++ .src_h = 256, ++ .crtc_h = 512, ++ .forced_alpha = true, ++ .fourcc = DRM_FORMAT_ARGB8888, ++ .expected_x_scaling = { VC4_SCALING_NONE, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 24, ++ }, ++ { ++ .src_w = 100, ++ .crtc_w = 73, ++ .src_h = 100, ++ .crtc_h = 73, ++ .forced_alpha = true, ++ .fourcc = DRM_FORMAT_ARGB8888, ++ .expected_x_scaling = { VC4_SCALING_PPF, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, }, ++ .expected_lbm_size = 8, ++ }, ++ { ++ .src_w = 256, ++ .crtc_w = 94, ++ .src_h = 256, ++ .crtc_h = 94, ++ .fourcc = DRM_FORMAT_ARGB8888, ++ .expected_x_scaling = { VC4_SCALING_TPZ, }, ++ .expected_y_scaling = { VC4_SCALING_TPZ, }, ++ .expected_lbm_size = 6, ++ }, ++ ++/* ++ * TODO: Those tests reflect the LBM size calculation examples, but the ++ * driver ends up taking different scaler filters decisions, and thus ++ * doesn't end up with the same sizes. It would be valuable to have ++ * those tests, but the driver doesn't take a bad decision either, so ++ * it's not clear what we should do at this point. ++ */ ++#if 0 ++ { ++ .src_w = 320, ++ .crtc_w = 320, ++ .src_h = 320, ++ .crtc_h = 320, ++ .fourcc = DRM_FORMAT_YUV420, ++ .expected_x_scaling = { VC4_SCALING_NONE, VC4_SCALING_NONE, }, ++ .expected_y_scaling = { VC4_SCALING_NONE, VC4_SCALING_PPF, }, ++ .expected_lbm_size = 10, ++ }, ++ { ++ .src_w = 512, ++ .crtc_w = 512, ++ .src_h = 512, ++ .crtc_h = 256, ++ .fourcc = DRM_FORMAT_YUV420, ++ .expected_x_scaling = { VC4_SCALING_NONE, VC4_SCALING_NONE, }, ++ .expected_y_scaling = { VC4_SCALING_TPZ, VC4_SCALING_NONE, }, ++ .expected_lbm_size = 5, ++ }, ++ { ++ .src_w = 486, ++ .crtc_w = 157, ++ .src_h = 404, ++ .crtc_h = 929, ++ .fourcc = DRM_FORMAT_YUV422, ++ .expected_x_scaling = { VC4_SCALING_PPF, VC4_SCALING_PPF, }, ++ .expected_y_scaling = { VC4_SCALING_PPF, VC4_SCALING_PPF, }, ++ .expected_lbm_size = 20, ++ }, ++ { ++ .src_w = 320, ++ .crtc_w = 128, ++ .src_h = 176, ++ .crtc_h = 70, ++ .fourcc = DRM_FORMAT_YUV420, ++ .expected_x_scaling = { VC4_SCALING_TPZ, VC4_SCALING_TPZ, }, ++ .expected_y_scaling = { VC4_SCALING_TPZ, VC4_SCALING_TPZ, }, ++ .expected_lbm_size = 8, ++ }, ++#endif ++}; ++ ++static void vc4_test_lbm_size_desc(const struct vc4_lbm_size_param *t, char *desc) ++{ ++ snprintf(desc, KUNIT_PARAM_DESC_SIZE, ++ "%ux%u to %ux%u %s(%p4cc)", ++ t->src_w, t->src_h, ++ t->crtc_w, t->crtc_h, ++ t->forced_alpha ? "with forced alpha " : "", ++ &t->fourcc); ++} ++ ++KUNIT_ARRAY_PARAM(vc4_test_lbm_size, ++ vc4_test_lbm_size_params, ++ vc4_test_lbm_size_desc); ++ ++static void drm_vc4_test_vc4_lbm_size(struct kunit *test) ++{ ++ const struct vc4_lbm_size_param *params = test->param_value; ++ const struct vc4_lbm_size_priv *priv = test->priv; ++ const struct drm_format_info *info; ++ struct drm_mode_fb_cmd2 fb_req = { }; ++ struct drm_atomic_state *state = priv->state; ++ struct vc4_plane_state *vc4_plane_state; ++ struct drm_plane_state *plane_state; ++ struct vc4_dummy_output *output; ++ struct drm_framebuffer *fb; ++ struct drm_plane *plane; ++ struct drm_crtc *crtc; ++ unsigned int i; ++ int ret; ++ ++ info = drm_format_info(params->fourcc); ++ KUNIT_ASSERT_NOT_NULL(test, info); ++ ++ output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output); ++ ++ crtc = vc4_find_crtc_for_encoder(test, &output->encoder.base); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc); ++ ++ plane = vc4_mock_atomic_add_plane(test, state, crtc); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane); ++ ++ plane_state = drm_atomic_get_plane_state(state, plane); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_state); ++ ++ vc4_plane_state = to_vc4_plane_state(plane_state); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4_plane_state); ++ ++ fb_req.pixel_format = params->fourcc; ++ fb_req.width = params->src_w; ++ fb_req.height = params->src_h; ++ ++ for (i = 0; i < info->num_planes; i++) { ++ struct drm_mode_create_dumb dumb_args = { }; ++ ++ dumb_args.width = params->src_w; ++ dumb_args.height = params->src_h; ++ dumb_args.bpp = drm_format_info_bpp(info, i); ++ ++ ret = drm_mode_create_dumb(state->dev, &dumb_args, priv->file); ++ KUNIT_ASSERT_EQ(test, ret, 0); ++ ++ fb_req.handles[i] = dumb_args.handle; ++ fb_req.pitches[i] = dumb_args.pitch; ++ } ++ ++ fb = drm_internal_framebuffer_create(state->dev, &fb_req, priv->file); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fb); ++ ++ drm_atomic_set_fb_for_plane(plane_state, fb); ++ ++ plane_state->src_x = 0; ++ plane_state->src_y = 0; ++ plane_state->src_h = params->src_h << 16; ++ plane_state->src_w = params->src_w << 16; ++ ++ plane_state->crtc_x = 0; ++ plane_state->crtc_y = 0; ++ plane_state->crtc_h = params->crtc_h; ++ plane_state->crtc_w = params->crtc_w; ++ ++ if (params->forced_alpha) ++ plane_state->alpha = 128; ++ ++ ret = drm_atomic_check_only(state); ++ KUNIT_ASSERT_EQ(test, ret, 0); ++ ++ KUNIT_EXPECT_EQ(test, vc4_plane_state->lbm.size, params->expected_lbm_size); ++ ++ for (i = 0; i < 2; i++) { ++ KUNIT_EXPECT_EQ(test, ++ vc4_plane_state->x_scaling[i], ++ params->expected_x_scaling[i]); ++ KUNIT_EXPECT_EQ(test, ++ vc4_plane_state->y_scaling[i], ++ params->expected_y_scaling[i]); ++ } ++ ++ drm_framebuffer_put(fb); ++ ++ for (i = 0; i < info->num_planes; i++) ++ drm_mode_destroy_dumb(state->dev, fb_req.handles[i], priv->file); ++} ++ ++static struct kunit_case vc4_lbm_size_tests[] = { ++ KUNIT_CASE_PARAM(drm_vc4_test_vc4_lbm_size, ++ vc4_test_lbm_size_gen_params), ++ {} ++}; ++ ++static int vc4_lbm_size_test_init(struct kunit *test) ++{ ++ struct drm_atomic_state *state; ++ struct vc4_lbm_size_priv *priv; ++ struct drm_device *drm; ++ struct vc4_dev *vc4; ++ ++ priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); ++ KUNIT_ASSERT_NOT_NULL(test, priv); ++ test->priv = priv; ++ ++ vc4 = vc6_mock_device(test); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); ++ priv->vc4 = vc4; ++ ++ priv->file = drm_file_alloc(priv->vc4->base.primary); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->file); ++ ++ drm_modeset_acquire_init(&priv->ctx, 0); ++ ++ drm = &vc4->base; ++ state = drm_atomic_state_alloc(drm); ++ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); ++ ++ state->acquire_ctx = &priv->ctx; ++ ++ priv->state = state; ++ ++ return 0; ++} ++ ++static void vc4_lbm_size_test_exit(struct kunit *test) ++{ ++ struct vc4_lbm_size_priv *priv = test->priv; ++ struct vc4_dev *vc4 = priv->vc4; ++ struct drm_device *drm = &vc4->base; ++ struct drm_atomic_state *state = priv->state; ++ ++ drm_atomic_state_put(state); ++ drm_modeset_drop_locks(&priv->ctx); ++ drm_modeset_acquire_fini(&priv->ctx); ++ drm_file_free(priv->file); ++ drm_dev_unregister(drm); ++ drm_kunit_helper_free_device(test, vc4->dev); ++} ++ ++static struct kunit_suite vc4_lbm_size_test_suite = { ++ .name = "vc4-lbm-size", ++ .init = vc4_lbm_size_test_init, ++ .exit = vc4_lbm_size_test_exit, ++ .test_cases = vc4_lbm_size_tests, ++}; ++ ++kunit_test_suite(vc4_lbm_size_test_suite); diff --git a/target/linux/bcm27xx/patches-6.1/950-0987-drm-vc4-kms-Avoid-setting-core-and-disp-clocks-for-h.patch b/target/linux/bcm27xx/patches-6.1/950-0987-drm-vc4-kms-Avoid-setting-core-and-disp-clocks-for-h.patch new file mode 100644 index 0000000000..f20b0cf3f8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0987-drm-vc4-kms-Avoid-setting-core-and-disp-clocks-for-h.patch @@ -0,0 +1,40 @@ +From 352d96c9e50012f2b5e5dde9933af8d570e7dc81 Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Mon, 17 Jul 2023 17:45:32 +0100 +Subject: [PATCH] drm/vc4: kms: Avoid setting core and disp clocks for hdmi + modes + +On 2712, the firmware always runs these clock at a speed sufficient +for dual 4kp60. + +The requests here prevent the gpu from going into its lowest voltage +mode, so just skip the clock requests. + +With this applied the idle voltage on my pi 5 reduces from 0.7424V +to 0.72V. + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_kms.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -435,7 +435,7 @@ static void vc4_atomic_commit_tail(struc + old_hvs_state->fifo_state[channel].pending_commit = NULL; + } + +- if (vc4->gen >= VC4_GEN_5 && !vc4->firmware_kms) { ++ if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long state_rate = max(old_hvs_state->core_clock_rate, + new_hvs_state->core_clock_rate); + unsigned long core_rate = clamp_t(unsigned long, state_rate, +@@ -489,7 +489,7 @@ static void vc4_atomic_commit_tail(struc + + drm_atomic_helper_cleanup_planes(dev, state); + +- if (vc4->gen >= VC4_GEN_5 && !vc4->firmware_kms) { ++ if (vc4->gen == VC4_GEN_5 && !vc4->firmware_kms) { + unsigned long core_rate = min_t(unsigned long, + hvs->max_core_rate, + new_hvs_state->core_clock_rate); diff --git a/target/linux/bcm27xx/patches-6.1/950-0988-drm-vc4-Assign-LBM-memory-during-atomic_flush.patch b/target/linux/bcm27xx/patches-6.1/950-0988-drm-vc4-Assign-LBM-memory-during-atomic_flush.patch new file mode 100644 index 0000000000..b489bbc7f7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0988-drm-vc4-Assign-LBM-memory-during-atomic_flush.patch @@ -0,0 +1,240 @@ +From bb0839405b61da6e6ae7141f7433f6a121725e6f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 31 Aug 2023 11:45:38 +0100 +Subject: [PATCH] drm/vc4: Assign LBM memory during atomic_flush. + +Avoid double buffering LBM allocations by making the +allocation a single alloc per crtc at atomic_flush. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c | 2 +- + drivers/gpu/drm/vc4/vc4_drv.h | 8 ++-- + drivers/gpu/drm/vc4/vc4_hvs.c | 47 ++++++++++++++++++- + drivers/gpu/drm/vc4/vc4_plane.c | 38 +++------------ + 4 files changed, 58 insertions(+), 37 deletions(-) + +--- a/drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c ++++ b/drivers/gpu/drm/vc4/tests/vc4_test_lbm_size.c +@@ -248,7 +248,7 @@ static void drm_vc4_test_vc4_lbm_size(st + ret = drm_atomic_check_only(state); + KUNIT_ASSERT_EQ(test, ret, 0); + +- KUNIT_EXPECT_EQ(test, vc4_plane_state->lbm.size, params->expected_lbm_size); ++ KUNIT_EXPECT_EQ(test, vc4_plane_state->lbm_size, params->expected_lbm_size); + + for (i = 0; i < 2; i++) { + KUNIT_EXPECT_EQ(test, +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -437,6 +437,8 @@ struct vc4_plane_state { + u32 dlist_size; /* Number of dwords allocated for the display list */ + u32 dlist_count; /* Number of used dwords in the display list. */ + ++ u32 lbm_size; /* LBM requirements for this plane */ ++ + /* Offset in the dlist to various words, for pageflip or + * cursor updates. + */ +@@ -462,9 +464,6 @@ struct vc4_plane_state { + bool is_unity; + bool is_yuv; + +- /* Our allocation in LBM for temporary storage during scaling. */ +- struct drm_mm_node lbm; +- + /* Our allocation in UPM for prefetching. */ + struct drm_mm_node upm[DRM_FORMAT_MAX_PLANES]; + +@@ -661,6 +660,9 @@ struct vc4_crtc { + * access to that value. + */ + unsigned int current_hvs_channel; ++ ++ /* @lbm: Our allocation in LBM for temporary storage during scaling. */ ++ struct drm_mm_node lbm; + }; + + static inline struct vc4_crtc * +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1103,6 +1103,7 @@ int vc4_hvs_atomic_check(struct drm_crtc + struct drm_plane *plane; + const struct drm_plane_state *plane_state; + u32 dlist_count = 0; ++ u32 lbm_count = 0; + + /* The pixelvalve can only feed one encoder (and encoders are + * 1:1 with connectors.) +@@ -1111,6 +1112,8 @@ int vc4_hvs_atomic_check(struct drm_crtc + return -EINVAL; + + drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) { ++ const struct vc4_plane_state *vc4_plane_state = ++ to_vc4_plane_state(plane_state); + u32 plane_dlist_count = vc4_plane_dlist_size(plane_state); + + drm_dbg_driver(dev, "[CRTC:%d:%s] Found [PLANE:%d:%s] with DLIST size: %u\n", +@@ -1119,6 +1122,7 @@ int vc4_hvs_atomic_check(struct drm_crtc + plane_dlist_count); + + dlist_count += plane_dlist_count; ++ lbm_count += vc4_plane_state->lbm_size; + } + + dlist_count++; /* Account for SCALER_CTL0_END. */ +@@ -1132,6 +1136,8 @@ int vc4_hvs_atomic_check(struct drm_crtc + + vc4_state->mm = alloc; + ++ /* FIXME: Check total lbm allocation here */ ++ + return vc4_hvs_gamma_check(crtc, state); + } + +@@ -1246,7 +1252,10 @@ void vc4_hvs_atomic_flush(struct drm_crt + bool debug_dump_regs = false; + bool enable_bg_fill = false; + u32 __iomem *dlist_start, *dlist_next; ++ unsigned long irqflags; + unsigned int zpos = 0; ++ u32 lbm_offset = 0; ++ u32 lbm_size = 0; + bool found = false; + int idx; + +@@ -1265,6 +1274,35 @@ void vc4_hvs_atomic_flush(struct drm_crt + vc4_hvs_dump_state(hvs); + } + ++ drm_atomic_crtc_for_each_plane(plane, crtc) { ++ vc4_plane_state = to_vc4_plane_state(plane->state); ++ lbm_size += vc4_plane_state->lbm_size; ++ } ++ ++ if (drm_mm_node_allocated(&vc4_crtc->lbm)) { ++ spin_lock_irqsave(&vc4_crtc->irq_lock, irqflags); ++ drm_mm_remove_node(&vc4_crtc->lbm); ++ spin_unlock_irqrestore(&vc4_crtc->irq_lock, irqflags); ++ } ++ ++ if (lbm_size) { ++ int ret; ++ ++ spin_lock_irqsave(&vc4_crtc->irq_lock, irqflags); ++ ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, ++ &vc4_crtc->lbm, ++ lbm_size, 1, ++ 0, 0); ++ spin_unlock_irqrestore(&vc4_crtc->irq_lock, irqflags); ++ ++ if (ret) { ++ pr_err("Failed to allocate LBM ret %d\n", ret); ++ return; ++ } ++ } ++ ++ lbm_offset = vc4_crtc->lbm.start; ++ + dlist_start = vc4->hvs->dlist + vc4_state->mm->mm_node.start; + dlist_next = dlist_start; + +@@ -1276,6 +1314,8 @@ void vc4_hvs_atomic_flush(struct drm_crt + if (plane->state->normalized_zpos != zpos) + continue; + ++ vc4_plane_state = to_vc4_plane_state(plane->state); ++ + /* Is this the first active plane? */ + if (dlist_next == dlist_start) { + /* We need to enable background fill when a plane +@@ -1286,10 +1326,15 @@ void vc4_hvs_atomic_flush(struct drm_crt + * already needs it or all planes on top blend from + * the first or a lower plane. + */ +- vc4_plane_state = to_vc4_plane_state(plane->state); + enable_bg_fill = vc4_plane_state->needs_bg_fill; + } + ++ if (vc4_plane_state->lbm_size) { ++ vc4_plane_state->dlist[vc4_plane_state->lbm_offset] = ++ lbm_offset; ++ lbm_offset += vc4_plane_state->lbm_size; ++ } ++ + dlist_next += vc4_plane_write_dlist(plane, dlist_next); + + found = true; +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -288,7 +288,6 @@ struct drm_plane_state *vc4_plane_duplic + if (!vc4_state) + return NULL; + +- memset(&vc4_state->lbm, 0, sizeof(vc4_state->lbm)); + memset(&vc4_state->upm, 0, sizeof(vc4_state->upm)); + + for (i = 0; i < DRM_FORMAT_MAX_PLANES; i++) +@@ -320,14 +319,6 @@ void vc4_plane_destroy_state(struct drm_ + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); + unsigned int i; + +- if (drm_mm_node_allocated(&vc4_state->lbm)) { +- unsigned long irqflags; +- +- spin_lock_irqsave(&hvs->mm_lock, irqflags); +- drm_mm_remove_node(&vc4_state->lbm); +- spin_unlock_irqrestore(&hvs->mm_lock, irqflags); +- } +- + for (i = 0; i < DRM_FORMAT_MAX_PLANES; i++) { + unsigned long irqflags; + +@@ -903,12 +894,13 @@ static int vc4_plane_allocate_lbm(struct + struct vc4_dev *vc4 = to_vc4_dev(drm); + struct drm_plane *plane = state->plane; + struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); +- unsigned long irqflags; + u32 lbm_size; + + lbm_size = vc4_lbm_size(state); +- if (!lbm_size) ++ if (!lbm_size) { ++ vc4_state->lbm_size = 0; + return 0; ++ } + + /* + * NOTE: BCM2712 doesn't need to be aligned, since the size +@@ -925,28 +917,10 @@ static int vc4_plane_allocate_lbm(struct + if (WARN_ON(!vc4_state->lbm_offset)) + return -EINVAL; + +- /* Allocate the LBM memory that the HVS will use for temporary +- * storage due to our scaling/format conversion. ++ /* FIXME: Add loop here that ensures that the total LBM assigned in this ++ * state is less than the total lbm size + */ +- if (!drm_mm_node_allocated(&vc4_state->lbm)) { +- int ret; +- +- spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags); +- ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, +- &vc4_state->lbm, +- lbm_size, 1, +- 0, 0); +- spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); +- +- if (ret) { +- drm_err(drm, "Failed to allocate LBM entry: %d\n", ret); +- return ret; +- } +- } else { +- WARN_ON_ONCE(lbm_size != vc4_state->lbm.size); +- } +- +- vc4_state->dlist[vc4_state->lbm_offset] = vc4_state->lbm.start; ++ vc4_state->lbm_size = lbm_size; + + return 0; + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0989-drm-panel-simple-Alter-the-timing-for-the-Pi-7-DSI-d.patch b/target/linux/bcm27xx/patches-6.1/950-0989-drm-panel-simple-Alter-the-timing-for-the-Pi-7-DSI-d.patch new file mode 100644 index 0000000000..ef70de7ee4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0989-drm-panel-simple-Alter-the-timing-for-the-Pi-7-DSI-d.patch @@ -0,0 +1,33 @@ +From b1bd2f406eab321be642decd6aee6b6222aec62b Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 28 Jul 2023 17:40:27 +0100 +Subject: [PATCH] drm/panel: simple: Alter the timing for the Pi 7" DSI display + +vc4 has always fixed up the timing, so the values defined have +never actually appeared on the wire. +The display appears to want a slightly longer HFP, so extend +the timings and recompute the clock to give the same frame rate. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/panel/panel-simple.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/panel/panel-simple.c ++++ b/drivers/gpu/drm/panel/panel-simple.c +@@ -3241,11 +3241,11 @@ static const struct panel_desc qishenglo + }; + + static const struct drm_display_mode raspberrypi_7inch_mode = { +- .clock = 25979400 / 1000, ++ .clock = 27777, + .hdisplay = 800, +- .hsync_start = 800 + 2, +- .hsync_end = 800 + 2 + 2, +- .htotal = 800 + 2 + 2 + 46, ++ .hsync_start = 800 + 59, ++ .hsync_end = 800 + 59 + 2, ++ .htotal = 800 + 59 + 2 + 46, + .vdisplay = 480, + .vsync_start = 480 + 7, + .vsync_end = 480 + 7 + 2, diff --git a/target/linux/bcm27xx/patches-6.1/950-0990-drm-panel-waveshare-Fix-up-timings-for-10.1-panel.patch b/target/linux/bcm27xx/patches-6.1/950-0990-drm-panel-waveshare-Fix-up-timings-for-10.1-panel.patch new file mode 100644 index 0000000000..0a4203fbc5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0990-drm-panel-waveshare-Fix-up-timings-for-10.1-panel.patch @@ -0,0 +1,33 @@ +From c7cf33911d477fe55a91a9e4d84dad857b244ae3 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 28 Jul 2023 18:10:53 +0100 +Subject: [PATCH] drm/panel: waveshare: Fix up timings for 10.1" panel + +The 10.1" panel doesn't work with the timings defined. vc4 +will always have been fixing up the timing due to the limited +integer divider, so compute the fixed up mode and use it +directly. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/panel/panel-waveshare-dsi.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/panel/panel-waveshare-dsi.c ++++ b/drivers/gpu/drm/panel/panel-waveshare-dsi.c +@@ -112,11 +112,11 @@ static const struct drm_display_mode ws_ + * https://www.waveshare.com/product/raspberry-pi/displays/10.1inch-dsi-lcd-c.htm + */ + static const struct drm_display_mode ws_panel_10_1_mode = { +- .clock = 76800, ++ .clock = 83333, + .hdisplay = 1280, +- .hsync_start = 1280 + 40, +- .hsync_end = 1280 + 40 + 20, +- .htotal = 1280 + 40 + 20 + 40, ++ .hsync_start = 1280 + 156, ++ .hsync_end = 1280 + 156 + 20, ++ .htotal = 1280 + 156 + 20 + 40, + .vdisplay = 800, + .vsync_start = 800 + 40, + .vsync_end = 800 + 40 + 48, diff --git a/target/linux/bcm27xx/patches-6.1/950-0991-media-i2c-imx477-Fix-locking-in-imx477_init_controls.patch b/target/linux/bcm27xx/patches-6.1/950-0991-media-i2c-imx477-Fix-locking-in-imx477_init_controls.patch new file mode 100644 index 0000000000..9d7869af9c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0991-media-i2c-imx477-Fix-locking-in-imx477_init_controls.patch @@ -0,0 +1,34 @@ +From 72c25bbb761de2b2acd9f8b652d63e2a2f1caeed Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Mon, 11 Sep 2023 12:17:25 +0300 +Subject: [PATCH] media: i2c: imx477: Fix locking in imx477_init_controls() + +The driver does not lock the imx477 mutex when calling +imx477_set_framing_limits(), leading to: + +WARNING: CPU: 3 PID: 426 at drivers/media/v4l2-core/v4l2-ctrls-api.c:934 __v4l2_ctrl_modify_range+0x1a0/0x210 [ +videodev] + +Fix this by taking the lock. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/i2c/imx477.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -2069,9 +2069,13 @@ static int imx477_init_controls(struct i + + imx477->sd.ctrl_handler = ctrl_hdlr; + ++ mutex_lock(&imx477->mutex); ++ + /* Setup exposure and frame/line length limits. */ + imx477_set_framing_limits(imx477); + ++ mutex_unlock(&imx477->mutex); ++ + return 0; + + error: diff --git a/target/linux/bcm27xx/patches-6.1/950-0994-overlays-Fix-vc4-kms-dsi-7inch.patch b/target/linux/bcm27xx/patches-6.1/950-0994-overlays-Fix-vc4-kms-dsi-7inch.patch new file mode 100644 index 0000000000..10339e2774 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0994-overlays-Fix-vc4-kms-dsi-7inch.patch @@ -0,0 +1,57 @@ +From 2ff65ffbdeb0c8764985af19df2a687a126136f4 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 29 Sep 2023 16:55:28 +0100 +Subject: [PATCH] overlays: Fix vc4-kms-dsi-7inch + +Fix the touchscreen. + +See: https://github.com/raspberrypi/linux/issues/5619 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/edt-ft5406.dtsi | 13 ++++--------- + .../boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts | 2 +- + 2 files changed, 5 insertions(+), 10 deletions(-) + +--- a/arch/arm/boot/dts/overlays/edt-ft5406.dtsi ++++ b/arch/arm/boot/dts/overlays/edt-ft5406.dtsi +@@ -22,11 +22,13 @@ + }; + }; + +- fragment@12 { +- target = <&i2cbus>; ++ ts_i2c_frag: fragment@12 { ++ target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; ++ status = "okay"; ++ + ft5406: ts@38 { + compatible = "edt,edt-ft5506"; + reg = <0x38>; +@@ -37,13 +39,6 @@ + }; + }; + +- ts_i2c_frag: fragment@13 { +- target = <&i2c_csi_dsi>; +- i2cbus: __overlay__ { +- status = "okay"; +- }; +- }; +- + __overrides__ { + sizex = <&ft5406>,"touchscreen-size-x:0"; + sizey = <&ft5406>,"touchscreen-size-y:0"; +--- a/arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-7inch-overlay.dts +@@ -119,6 +119,6 @@ + <&panel_disp>, "reg:0=0", + <®_bridge>, "reg:0=0", + <®_bridge>, "regulator-name=bridge_reg_0"; +- disable_touch = <0>, "-10-11-12"; ++ disable_touch = <&ft5406>, "status=disabled"; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-0996-ASoC-hdmi-codec-Fix-broken-channel-map-reporting.patch b/target/linux/bcm27xx/patches-6.1/950-0996-ASoC-hdmi-codec-Fix-broken-channel-map-reporting.patch new file mode 100644 index 0000000000..c8fd2a2f90 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0996-ASoC-hdmi-codec-Fix-broken-channel-map-reporting.patch @@ -0,0 +1,56 @@ +From a1caea3c996f6bfa8c9568f521257f4e473285fb Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Fri, 29 Sep 2023 21:50:28 +0200 +Subject: [PATCH] ASoC: hdmi-codec: Fix broken channel map reporting + +Commit b84b53149476b22cc3b8677b771fb4cf06d1d455 upstream. + +Commit 4e0871333661 ("ASoC: hdmi-codec: fix channel info for +compressed formats") accidentally changed hcp->chmap_idx from +ca_id, the CEA channel allocation ID, to idx, the index to +the table of channel mappings ordered by preference. + +This resulted in wrong channel maps being reported to userspace, +eg for 5.1 "FL,FR,LFE,FC" was reported instead of the expected +"FL,FR,LFE,FC,RL,RR": + +~ # speaker-test -c 6 -t sine +... + 0 - Front Left + 3 - Front Center + 1 - Front Right + 2 - LFE + 4 - Unknown + 5 - Unknown + +~ # amixer cget iface=PCM,name='Playback Channel Map' | grep ': values' + : values=3,4,8,7,0,0,0,0 + +Switch this back to ca_id in case of PCM audio so the correct channel +map is reported again and set it to HDMI_CODEC_CHMAP_IDX_UNKNOWN in +case of non-PCM audio so the PCM channel map control returns "Unknown" +channels (value 0). + +Fixes: 4e0871333661 ("ASoC: hdmi-codec: fix channel info for compressed formats") +Cc: stable@vger.kernel.org +Signed-off-by: Matthias Reichl +Link: https://lore.kernel.org/r/20230929195027.97136-1-hias@horus.com +Signed-off-by: Mark Brown +--- + sound/soc/codecs/hdmi-codec.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/sound/soc/codecs/hdmi-codec.c ++++ b/sound/soc/codecs/hdmi-codec.c +@@ -520,7 +520,10 @@ static int hdmi_codec_fill_codec_params( + hp->sample_rate = sample_rate; + hp->channels = channels; + +- hcp->chmap_idx = idx; ++ if (pcm_audio) ++ hcp->chmap_idx = ca_id; ++ else ++ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; + + return 0; + } diff --git a/target/linux/bcm27xx/patches-6.1/950-0997-media-rp1-cfe-Fix-use-of-freed-memory-on-errors.patch b/target/linux/bcm27xx/patches-6.1/950-0997-media-rp1-cfe-Fix-use-of-freed-memory-on-errors.patch new file mode 100644 index 0000000000..7f1b505336 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0997-media-rp1-cfe-Fix-use-of-freed-memory-on-errors.patch @@ -0,0 +1,48 @@ +From 3922bebc11fcc8459c798cfcb582828f9bbaa9e9 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 28 Sep 2023 11:33:53 +0300 +Subject: [PATCH] media: rp1: cfe: Fix use of freed memory on errors + +cfe_probe_complete() calls cfe_put() on both success and fail code paths. +This works for the success path, but causes the cfe_device struct to be +freed, even if it will be used later in the teardown code. + +Fix this by making the ref handling a bit saner: Let the video nodes +have the refs as they do now, but also keep a ref in the "main" driver, +released only at cfe_remove() time. This way the driver does not depend +on the video nodes keeping the refs. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -1837,17 +1837,10 @@ static int cfe_probe_complete(struct cfe + goto unregister; + } + +- /* +- * Release the initial reference, all references are now owned by the +- * video devices. +- */ +- cfe_put(cfe); + return 0; + + unregister: + cfe_unregister_nodes(cfe); +- cfe_put(cfe); +- + return ret; + } + +@@ -2129,6 +2122,8 @@ static int cfe_remove(struct platform_de + + v4l2_device_unregister(&cfe->v4l2_dev); + ++ cfe_put(cfe); ++ + return 0; + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-0998-media-rp1-cfe-Fix-width-height-in-cfe_start_channel.patch b/target/linux/bcm27xx/patches-6.1/950-0998-media-rp1-cfe-Fix-width-height-in-cfe_start_channel.patch new file mode 100644 index 0000000000..d49856c32d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0998-media-rp1-cfe-Fix-width-height-in-cfe_start_channel.patch @@ -0,0 +1,88 @@ +From 84c9958dd71b8a4dcf16cbf6fdb867c668652634 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Wed, 27 Sep 2023 16:00:39 +0300 +Subject: [PATCH] media: rp1: cfe: Fix width & height in cfe_start_channel() + +The logic for handling width & height in cfe_start_channel() is somewhat +odd and, afaics, broken. The code reads: + +bool start_fe = is_fe_enabled(cfe) && + test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING); + +if (start_fe || is_image_output_node(node)) { + width = node->fmt.fmt.pix.width; + height = node->fmt.fmt.pix.height; +} + +cfe_start_channel() is called for all video nodes that will be used. So +this means that if, say, fe_stats is enabled as the last node, start_fe +will be true, and width and height will be taken from fe_stats' node. +The width and height will thus contain garbage, which then gets +programmed to the csi2 registers. + +It seems that this often still works fine, though, probably if the width +& height are large enough. + +Drop the above code, and instead get the width & height from the csi2 +subdev's sink pad for the csi2 channel that is used. For metadata the +width & height will be 0 as before. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -763,20 +763,16 @@ static void cfe_start_channel(struct cfe + struct v4l2_mbus_framefmt *source_fmt; + const struct cfe_fmt *fmt; + unsigned long flags; +- unsigned int width = 0, height = 0; + bool start_fe = is_fe_enabled(cfe) && + test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING); + + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); + +- if (start_fe || is_image_output_node(node)) { +- width = node->fmt.fmt.pix.width; +- height = node->fmt.fmt.pix.height; +- } +- + state = v4l2_subdev_lock_and_get_active_state(&cfe->csi2.sd); + + if (start_fe) { ++ unsigned int width, height; ++ + WARN_ON(!is_fe_enabled(cfe)); + cfe_dbg("%s: %s using csi2 channel %d\n", + __func__, node_desc[FE_OUT0].name, +@@ -785,6 +781,9 @@ static void cfe_start_channel(struct cfe + source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, cfe->fe_csi2_channel); + fmt = find_format_by_code(source_fmt->code); + ++ width = source_fmt->width; ++ height = source_fmt->height; ++ + /* + * Start the associated CSI2 Channel as well. + * +@@ -800,6 +799,8 @@ static void cfe_start_channel(struct cfe + } + + if (is_csi2_node(node)) { ++ unsigned int width = 0, height = 0; ++ + u32 mode = CSI2_MODE_NORMAL; + + source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, +@@ -807,6 +808,9 @@ static void cfe_start_channel(struct cfe + fmt = find_format_by_code(source_fmt->code); + + if (is_image_output_node(node)) { ++ width = source_fmt->width; ++ height = source_fmt->height; ++ + if (node->fmt.fmt.pix.pixelformat == + fmt->remap[CFE_REMAP_16BIT]) + mode = CSI2_MODE_REMAP; diff --git a/target/linux/bcm27xx/patches-6.1/950-0999-media-rp1-csi2-Fix-missing-reg-writes.patch b/target/linux/bcm27xx/patches-6.1/950-0999-media-rp1-csi2-Fix-missing-reg-writes.patch new file mode 100644 index 0000000000..2a3915b6e3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-0999-media-rp1-csi2-Fix-missing-reg-writes.patch @@ -0,0 +1,36 @@ +From 62e8ab88d2c230dad122aabe2ad0e227d7ceba40 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 28 Sep 2023 10:42:22 +0300 +Subject: [PATCH] media: rp1: csi2: Fix missing reg writes + +The driver has two places where it writes a register based on a +condition, and when that condition is false, the driver presumes that +the register has the reset value. This is not a good idea, so fix those +places to always write the register. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/csi2.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -253,6 +253,7 @@ void csi2_start_channel(struct csi2_devi + */ + set_field(&ctrl, 0x3ff, LC_MASK); + set_field(&ctrl, 0x00, CH_MODE_MASK); ++ csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), 0); + } + + set_field(&ctrl, dt, DT_MASK); +@@ -277,8 +278,8 @@ void csi2_open_rx(struct csi2_device *cs + { + dphy_start(&csi2->dphy); + +- if (!csi2->multipacket_line) +- csi2_reg_write(csi2, CSI2_CTRL, EOP_IS_EOL); ++ csi2_reg_write(csi2, CSI2_CTRL, ++ csi2->multipacket_line ? 0 : EOP_IS_EOL); + } + + void csi2_close_rx(struct csi2_device *csi2) diff --git a/target/linux/bcm27xx/patches-6.1/950-1000-media-rp1-fe-Use-0-not-1-when-working-with-unsigned-.patch b/target/linux/bcm27xx/patches-6.1/950-1000-media-rp1-fe-Use-0-not-1-when-working-with-unsigned-.patch new file mode 100644 index 0000000000..f468b7ac48 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1000-media-rp1-fe-Use-0-not-1-when-working-with-unsigned-.patch @@ -0,0 +1,33 @@ +From 455c4ae2c70348a5842835d2f67f7cd8e665a2a6 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 21 Sep 2023 16:03:07 +0300 +Subject: [PATCH] media: rp1: fe: Use ~0, not -1, when working with unsigned + values + +Use ~0, not -1, when working with unsigned values (-1 is not unsigned). + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -372,7 +372,7 @@ void pisp_fe_submit_job(struct pisp_fe_d + void pisp_fe_start(struct pisp_fe_device *fe) + { + pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_RESET); +- pisp_fe_reg_write(fe, FE_INT_STATUS, -1); ++ pisp_fe_reg_write(fe, FE_INT_STATUS, ~0); + pisp_fe_reg_write(fe, FE_INT_EN, FE_INT_EOF | FE_INT_SOF | FE_INT_LINES0 | FE_INT_LINES1); + fe->inframe_count = 0; + } +@@ -383,7 +383,7 @@ void pisp_fe_stop(struct pisp_fe_device + pisp_fe_reg_write(fe, FE_CONTROL, FE_CONTROL_ABORT); + usleep_range(1000, 2000); + WARN_ON(pisp_fe_reg_read(fe, FE_STATUS)); +- pisp_fe_reg_write(fe, FE_INT_STATUS, -1); ++ pisp_fe_reg_write(fe, FE_INT_STATUS, ~0); + } + + static struct pisp_fe_device *to_pisp_fe_device(struct v4l2_subdev *subdev) diff --git a/target/linux/bcm27xx/patches-6.1/950-1001-media-rp1-cfe-Fix-verbose-debug-print.patch b/target/linux/bcm27xx/patches-6.1/950-1001-media-rp1-cfe-Fix-verbose-debug-print.patch new file mode 100644 index 0000000000..3344c32d29 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1001-media-rp1-cfe-Fix-verbose-debug-print.patch @@ -0,0 +1,26 @@ +From bf1709d2cf2b57c4ea98b8363156835249ae02cc Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 22 Sep 2023 12:41:35 +0300 +Subject: [PATCH] media: rp1: cfe: Fix verbose debug print + +The debug print in cfe_schedule_next_csi2_job() is printed every frame, +and should thus use cfe_dbg_irq() to avoid spamming, rather than cfe_dbg(). + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -518,8 +518,8 @@ static void cfe_schedule_next_csi2_job(s + node->next_frm = buf; + list_del(&buf->list); + +- cfe_dbg("%s: [%s] buffer:%p\n", +- __func__, node_desc[node->id].name, &buf->vb.vb2_buf); ++ cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, &buf->vb.vb2_buf); + + if (is_meta_node(node)) { + size = node->fmt.fmt.meta.buffersize; diff --git a/target/linux/bcm27xx/patches-6.1/950-1002-media-rp1-cfe-Rename-xxx_dbg_irq-to-xxx_dbg_verbose.patch b/target/linux/bcm27xx/patches-6.1/950-1002-media-rp1-cfe-Rename-xxx_dbg_irq-to-xxx_dbg_verbose.patch new file mode 100644 index 0000000000..14fa0447df --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1002-media-rp1-cfe-Rename-xxx_dbg_irq-to-xxx_dbg_verbose.patch @@ -0,0 +1,227 @@ +From a1ea528e187ee045aeff929ff0f4b2e53fdd970f Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Wed, 4 Oct 2023 10:12:37 +0300 +Subject: [PATCH] media: rp1: cfe: Rename xxx_dbg_irq() to xxx_dbg_verbose() + +Rename the xxx_dbg_irq() macros to xxx_dbg_verbose(), as they can be +used to verbose debugs outside irq context too. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 40 +++++++++---------- + .../media/platform/raspberrypi/rp1_cfe/cfe.h | 2 +- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 26 ++++++------ + .../platform/raspberrypi/rp1_cfe/pisp_fe.c | 12 +++--- + 4 files changed, 40 insertions(+), 40 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -49,11 +49,11 @@ + #define CFE_MODULE_NAME "rp1-cfe" + #define CFE_VERSION "1.0" + +-bool cfe_debug_irq; ++bool cfe_debug_verbose; + +-#define cfe_dbg_irq(fmt, arg...) \ ++#define cfe_dbg_verbose(fmt, arg...) \ + do { \ +- if (cfe_debug_irq) \ ++ if (cfe_debug_verbose) \ + dev_dbg(&cfe->pdev->dev, fmt, ##arg); \ + } while (0) + #define cfe_dbg(fmt, arg...) dev_dbg(&cfe->pdev->dev, fmt, ##arg) +@@ -518,8 +518,8 @@ static void cfe_schedule_next_csi2_job(s + node->next_frm = buf; + list_del(&buf->list); + +- cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, +- node_desc[node->id].name, &buf->vb.vb2_buf); ++ cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, &buf->vb.vb2_buf); + + if (is_meta_node(node)) { + size = node->fmt.fmt.meta.buffersize; +@@ -550,8 +550,8 @@ static void cfe_schedule_next_pisp_job(s + buf = list_first_entry(&node->dma_queue, struct cfe_buffer, + list); + +- cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, +- node_desc[node->id].name, &buf->vb.vb2_buf); ++ cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, &buf->vb.vb2_buf); + + node->next_frm = buf; + vb2_bufs[node_desc[i].link_pad] = &buf->vb.vb2_buf; +@@ -573,8 +573,8 @@ static bool cfe_check_job_ready(struct c + continue; + + if (list_empty(&node->dma_queue)) { +- cfe_dbg_irq("%s: [%s] has no buffer, unable to schedule job\n", +- __func__, node_desc[i].name); ++ cfe_dbg_verbose("%s: [%s] has no buffer, unable to schedule job\n", ++ __func__, node_desc[i].name); + return false; + } + } +@@ -592,7 +592,7 @@ static void cfe_prepare_next_job(struct + /* Flag if another job is ready after this. */ + cfe->job_ready = cfe_check_job_ready(cfe); + +- cfe_dbg_irq("%s: end with scheduled job\n", __func__); ++ cfe_dbg_verbose("%s: end with scheduled job\n", __func__); + } + + static void cfe_process_buffer_complete(struct cfe_node *node, +@@ -600,8 +600,8 @@ static void cfe_process_buffer_complete( + { + struct cfe_device *cfe = node->cfe; + +- cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, +- &node->cur_frm->vb.vb2_buf); ++ cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, &node->cur_frm->vb.vb2_buf); + + node->cur_frm->vb.sequence = sequence; + vb2_buffer_done(&node->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); +@@ -621,8 +621,8 @@ static void cfe_sof_isr_handler(struct c + { + struct cfe_device *cfe = node->cfe; + +- cfe_dbg_irq("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, +- cfe->sequence); ++ cfe_dbg_verbose("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, ++ cfe->sequence); + + node->cur_frm = node->next_frm; + node->next_frm = NULL; +@@ -651,8 +651,8 @@ static void cfe_eof_isr_handler(struct c + { + struct cfe_device *cfe = node->cfe; + +- cfe_dbg_irq("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, +- cfe->sequence); ++ cfe_dbg_verbose("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, ++ cfe->sequence); + + if (node->cur_frm) + cfe_process_buffer_complete(node, cfe->sequence); +@@ -921,8 +921,8 @@ static int cfe_buffer_prepare(struct vb2 + struct cfe_buffer *buf = to_cfe_buffer(vb); + unsigned long size; + +- cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, +- vb); ++ cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, vb); + + size = is_image_output_node(node) ? node->fmt.fmt.pix.sizeimage : + node->fmt.fmt.meta.buffersize; +@@ -954,8 +954,8 @@ static void cfe_buffer_queue(struct vb2_ + struct cfe_buffer *buf = to_cfe_buffer(vb); + unsigned long flags; + +- cfe_dbg_irq("%s: [%s] buffer:%p\n", __func__, node_desc[node->id].name, +- vb); ++ cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, ++ node_desc[node->id].name, vb); + + spin_lock_irqsave(&cfe->state_lock, flags); + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h +@@ -11,7 +11,7 @@ + #include + #include + +-extern bool cfe_debug_irq; ++extern bool cfe_debug_verbose; + + enum cfe_remap_types { + CFE_REMAP_16BIT, +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -16,9 +16,9 @@ + #include "csi2.h" + #include "cfe.h" + +-#define csi2_dbg_irq(fmt, arg...) \ ++#define csi2_dbg_verbose(fmt, arg...) \ + do { \ +- if (cfe_debug_irq) \ ++ if (cfe_debug_verbose) \ + dev_dbg(csi2->v4l2_dev->dev, fmt, ##arg); \ + } while (0) + #define csi2_dbg(fmt, arg...) dev_dbg(csi2->v4l2_dev->dev, fmt, ##arg) +@@ -154,7 +154,7 @@ void csi2_isr(struct csi2_device *csi2, + u32 status; + + status = csi2_reg_read(csi2, CSI2_STATUS); +- csi2_dbg_irq("ISR: STA: 0x%x\n", status); ++ csi2_dbg_verbose("ISR: STA: 0x%x\n", status); + + /* Write value back to clear the interrupts */ + csi2_reg_write(csi2, CSI2_STATUS, status); +@@ -167,16 +167,16 @@ void csi2_isr(struct csi2_device *csi2, + + dbg = csi2_reg_read(csi2, CSI2_CH_DEBUG(i)); + +- csi2_dbg_irq("ISR: [%u], %s%s%s%s%s frame: %u line: %u\n", i, +- (status & IRQ_FS(i)) ? "FS " : "", +- (status & IRQ_FE(i)) ? "FE " : "", +- (status & IRQ_FE_ACK(i)) ? "FE_ACK " : "", +- (status & IRQ_LE(i)) ? "LE " : "", +- (status & IRQ_LE_ACK(i)) ? "LE_ACK " : "", +- dbg >> 16, +- csi2->num_lines[i] ? +- ((dbg & 0xffff) % csi2->num_lines[i]) : +- 0); ++ csi2_dbg_verbose("ISR: [%u], %s%s%s%s%s frame: %u line: %u\n", ++ i, (status & IRQ_FS(i)) ? "FS " : "", ++ (status & IRQ_FE(i)) ? "FE " : "", ++ (status & IRQ_FE_ACK(i)) ? "FE_ACK " : "", ++ (status & IRQ_LE(i)) ? "LE " : "", ++ (status & IRQ_LE_ACK(i)) ? "LE_ACK " : "", ++ dbg >> 16, ++ csi2->num_lines[i] ? ++ ((dbg & 0xffff) % csi2->num_lines[i]) : ++ 0); + + sof[i] = !!(status & IRQ_FS(i)); + eof[i] = !!(status & IRQ_FE_ACK(i)); +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -114,9 +114,9 @@ static const struct pisp_fe_config_param + sizeof(struct pisp_fe_output_config) }, + }; + +-#define pisp_fe_dbg_irq(fmt, arg...) \ ++#define pisp_fe_dbg_verbose(fmt, arg...) \ + do { \ +- if (cfe_debug_irq) \ ++ if (cfe_debug_verbose) \ + dev_dbg(fe->v4l2_dev->dev, fmt, ##arg); \ + } while (0) + #define pisp_fe_dbg(fmt, arg...) dev_dbg(fe->v4l2_dev->dev, fmt, ##arg) +@@ -202,9 +202,9 @@ void pisp_fe_isr(struct pisp_fe_device * + int_status = pisp_fe_reg_read(fe, FE_INT_STATUS); + pisp_fe_reg_write(fe, FE_INT_STATUS, int_status); + +- pisp_fe_dbg_irq("%s: status 0x%x out 0x%x frame 0x%x error 0x%x int 0x%x\n", +- __func__, status, out_status, frame_status, error_status, +- int_status); ++ pisp_fe_dbg_verbose("%s: status 0x%x out 0x%x frame 0x%x error 0x%x int 0x%x\n", ++ __func__, status, out_status, frame_status, error_status, ++ int_status); + + /* We do not report interrupts for the input/stream pad. */ + for (i = 0; i < FE_NUM_PADS - 1; i++) { +@@ -339,7 +339,7 @@ void pisp_fe_submit_job(struct pisp_fe_d + * sequence of relaxed writes which follow. + */ + status = pisp_fe_reg_read(fe, FE_STATUS); +- pisp_fe_dbg_irq("%s: status = 0x%x\n", __func__, status); ++ pisp_fe_dbg_verbose("%s: status = 0x%x\n", __func__, status); + if (WARN_ON(status & FE_STATUS_QUEUED)) + return; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1003-media-rp1-Add-back-reg-write-debug-prints.patch b/target/linux/bcm27xx/patches-6.1/950-1003-media-rp1-Add-back-reg-write-debug-prints.patch new file mode 100644 index 0000000000..c86f7a3e17 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1003-media-rp1-Add-back-reg-write-debug-prints.patch @@ -0,0 +1,41 @@ +From 8240f1328ead0152f116b385b3169f8f010a7869 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 22 Sep 2023 12:39:33 +0300 +Subject: [PATCH] media: rp1: Add back reg write debug prints + +Add back debug prints in csi2 and pisp_fe reg_write() functions, but use +the 'irq' variants to avoid spamming in normal situation. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/csi2.c | 1 + + drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c | 2 ++ + 2 files changed, 3 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -92,6 +92,7 @@ static inline u32 csi2_reg_read(struct c + static inline void csi2_reg_write(struct csi2_device *csi2, u32 offset, u32 val) + { + writel(val, csi2->base + offset); ++ csi2_dbg_verbose("csi2: write 0x%04x -> 0x%03x\n", val, offset); + } + + static inline void set_field(u32 *valp, u32 field, u32 mask) +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -132,12 +132,14 @@ static inline void pisp_fe_reg_write(str + u32 val) + { + writel(val, fe->base + offset); ++ pisp_fe_dbg_verbose("fe: write 0x%04x -> 0x%03x\n", val, offset); + } + + static inline void pisp_fe_reg_write_relaxed(struct pisp_fe_device *fe, u32 offset, + u32 val) + { + writel_relaxed(val, fe->base + offset); ++ pisp_fe_dbg_verbose("fe: write 0x%04x -> 0x%03x\n", val, offset); + } + + static int pisp_regs_show(struct seq_file *s, void *data) diff --git a/target/linux/bcm27xx/patches-6.1/950-1004-media-rp1-cfe-Add-verbose-debug-module-parameter.patch b/target/linux/bcm27xx/patches-6.1/950-1004-media-rp1-cfe-Add-verbose-debug-module-parameter.patch new file mode 100644 index 0000000000..f44cb50d10 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1004-media-rp1-cfe-Add-verbose-debug-module-parameter.patch @@ -0,0 +1,23 @@ +From f2553458c0c1942731447aac3878f51aa1b326a7 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Wed, 4 Oct 2023 10:19:47 +0300 +Subject: [PATCH] media: rp1: cfe: Add verbose debug module parameter + +Expose the verbose debug flag as a module parameter. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -50,6 +50,8 @@ + #define CFE_VERSION "1.0" + + bool cfe_debug_verbose; ++module_param_named(verbose_debug, cfe_debug_verbose, bool, 0644); ++MODULE_PARM_DESC(verbose_debug, "verbose debugging messages"); + + #define cfe_dbg_verbose(fmt, arg...) \ + do { \ diff --git a/target/linux/bcm27xx/patches-6.1/950-1005-media-rp1-csi2-Track-CSI-2-errors.patch b/target/linux/bcm27xx/patches-6.1/950-1005-media-rp1-csi2-Track-CSI-2-errors.patch new file mode 100644 index 0000000000..9d8da81887 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1005-media-rp1-csi2-Track-CSI-2-errors.patch @@ -0,0 +1,245 @@ +From b19c2b5f88f141e58044e5d1012f867d46f74bf3 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 21 Sep 2023 18:18:53 +0300 +Subject: [PATCH] media: rp1: csi2: Track CSI-2 errors + +Track the errors from the CSI-2 receiver: overflows and discards. These +are recorded in a table which can be read by the userspace via debugfs. + +As tracking the errors may cause much more interrupt load, the tracking +needs to be enabled with a module parameter. + +Note that the recording is not perfect: we only record the last +discarded DT for each discard type, instead of recording all of them. +This means that e.g. if the device is discarding two unmatched DTs, the +debugfs file only shows the last one recorded. Recording all of them +would need a more sophisticated recording system to avoid the need of a +very large table, or dynamic allocation. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 123 ++++++++++++++++++ + .../media/platform/raspberrypi/rp1_cfe/csi2.h | 16 +++ + 2 files changed, 139 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -16,6 +16,10 @@ + #include "csi2.h" + #include "cfe.h" + ++static bool csi2_track_errors; ++module_param_named(track_csi2_errors, csi2_track_errors, bool, 0); ++MODULE_PARM_DESC(track_csi2_errors, "track csi-2 errors"); ++ + #define csi2_dbg_verbose(fmt, arg...) \ + do { \ + if (cfe_debug_verbose) \ +@@ -32,9 +36,28 @@ + #define CSI2_DISCARDS_INACTIVE 0x00c + #define CSI2_DISCARDS_UNMATCHED 0x010 + #define CSI2_DISCARDS_LEN_LIMIT 0x014 ++ ++#define CSI2_DISCARDS_AMOUNT_SHIFT 0 ++#define CSI2_DISCARDS_AMOUNT_MASK GENMASK(23, 0) ++#define CSI2_DISCARDS_DT_SHIFT 24 ++#define CSI2_DISCARDS_DT_MASK GENMASK(29, 24) ++#define CSI2_DISCARDS_VC_SHIFT 30 ++#define CSI2_DISCARDS_VC_MASK GENMASK(31, 30) ++ + #define CSI2_LLEV_PANICS 0x018 + #define CSI2_ULEV_PANICS 0x01c + #define CSI2_IRQ_MASK 0x020 ++#define CSI2_IRQ_MASK_IRQ_OVERFLOW BIT(0) ++#define CSI2_IRQ_MASK_IRQ_DISCARD_OVERFLOW BIT(1) ++#define CSI2_IRQ_MASK_IRQ_DISCARD_LENGTH_LIMIT BIT(2) ++#define CSI2_IRQ_MASK_IRQ_DISCARD_UNMATCHED BIT(3) ++#define CSI2_IRQ_MASK_IRQ_DISCARD_INACTIVE BIT(4) ++#define CSI2_IRQ_MASK_IRQ_ALL \ ++ (CSI2_IRQ_MASK_IRQ_OVERFLOW | CSI2_IRQ_MASK_IRQ_DISCARD_OVERFLOW | \ ++ CSI2_IRQ_MASK_IRQ_DISCARD_LENGTH_LIMIT | \ ++ CSI2_IRQ_MASK_IRQ_DISCARD_UNMATCHED | \ ++ CSI2_IRQ_MASK_IRQ_DISCARD_INACTIVE) ++ + #define CSI2_CTRL 0x024 + #define CSI2_CH_CTRL(x) ((x) * 0x40 + 0x28) + #define CSI2_CH_ADDR0(x) ((x) * 0x40 + 0x2c) +@@ -149,6 +172,92 @@ static int csi2_regs_show(struct seq_fil + + DEFINE_SHOW_ATTRIBUTE(csi2_regs); + ++static int csi2_errors_show(struct seq_file *s, void *data) ++{ ++ struct csi2_device *csi2 = s->private; ++ unsigned long flags; ++ u32 discards_table[DISCARDS_TABLE_NUM_VCS][DISCARDS_TABLE_NUM_ENTRIES]; ++ u32 discards_dt_table[DISCARDS_TABLE_NUM_ENTRIES]; ++ u32 overflows; ++ ++ spin_lock_irqsave(&csi2->errors_lock, flags); ++ ++ memcpy(discards_table, csi2->discards_table, sizeof(discards_table)); ++ memcpy(discards_dt_table, csi2->discards_dt_table, ++ sizeof(discards_dt_table)); ++ overflows = csi2->overflows; ++ ++ csi2->overflows = 0; ++ memset(csi2->discards_table, 0, sizeof(discards_table)); ++ memset(csi2->discards_dt_table, 0, sizeof(discards_dt_table)); ++ ++ spin_unlock_irqrestore(&csi2->errors_lock, flags); ++ ++ seq_printf(s, "Overflows %u\n", overflows); ++ seq_puts(s, "Discards:\n"); ++ seq_puts(s, "VC OVLF LEN UNMATCHED INACTIVE\n"); ++ ++ for (unsigned int vc = 0; vc < DISCARDS_TABLE_NUM_VCS; ++vc) { ++ seq_printf(s, "%u %10u %10u %10u %10u\n", vc, ++ discards_table[vc][DISCARDS_TABLE_OVERFLOW], ++ discards_table[vc][DISCARDS_TABLE_LENGTH_LIMIT], ++ discards_table[vc][DISCARDS_TABLE_UNMATCHED], ++ discards_table[vc][DISCARDS_TABLE_INACTIVE]); ++ } ++ ++ seq_printf(s, "Last DT %10u %10u %10u %10u\n", ++ discards_dt_table[DISCARDS_TABLE_OVERFLOW], ++ discards_dt_table[DISCARDS_TABLE_LENGTH_LIMIT], ++ discards_dt_table[DISCARDS_TABLE_UNMATCHED], ++ discards_dt_table[DISCARDS_TABLE_INACTIVE]); ++ ++ return 0; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(csi2_errors); ++ ++static void csi2_isr_handle_errors(struct csi2_device *csi2, u32 status) ++{ ++ spin_lock(&csi2->errors_lock); ++ ++ if (status & IRQ_OVERFLOW) ++ csi2->overflows++; ++ ++ for (unsigned int i = 0; i < DISCARDS_TABLE_NUM_ENTRIES; ++i) { ++ static const u32 discard_bits[] = { ++ IRQ_DISCARD_OVERFLOW, ++ IRQ_DISCARD_LEN_LIMIT, ++ IRQ_DISCARD_UNMATCHED, ++ IRQ_DISCARD_INACTIVE, ++ }; ++ static const u8 discard_regs[] = { ++ CSI2_DISCARDS_OVERFLOW, ++ CSI2_DISCARDS_LEN_LIMIT, ++ CSI2_DISCARDS_UNMATCHED, ++ CSI2_DISCARDS_INACTIVE, ++ }; ++ u32 amount; ++ u8 dt, vc; ++ u32 v; ++ ++ if (!(status & discard_bits[i])) ++ continue; ++ ++ v = csi2_reg_read(csi2, discard_regs[i]); ++ csi2_reg_write(csi2, discard_regs[i], 0); ++ ++ amount = (v & CSI2_DISCARDS_AMOUNT_MASK) >> ++ CSI2_DISCARDS_AMOUNT_SHIFT; ++ dt = (v & CSI2_DISCARDS_DT_MASK) >> CSI2_DISCARDS_DT_SHIFT; ++ vc = (v & CSI2_DISCARDS_VC_MASK) >> CSI2_DISCARDS_VC_SHIFT; ++ ++ csi2->discards_table[vc][i] += amount; ++ csi2->discards_dt_table[i] = dt; ++ } ++ ++ spin_unlock(&csi2->errors_lock); ++} ++ + void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci) + { + unsigned int i; +@@ -183,6 +292,9 @@ void csi2_isr(struct csi2_device *csi2, + eof[i] = !!(status & IRQ_FE_ACK(i)); + lci[i] = !!(status & IRQ_LE_ACK(i)); + } ++ ++ if (csi2_track_errors) ++ csi2_isr_handle_errors(csi2, status); + } + + void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel, +@@ -277,6 +389,9 @@ void csi2_stop_channel(struct csi2_devic + + void csi2_open_rx(struct csi2_device *csi2) + { ++ csi2_reg_write(csi2, CSI2_IRQ_MASK, ++ csi2_track_errors ? CSI2_IRQ_MASK_IRQ_ALL : 0); ++ + dphy_start(&csi2->dphy); + + csi2_reg_write(csi2, CSI2_CTRL, +@@ -286,6 +401,8 @@ void csi2_open_rx(struct csi2_device *cs + void csi2_close_rx(struct csi2_device *csi2) + { + dphy_stop(&csi2->dphy); ++ ++ csi2_reg_write(csi2, CSI2_IRQ_MASK, 0); + } + + static struct csi2_device *to_csi2_device(struct v4l2_subdev *subdev) +@@ -398,11 +515,17 @@ int csi2_init(struct csi2_device *csi2, + { + unsigned int i, ret; + ++ spin_lock_init(&csi2->errors_lock); ++ + csi2->dphy.dev = csi2->v4l2_dev->dev; + dphy_probe(&csi2->dphy); + + debugfs_create_file("csi2_regs", 0444, debugfs, csi2, &csi2_regs_fops); + ++ if (csi2_track_errors) ++ debugfs_create_file("csi2_errors", 0444, debugfs, csi2, ++ &csi2_errors_fops); ++ + for (i = 0; i < CSI2_NUM_CHANNELS * 2; i++) + csi2->pad[i].flags = i < CSI2_NUM_CHANNELS ? + MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h +@@ -17,6 +17,8 @@ + + #define CSI2_NUM_CHANNELS 4 + ++#define DISCARDS_TABLE_NUM_VCS 4 ++ + enum csi2_mode { + CSI2_MODE_NORMAL, + CSI2_MODE_REMAP, +@@ -37,6 +39,14 @@ struct csi2_cfg { + u32 buffer_size; + }; + ++enum discards_table_index { ++ DISCARDS_TABLE_OVERFLOW = 0, ++ DISCARDS_TABLE_LENGTH_LIMIT, ++ DISCARDS_TABLE_UNMATCHED, ++ DISCARDS_TABLE_INACTIVE, ++ DISCARDS_TABLE_NUM_ENTRIES, ++}; ++ + struct csi2_device { + /* Parent V4l2 device */ + struct v4l2_device *v4l2_dev; +@@ -53,6 +63,12 @@ struct csi2_device { + + struct media_pad pad[CSI2_NUM_CHANNELS * 2]; + struct v4l2_subdev sd; ++ ++ /* lock for csi2 errors counters */ ++ spinlock_t errors_lock; ++ u32 overflows; ++ u32 discards_table[DISCARDS_TABLE_NUM_VCS][DISCARDS_TABLE_NUM_ENTRIES]; ++ u32 discards_dt_table[DISCARDS_TABLE_NUM_ENTRIES]; + }; + + void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci); diff --git a/target/linux/bcm27xx/patches-6.1/950-1006-media-rp1-cfe-Drop-unused-field.patch b/target/linux/bcm27xx/patches-6.1/950-1006-media-rp1-cfe-Drop-unused-field.patch new file mode 100644 index 0000000000..b53a5b6154 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1006-media-rp1-cfe-Drop-unused-field.patch @@ -0,0 +1,31 @@ +From d6bd676b49cf10046665efde820b0cc00dc43994 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 28 Sep 2023 17:04:07 +0300 +Subject: [PATCH] media: rp1: cfe: Drop unused field + +Drop 'sensor_embedded_data' field, as it is unused. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -292,7 +292,6 @@ struct cfe_device { + struct csi2_device csi2; + struct pisp_fe_device fe; + +- bool sensor_embedded_data; + int fe_csi2_channel; + + unsigned int sequence; +@@ -1821,8 +1820,6 @@ static int cfe_probe_complete(struct cfe + + cfe->v4l2_dev.notify = cfe_notify; + +- cfe->sensor_embedded_data = (cfe->sensor->entity.num_pads >= 2); +- + for (i = 0; i < NUM_NODES; i++) { + ret = cfe_register_node(cfe, i); + if (ret) { diff --git a/target/linux/bcm27xx/patches-6.1/950-1007-media-rp1-csi2-Set-values-for-enum-csi2_mode.patch b/target/linux/bcm27xx/patches-6.1/950-1007-media-rp1-csi2-Set-values-for-enum-csi2_mode.patch new file mode 100644 index 0000000000..126ee2c493 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1007-media-rp1-csi2-Set-values-for-enum-csi2_mode.patch @@ -0,0 +1,30 @@ +From c56b53d62116b4672962124afab02f3beada4244 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 12:57:23 +0300 +Subject: [PATCH] media: rp1: csi2: Set values for enum csi2_mode + +Set hardcoded values for enum csi2_mode, as the values will be +programmed to HW registers. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/csi2.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h +@@ -20,10 +20,10 @@ + #define DISCARDS_TABLE_NUM_VCS 4 + + enum csi2_mode { +- CSI2_MODE_NORMAL, +- CSI2_MODE_REMAP, +- CSI2_MODE_COMPRESSED, +- CSI2_MODE_FE_STREAMING ++ CSI2_MODE_NORMAL = 0, ++ CSI2_MODE_REMAP = 1, ++ CSI2_MODE_COMPRESSED = 2, ++ CSI2_MODE_FE_STREAMING = 3, + }; + + enum csi2_compression_mode { diff --git a/target/linux/bcm27xx/patches-6.1/950-1008-media-rp1-fe-Fix-default-mbus-code.patch b/target/linux/bcm27xx/patches-6.1/950-1008-media-rp1-fe-Fix-default-mbus-code.patch new file mode 100644 index 0000000000..e4ea9e1d16 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1008-media-rp1-fe-Fix-default-mbus-code.patch @@ -0,0 +1,27 @@ +From 5edacf33de9e0349dd5a02ad684bfceae1d5565f Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 13:29:15 +0300 +Subject: [PATCH] media: rp1: fe: Fix default mbus code + +When pisp_fe_pad_set_fmt() is given an mbus code that CFE does not +support, it currently defaults to MEDIA_BUS_FMT_SBGGR10_1X10. This is +not correct, as FE does not support SBGGR10. + +Set the default to MEDIA_BUS_FMT_SRGGB16_1X16 instead. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -437,7 +437,7 @@ static int pisp_fe_pad_set_fmt(struct v4 + case FE_OUTPUT1_PAD: + cfe_fmt = find_format_by_code(format->format.code); + if (!cfe_fmt || !(cfe_fmt->flags & CFE_FORMAT_FLAG_FE_OUT)) +- cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10); ++ cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SRGGB16_1X16); + + format->format.code = cfe_fmt->code; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1009-media-rp1-cfe-Fix-default-meta-format-s-field.patch b/target/linux/bcm27xx/patches-6.1/950-1009-media-rp1-cfe-Fix-default-meta-format-s-field.patch new file mode 100644 index 0000000000..2ac5e0e88a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1009-media-rp1-cfe-Fix-default-meta-format-s-field.patch @@ -0,0 +1,25 @@ +From 47fd9528bc1d93dd07ce9baa19c736966b536bd9 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Mon, 2 Oct 2023 14:38:07 +0300 +Subject: [PATCH] media: rp1: cfe: Fix default meta format's field + +Set default meta format's field to V4L2_FIELD_NONE, instead of zeroing +it which indicates V4L2_FIELD_ANY. Metadata doesn't have fields, so NONE +makes sense, and furthermore the default v4l2 link validation will check +for matching fields, or that the sink field is NONE. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -110,6 +110,7 @@ const struct v4l2_mbus_framefmt cfe_defa + .width = 8192, + .height = 1, + .code = MEDIA_BUS_FMT_SENSOR_DATA, ++ .field = V4L2_FIELD_NONE, + }; + + enum node_ids { diff --git a/target/linux/bcm27xx/patches-6.1/950-1010-media-rp1-cfe-Fail-streaming-if-FE_CONFIG-node-is-no.patch b/target/linux/bcm27xx/patches-6.1/950-1010-media-rp1-cfe-Fail-streaming-if-FE_CONFIG-node-is-no.patch new file mode 100644 index 0000000000..de469c3565 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1010-media-rp1-cfe-Fail-streaming-if-FE_CONFIG-node-is-no.patch @@ -0,0 +1,31 @@ +From 3e2203b265ddd8630fea0fbb69b3a2ec1496f773 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 4 Oct 2023 09:39:59 +0100 +Subject: [PATCH] media: rp1: cfe: Fail streaming if FE_CONFIG node is not + enabled + +When the FE is enabled, ensure that the FE_CONFIG node is enabled. +Otherwise fail cfe_start_streaming() entirely. + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -997,6 +997,14 @@ static int cfe_start_streaming(struct vb + goto err_streaming; + } + ++ /* When using the Frontend, we must enable the FE_CONFIG node. */ ++ if (is_fe_enabled(cfe) && ++ !check_state(cfe, NODE_ENABLED, cfe->node[FE_CONFIG].id)) { ++ cfe_err("FE enabled, but FE_CONFIG node is not\n"); ++ ret = -EINVAL; ++ goto err_streaming; ++ } ++ + ret = media_pipeline_start(&node->pad, &cfe->pipe); + if (ret < 0) { + cfe_err("Failed to start media pipeline: %d\n", ret); diff --git a/target/linux/bcm27xx/patches-6.1/950-1011-media-i2c-Move-Kconfig-entry-for-IMX477-to-the-camer.patch b/target/linux/bcm27xx/patches-6.1/950-1011-media-i2c-Move-Kconfig-entry-for-IMX477-to-the-camer.patch new file mode 100644 index 0000000000..37e1a86e16 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1011-media-i2c-Move-Kconfig-entry-for-IMX477-to-the-camer.patch @@ -0,0 +1,51 @@ +From 52811174f534824f5e5bcdb681f0c508aa335244 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 4 Oct 2023 11:09:10 +0100 +Subject: [PATCH] media: i2c: Move Kconfig entry for IMX477 to the camera + sensor section + +It was accidentally placed in the audio decoder section. + +Signed-off-by: Naushir Patuck +--- + drivers/media/i2c/Kconfig | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/drivers/media/i2c/Kconfig ++++ b/drivers/media/i2c/Kconfig +@@ -270,6 +270,17 @@ config VIDEO_IMX412 + To compile this driver as a module, choose M here: the + module will be called imx412. + ++config VIDEO_IMX477 ++ tristate "Sony IMX477 sensor support" ++ depends on I2C && VIDEO_DEV ++ select VIDEO_V4L2_SUBDEV_API ++ help ++ This is a Video4Linux2 sensor driver for the Sony ++ IMX477 camera. Also supports the Sony IMX378. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called imx477. ++ + config VIDEO_IMX519 + tristate "Arducam IMX519 sensor support" + depends on I2C && VIDEO_DEV +@@ -1106,17 +1117,6 @@ config VIDEO_UDA1342 + To compile this driver as a module, choose M here: the + module will be called uda1342. + +-config VIDEO_IMX477 +- tristate "Sony IMX477 sensor support" +- depends on I2C && VIDEO_DEV +- select VIDEO_V4L2_SUBDEV_API +- help +- This is a Video4Linux2 sensor driver for the Sony +- IMX477 camera. Also supports the Sony IMX378. +- +- To compile this driver as a module, choose M here: the +- module will be called imx477. +- + config VIDEO_VP27SMPX + tristate "Panasonic VP27's internal MPX" + depends on VIDEO_DEV && I2C diff --git a/target/linux/bcm27xx/patches-6.1/950-1013-drm-Look-for-an-alias-for-the-displays-to-use-as-the.patch b/target/linux/bcm27xx/patches-6.1/950-1013-drm-Look-for-an-alias-for-the-displays-to-use-as-the.patch new file mode 100644 index 0000000000..8de6c372c0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1013-drm-Look-for-an-alias-for-the-displays-to-use-as-the.patch @@ -0,0 +1,109 @@ +From 3aa1f2477545ea6298bc6f2d7ffae68f090af9b8 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 28 Sep 2023 18:27:09 +0100 +Subject: [PATCH] drm: Look for an alias for the displays to use as the DRM + device name + +Allow DT aliases of eg DSI2 to force make DRM allocate the +display with the requested name. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_connector.c | 60 ++++++++++++++++++++++++++++++--- + 1 file changed, 56 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/drm_connector.c ++++ b/drivers/gpu/drm/drm_connector.c +@@ -81,6 +81,7 @@ struct drm_conn_prop_enum_list { + int type; + const char *name; + struct ida ida; ++ int first_dyn_num; + }; + + /* +@@ -110,12 +111,41 @@ static struct drm_conn_prop_enum_list dr + { DRM_MODE_CONNECTOR_USB, "USB" }, + }; + ++#define MAX_DT_NODE_NAME_LEN 20 ++#define DT_DRM_NODE_PREFIX "drm_" ++ ++static void drm_connector_get_of_name(int type, char *node_name, int length) ++{ ++ int i = 0; ++ ++ strcpy(node_name, DT_DRM_NODE_PREFIX); ++ ++ do { ++ node_name[i + strlen(DT_DRM_NODE_PREFIX)] = ++ tolower(drm_connector_enum_list[type].name[i]); ++ ++ } while (drm_connector_enum_list[type].name[i++] && ++ i < length); ++ ++ node_name[length - 1] = '\0'; ++} ++ + void drm_connector_ida_init(void) + { +- int i; ++ int i, id; ++ char node_name[MAX_DT_NODE_NAME_LEN]; + +- for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++) ++ for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++) { + ida_init(&drm_connector_enum_list[i].ida); ++ ++ drm_connector_get_of_name(i, node_name, MAX_DT_NODE_NAME_LEN); ++ ++ id = of_alias_get_highest_id(node_name); ++ if (id > 0) ++ drm_connector_enum_list[i].first_dyn_num = id + 1; ++ else ++ drm_connector_enum_list[i].first_dyn_num = 1; ++ } + } + + void drm_connector_ida_destroy(void) +@@ -222,7 +252,9 @@ static int __drm_connector_init(struct d + struct i2c_adapter *ddc) + { + struct drm_mode_config *config = &dev->mode_config; ++ char node_name[MAX_DT_NODE_NAME_LEN]; + int ret; ++ int id; + struct ida *connector_ida = + &drm_connector_enum_list[connector_type].ida; + +@@ -252,8 +284,28 @@ static int __drm_connector_init(struct d + ret = 0; + + connector->connector_type = connector_type; +- connector->connector_type_id = +- ida_alloc_min(connector_ida, 1, GFP_KERNEL); ++ connector->connector_type_id = 0; ++ ++ drm_connector_get_of_name(connector_type, node_name, MAX_DT_NODE_NAME_LEN); ++ id = of_alias_get_id(dev->dev->of_node, node_name); ++ if (id > 0) { ++ /* Try and allocate the requested ID ++ * Valid range is 1 to 31, hence ignoring 0 as an error ++ */ ++ int type_id = ida_alloc_range(connector_ida, id, id, GFP_KERNEL); ++ ++ if (type_id > 0) ++ connector->connector_type_id = type_id; ++ else ++ drm_err(dev, "Failed to acquire type ID %d for interface type %s, ret %d\n", ++ id, drm_connector_enum_list[connector_type].name, ++ type_id); ++ } ++ if (!connector->connector_type_id) ++ connector->connector_type_id = ++ ida_alloc_min(connector_ida, ++ drm_connector_enum_list[connector_type].first_dyn_num, ++ GFP_KERNEL); + if (connector->connector_type_id < 0) { + ret = connector->connector_type_id; + goto out_put_id; diff --git a/target/linux/bcm27xx/patches-6.1/950-1014-dt-Add-DSI1-and-DSI2-aliases-to-2712.patch b/target/linux/bcm27xx/patches-6.1/950-1014-dt-Add-DSI1-and-DSI2-aliases-to-2712.patch new file mode 100644 index 0000000000..6d79cb6c4d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1014-dt-Add-DSI1-and-DSI2-aliases-to-2712.patch @@ -0,0 +1,24 @@ +From 7ec42740a45b21bca859cde5b7cbe2f09ef3d586 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 28 Sep 2023 18:40:36 +0100 +Subject: [PATCH] dt: Add DSI1 and DSI2 aliases to 2712 + +In order to keep the DRM names consistent as DSI-1 and DSI-2, add +aliases to the Pi5 DT. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -785,6 +785,8 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + gpio4 = &pinctrl_aon; + usb0 = &rp1_usb0; + usb1 = &rp1_usb1; ++ drm_dsi1 = &dsi0; ++ drm_dsi2 = &dsi1; + }; + + __overrides__ { diff --git a/target/linux/bcm27xx/patches-6.1/950-1015-vc4-drm-Remove-the-clear-of-SCALER_DISPBKGND_FILL.patch b/target/linux/bcm27xx/patches-6.1/950-1015-vc4-drm-Remove-the-clear-of-SCALER_DISPBKGND_FILL.patch new file mode 100644 index 0000000000..a4c8aeadd3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1015-vc4-drm-Remove-the-clear-of-SCALER_DISPBKGND_FILL.patch @@ -0,0 +1,64 @@ +From e6e0631fdeb0cd7d4c50e629b4b298e0b76e885b Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Wed, 4 Oct 2023 16:02:39 +0100 +Subject: [PATCH] vc4/drm: Remove the clear of SCALER_DISPBKGND_FILL + +Since "drm/vc4: hvs: Support BCM2712 HVS" booting Pi4 +with dual 4kp30 displays connected fails with: +vc4-drm gpu: [drm] *ERROR* [CRTC:107:pixelvalve-4] flip_done timed out + +It has been tracked down to the referenced commit adding a +path to clear the SCALER_DISPBKGND_FILL when not required. + +Dual 4kp30 works with a core clock of 297MHz when background fill +is enabled, but requires a higher value with it disabled. +320MHz still fails, while 330MHz seems okay. + +Lets always enable background fill for Pi0-4. + +Fixes: e84da235223d ("drm/vc4: hvs: Support BCM2712 HVS") + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 20 +++++++++----------- + 1 file changed, 9 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1349,27 +1349,25 @@ void vc4_hvs_atomic_flush(struct drm_crt + WARN_ON(!vc4_state->mm); + WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm->mm_node.size); + +- if (enable_bg_fill) { ++ if (vc4->gen >= VC4_GEN_6) { + /* This sets a black background color fill, as is the case + * with other DRM drivers. + */ +- if (vc4->gen >= VC4_GEN_6) ++ if (enable_bg_fill) + HVS_WRITE(SCALER6_DISPX_CTRL1(channel), + HVS_READ(SCALER6_DISPX_CTRL1(channel)) | + SCALER6_DISPX_CTRL1_BGENB); + else +- HVS_WRITE(SCALER_DISPBKGNDX(channel), +- HVS_READ(SCALER_DISPBKGNDX(channel)) | +- SCALER_DISPBKGND_FILL); +- } else { +- if (vc4->gen >= VC4_GEN_6) + HVS_WRITE(SCALER6_DISPX_CTRL1(channel), + HVS_READ(SCALER6_DISPX_CTRL1(channel)) & + ~SCALER6_DISPX_CTRL1_BGENB); +- else +- HVS_WRITE(SCALER_DISPBKGNDX(channel), +- HVS_READ(SCALER_DISPBKGNDX(channel)) & +- ~SCALER_DISPBKGND_FILL); ++ } else { ++ /* we can actually run with a lower core clock when background ++ * fill is enabled on VC4_GEN_5 so leave it enabled always. ++ */ ++ HVS_WRITE(SCALER_DISPBKGNDX(channel), ++ HVS_READ(SCALER_DISPBKGNDX(channel)) | ++ SCALER_DISPBKGND_FILL); + } + + /* Only update DISPLIST if the CRTC was already running and is not diff --git a/target/linux/bcm27xx/patches-6.1/950-1017-gpio-brcmstb-Use-dynamic-GPIO-base-numbers.patch b/target/linux/bcm27xx/patches-6.1/950-1017-gpio-brcmstb-Use-dynamic-GPIO-base-numbers.patch new file mode 100644 index 0000000000..9bf9e6d96d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1017-gpio-brcmstb-Use-dynamic-GPIO-base-numbers.patch @@ -0,0 +1,117 @@ +From 450d617786926b27c25e930241efbd2e37d66bb8 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 6 Oct 2023 16:30:35 +0100 +Subject: [PATCH] gpio: brcmstb: Use dynamic GPIO base numbers + +Forcing a gpiochip to have a fixed base number now leads to a warning +message. Remove the need to do so by calculating hwirq numbers based +on bank numbers. + +Signed-off-by: Phil Elwell +Fixes: 3b0213d56eb7 ("gpio: Add GPIO support for Broadcom STB SoCs") +--- + drivers/gpio/gpio-brcmstb.c | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +--- a/drivers/gpio/gpio-brcmstb.c ++++ b/drivers/gpio/gpio-brcmstb.c +@@ -50,7 +50,6 @@ struct brcmstb_gpio_priv { + struct irq_domain *irq_domain; + struct irq_chip irq_chip; + int parent_irq; +- int gpio_base; + int num_gpios; + int parent_wake_irq; + }; +@@ -92,7 +91,7 @@ brcmstb_gpio_get_active_irqs(struct brcm + static int brcmstb_gpio_hwirq_to_offset(irq_hw_number_t hwirq, + struct brcmstb_gpio_bank *bank) + { +- return hwirq - (bank->gc.base - bank->parent_priv->gpio_base); ++ return hwirq - bank->id * 32; + } + + static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank, +@@ -117,8 +116,9 @@ static void brcmstb_gpio_set_imask(struc + static int brcmstb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) + { + struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc); ++ struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc); + /* gc_offset is relative to this gpio_chip; want real offset */ +- int hwirq = offset + (gc->base - priv->gpio_base); ++ int hwirq = offset + bank->id * 32; + + if (hwirq >= priv->num_gpios) + return -ENXIO; +@@ -263,7 +263,7 @@ static void brcmstb_gpio_irq_bank_handle + { + struct brcmstb_gpio_priv *priv = bank->parent_priv; + struct irq_domain *domain = priv->irq_domain; +- int hwbase = bank->gc.base - priv->gpio_base; ++ int hwbase = bank->id * 32; + unsigned long status; + + while ((status = brcmstb_gpio_get_active_irqs(bank))) { +@@ -414,7 +414,7 @@ static int brcmstb_gpio_of_xlate(struct + if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) + return -EINVAL; + +- offset = gpiospec->args[0] - (gc->base - priv->gpio_base); ++ offset = gpiospec->args[0] - bank->id * 32; + if (offset >= gc->ngpio || offset < 0) + return -EINVAL; + +@@ -598,8 +598,8 @@ static int brcmstb_gpio_probe(struct pla + const __be32 *p; + u32 bank_width; + int num_banks = 0; ++ int num_gpios = 0; + int err; +- static int gpio_base; + unsigned long flags = 0; + bool need_wakeup_event = false; + +@@ -614,7 +614,6 @@ static int brcmstb_gpio_probe(struct pla + if (IS_ERR(reg_base)) + return PTR_ERR(reg_base); + +- priv->gpio_base = gpio_base; + priv->reg_base = reg_base; + priv->pdev = pdev; + +@@ -656,7 +655,7 @@ static int brcmstb_gpio_probe(struct pla + dev_dbg(dev, "Width 0 found: Empty bank @ %d\n", + num_banks); + num_banks++; +- gpio_base += MAX_GPIO_PER_BANK; ++ num_gpios += MAX_GPIO_PER_BANK; + continue; + } + +@@ -698,7 +697,7 @@ static int brcmstb_gpio_probe(struct pla + err = -ENOMEM; + goto fail; + } +- gc->base = gpio_base; ++ gc->base = -1; + gc->of_gpio_n_cells = 2; + gc->of_xlate = brcmstb_gpio_of_xlate; + /* not all ngpio lines are valid, will use bank width later */ +@@ -722,7 +721,7 @@ static int brcmstb_gpio_probe(struct pla + bank->id); + goto fail; + } +- gpio_base += gc->ngpio; ++ num_gpios += gc->ngpio; + + dev_dbg(dev, "bank=%d, base=%d, ngpio=%d, width=%d\n", bank->id, + gc->base, gc->ngpio, bank->width); +@@ -733,7 +732,7 @@ static int brcmstb_gpio_probe(struct pla + num_banks++; + } + +- priv->num_gpios = gpio_base - priv->gpio_base; ++ priv->num_gpios = num_gpios; + if (priv->parent_irq > 0) { + err = brcmstb_gpio_irq_setup(pdev, priv); + if (err) diff --git a/target/linux/bcm27xx/patches-6.1/950-1018-media-rpivid-Allow-use-of-iommu-in-rpivid.patch b/target/linux/bcm27xx/patches-6.1/950-1018-media-rpivid-Allow-use-of-iommu-in-rpivid.patch new file mode 100644 index 0000000000..a6d199a8c7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1018-media-rpivid-Allow-use-of-iommu-in-rpivid.patch @@ -0,0 +1,57 @@ +From 1770efc97981dbf756a18f5eb7615c4bafab665b Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Mon, 2 Oct 2023 15:12:52 +0100 +Subject: [PATCH] media/rpivid: Allow use of iommu in rpivid + +In order to use iommu on hevc set dma mask_and_coherent in probe. +I am assured dma_set_mask_and_coherent is benign on Pi4 (which has +no iommu) and it seems to be so in practice. +Also adds a bit of debug to make internal buffer allocation failure +easier to spot in future + +Signed-off-by: John Cox +--- + drivers/staging/media/rpivid/rpivid.c | 7 +++++++ + drivers/staging/media/rpivid/rpivid_h265.c | 12 ++++++++++-- + 2 files changed, 17 insertions(+), 2 deletions(-) + +--- a/drivers/staging/media/rpivid/rpivid.c ++++ b/drivers/staging/media/rpivid/rpivid.c +@@ -360,6 +360,13 @@ static int rpivid_probe(struct platform_ + snprintf(vfd->name, sizeof(vfd->name), "%s", rpivid_video_device.name); + video_set_drvdata(vfd, dev); + ++ ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(36)); ++ if (ret) { ++ v4l2_err(&dev->v4l2_dev, ++ "Failed dma_set_mask_and_coherent\n"); ++ goto err_v4l2; ++ } ++ + dev->m2m_dev = v4l2_m2m_init(&rpivid_m2m_ops); + if (IS_ERR(dev->m2m_dev)) { + v4l2_err(&dev->v4l2_dev, +--- a/drivers/staging/media/rpivid/rpivid_h265.c ++++ b/drivers/staging/media/rpivid/rpivid_h265.c +@@ -2495,11 +2495,19 @@ static int rpivid_h265_start(struct rpiv + for (i = 0; i != ARRAY_SIZE(ctx->pu_bufs); ++i) { + // Don't actually need a kernel mapping here + if (gptr_alloc(dev, ctx->pu_bufs + i, pu_alloc, +- DMA_ATTR_NO_KERNEL_MAPPING)) ++ DMA_ATTR_NO_KERNEL_MAPPING)) { ++ v4l2_err(&dev->v4l2_dev, ++ "Failed to alloc %#zx PU%d buffer\n", ++ pu_alloc, i); + goto fail; ++ } + if (gptr_alloc(dev, ctx->coeff_bufs + i, coeff_alloc, +- DMA_ATTR_NO_KERNEL_MAPPING)) ++ DMA_ATTR_NO_KERNEL_MAPPING)) { ++ v4l2_err(&dev->v4l2_dev, ++ "Failed to alloc %#zx Coeff%d buffer\n", ++ pu_alloc, i); + goto fail; ++ } + } + aux_q_init(ctx); + diff --git a/target/linux/bcm27xx/patches-6.1/950-1019-dts-bcm2712-Add-iommu-to-rpivid.patch b/target/linux/bcm27xx/patches-6.1/950-1019-dts-bcm2712-Add-iommu-to-rpivid.patch new file mode 100644 index 0000000000..9f7c8674fb --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1019-dts-bcm2712-Add-iommu-to-rpivid.patch @@ -0,0 +1,22 @@ +From 10ff8ba24c68f704ecf5a58878617dfe149a14c6 Mon Sep 17 00:00:00 2001 +From: John Cox +Date: Mon, 2 Oct 2023 15:15:13 +0100 +Subject: [PATCH] dts/bcm2712: Add iommu to rpivid + +Add iommu to rpivid so it can cope with scatter/gather + +Signed-off-by: John Cox +--- + arch/arm/boot/dts/bcm2712.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/bcm2712.dtsi ++++ b/arch/arm/boot/dts/bcm2712.dtsi +@@ -1158,6 +1158,7 @@ + clocks = <&firmware_clocks 11>; + clock-names = "hevc"; + status = "disabled"; ++ iommus = <&iommu2>; + }; + + sdio1: mmc@fff000 { diff --git a/target/linux/bcm27xx/patches-6.1/950-1020-drivers-media-rp1_cfe-Remove-PISP-specific-MBUS-form.patch b/target/linux/bcm27xx/patches-6.1/950-1020-drivers-media-rp1_cfe-Remove-PISP-specific-MBUS-form.patch new file mode 100644 index 0000000000..fabc96e422 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1020-drivers-media-rp1_cfe-Remove-PISP-specific-MBUS-form.patch @@ -0,0 +1,117 @@ +From b5c3cc7fd9fca73352310e61092fb445b56a362a Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Tue, 10 Oct 2023 12:41:15 +0100 +Subject: [PATCH] drivers: media: rp1_cfe: Remove PISP specific MBUS formats + +Remove the MEDIA_BUS_FMT_PISP* format codcs entirely. For the image +pad formats, use the 16-bit Bayer format mbus codes instead. For the +config and stats pad formats, use MEDIA_BUS_FMT_FIXED. + +Signed-off-by: Naushir Patuck +--- + .../media/platform/raspberrypi/rp1_cfe/cfe_fmts.h | 10 ++++++---- + .../media/platform/raspberrypi/rp1_cfe/pisp_fe.c | 11 ++++------- + include/uapi/linux/media-bus-format.h | 14 -------------- + 3 files changed, 10 insertions(+), 25 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h +@@ -215,25 +215,25 @@ static const struct cfe_fmt formats[] = + /* PiSP Compressed Mode 1 */ + { + .fourcc = V4L2_PIX_FMT_PISP_COMP1_RGGB, +- .code = MEDIA_BUS_FMT_PISP_COMP1_RGGB, ++ .code = MEDIA_BUS_FMT_SRGGB16_1X16, + .depth = 8, + .flags = CFE_FORMAT_FLAG_FE_OUT, + }, + { + .fourcc = V4L2_PIX_FMT_PISP_COMP1_BGGR, +- .code = MEDIA_BUS_FMT_PISP_COMP1_BGGR, ++ .code = MEDIA_BUS_FMT_SBGGR16_1X16, + .depth = 8, + .flags = CFE_FORMAT_FLAG_FE_OUT, + }, + { + .fourcc = V4L2_PIX_FMT_PISP_COMP1_GBRG, +- .code = MEDIA_BUS_FMT_PISP_COMP1_GBRG, ++ .code = MEDIA_BUS_FMT_SGBRG16_1X16, + .depth = 8, + .flags = CFE_FORMAT_FLAG_FE_OUT, + }, + { + .fourcc = V4L2_PIX_FMT_PISP_COMP1_GRBG, +- .code = MEDIA_BUS_FMT_PISP_COMP1_GRBG, ++ .code = MEDIA_BUS_FMT_SGRBG16_1X16, + .depth = 8, + .flags = CFE_FORMAT_FLAG_FE_OUT, + }, +@@ -283,10 +283,12 @@ static const struct cfe_fmt formats[] = + /* Frontend formats */ + { + .fourcc = V4L2_META_FMT_RPI_FE_CFG, ++ .code = MEDIA_BUS_FMT_FIXED, + .flags = CFE_FORMAT_FLAG_META_OUT, + }, + { + .fourcc = V4L2_META_FMT_RPI_FE_STATS, ++ .code = MEDIA_BUS_FMT_FIXED, + .flags = CFE_FORMAT_FLAG_META_CAP, + }, + }; +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -404,7 +404,7 @@ static int pisp_fe_init_cfg(struct v4l2_ + + fmt = v4l2_subdev_get_pad_format(sd, state, FE_CONFIG_PAD); + *fmt = cfe_default_meta_format; +- fmt->code = MEDIA_BUS_FMT_PISP_FE_CONFIG; ++ fmt->code = MEDIA_BUS_FMT_FIXED; + + fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT0_PAD); + *fmt = cfe_default_format; +@@ -416,7 +416,7 @@ static int pisp_fe_init_cfg(struct v4l2_ + + fmt = v4l2_subdev_get_pad_format(sd, state, FE_STATS_PAD); + *fmt = cfe_default_meta_format; +- fmt->code = MEDIA_BUS_FMT_PISP_FE_STATS; ++ fmt->code = MEDIA_BUS_FMT_FIXED; + + return 0; + } +@@ -443,12 +443,9 @@ static int pisp_fe_pad_set_fmt(struct v4 + + break; + +- case FE_CONFIG_PAD: +- format->format.code = MEDIA_BUS_FMT_PISP_FE_CONFIG; +- break; +- + case FE_STATS_PAD: +- format->format.code = MEDIA_BUS_FMT_PISP_FE_STATS; ++ case FE_CONFIG_PAD: ++ format->format.code = MEDIA_BUS_FMT_FIXED; + break; + } + +--- a/include/uapi/linux/media-bus-format.h ++++ b/include/uapi/linux/media-bus-format.h +@@ -175,18 +175,4 @@ + /* 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 */ diff --git a/target/linux/bcm27xx/patches-6.1/950-1022-vc04_services-bcm2835-codec-Correct-alignment-requir.patch b/target/linux/bcm27xx/patches-6.1/950-1022-vc04_services-bcm2835-codec-Correct-alignment-requir.patch new file mode 100644 index 0000000000..313ca37738 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1022-vc04_services-bcm2835-codec-Correct-alignment-requir.patch @@ -0,0 +1,53 @@ +From 9f4002165439d02a63760e68948246e3af764318 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 11 Oct 2023 15:05:38 +0100 +Subject: [PATCH] vc04_services: bcm2835-codec: Correct alignment requirements + for YUYV + +The firmware wants the YUYV format stride alignment to be to a multiple +of 32pixels / 64 bytes. The kernel driver was configuring it to a multiple +of 16 pixels / 32 bytes, which then failed when it tried starting to +stream. + +Correct the alignment requirements. + +Signed-off-by: Dave Stevenson +--- + .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c ++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c +@@ -206,28 +206,28 @@ static const struct bcm2835_codec_fmt su + }, { + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, +- .bytesperline_align = { 32, 32, 32, 32, 32 }, ++ .bytesperline_align = { 64, 64, 64, 64, 64 }, + .flags = 0, + .mmal_fmt = MMAL_ENCODING_YUYV, + .size_multiplier_x2 = 2, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .depth = 16, +- .bytesperline_align = { 32, 32, 32, 32, 32 }, ++ .bytesperline_align = { 64, 64, 64, 64, 64 }, + .flags = 0, + .mmal_fmt = MMAL_ENCODING_UYVY, + .size_multiplier_x2 = 2, + }, { + .fourcc = V4L2_PIX_FMT_YVYU, + .depth = 16, +- .bytesperline_align = { 32, 32, 32, 32, 32 }, ++ .bytesperline_align = { 64, 64, 64, 64, 64 }, + .flags = 0, + .mmal_fmt = MMAL_ENCODING_YVYU, + .size_multiplier_x2 = 2, + }, { + .fourcc = V4L2_PIX_FMT_VYUY, + .depth = 16, +- .bytesperline_align = { 32, 32, 32, 32, 32 }, ++ .bytesperline_align = { 64, 64, 64, 64, 64 }, + .flags = 0, + .mmal_fmt = MMAL_ENCODING_VYUY, + .size_multiplier_x2 = 2, diff --git a/target/linux/bcm27xx/patches-6.1/950-1025-input-touchscreen-edt-ft5x06-Suppress-bogus-data-on-.patch b/target/linux/bcm27xx/patches-6.1/950-1025-input-touchscreen-edt-ft5x06-Suppress-bogus-data-on-.patch new file mode 100644 index 0000000000..fe956c2ed4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1025-input-touchscreen-edt-ft5x06-Suppress-bogus-data-on-.patch @@ -0,0 +1,96 @@ +From dd802fc03b1c71b4297e87068077bfcf9810300a Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 11 Oct 2023 15:14:59 +0100 +Subject: [PATCH] input: touchscreen: edt-ft5x06: Suppress bogus data on + startup + +When polled without the use of IRQ, FT5x06 registers may return +undefined initial data, causing unwanted touches or event spamming. +A simple way to filter this out is to suppress touches until the +TD_STATUS register changes for the first time. + +Increase the delay before first polling to 300ms, to avoid +transient I2C read flakiness that seems to occur after reset. + +Signed-off-by: Nick Hollinghurst +--- + drivers/input/touchscreen/edt-ft5x06.c | 31 +++++++++++++++++++++++--- + 1 file changed, 28 insertions(+), 3 deletions(-) + +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -75,6 +75,8 @@ + #define EDT_DEFAULT_NUM_X 1024 + #define EDT_DEFAULT_NUM_Y 1024 + ++#define RESET_DELAY_MS 300 /* reset deassert to I2C */ ++#define FIRST_POLL_DELAY_MS 300 /* in addition to the above */ + #define POLL_INTERVAL_MS 17 /* 17ms = 60fps */ + + enum edt_pmode { +@@ -134,6 +136,7 @@ struct edt_ft5x06_ts_data { + + char name[EDT_NAME_LEN]; + char fw_version[EDT_NAME_LEN]; ++ int init_td_status; + + struct edt_reg_addr reg_addr; + enum edt_ver version; +@@ -268,12 +271,33 @@ static irqreturn_t edt_ft5x06_ts_isr(int + * points. + */ + num_points = min(rdbuf[2] & 0xf, tsdata->max_support_points); ++ ++ /* When polling FT5x06 without IRQ: initial register contents ++ * could be stale or undefined; discard all readings until ++ * TD_STATUS changes for the first time (or num_points is 0). ++ */ ++ if (tsdata->init_td_status) { ++ if (tsdata->init_td_status < 0) ++ tsdata->init_td_status = rdbuf[2]; ++ ++ if (num_points && rdbuf[2] == tsdata->init_td_status) ++ goto out; ++ ++ tsdata->init_td_status = 0; ++ } ++ + if (num_points) { + datalen = tplen * num_points + crclen; + cmd = offset; + error = edt_ft5x06_ts_readwrite(tsdata->client, + sizeof(cmd), &cmd, + datalen, &rdbuf[offset]); ++ if (error) { ++ dev_err_ratelimited(dev, ++ "Unable to fetch data, error: %d\n", ++ error); ++ goto out; ++ } + } + } + +@@ -1294,7 +1318,7 @@ static int edt_ft5x06_ts_probe(struct i2 + if (tsdata->reset_gpio) { + usleep_range(5000, 6000); + gpiod_set_value_cansleep(tsdata->reset_gpio, 0); +- msleep(300); ++ msleep(RESET_DELAY_MS); + } + + input = devm_input_allocate_device(&client->dev); +@@ -1384,11 +1408,12 @@ static int edt_ft5x06_ts_probe(struct i2 + return error; + } + } else { ++ tsdata->init_td_status = -1; /* filter bogus initial data */ + INIT_WORK(&tsdata->work_i2c_poll, + edt_ft5x06_ts_work_i2c_poll); + timer_setup(&tsdata->timer, edt_ft5x06_ts_irq_poll_timer, 0); +- tsdata->timer.expires = jiffies + +- msecs_to_jiffies(POLL_INTERVAL_MS); ++ tsdata->timer.expires = ++ jiffies + msecs_to_jiffies(FIRST_POLL_DELAY_MS); + add_timer(&tsdata->timer); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1029-overlays-mcp23017-allow-specification-of-the-i2c-bus.patch b/target/linux/bcm27xx/patches-6.1/950-1029-overlays-mcp23017-allow-specification-of-the-i2c-bus.patch new file mode 100644 index 0000000000..8cb35e1a79 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1029-overlays-mcp23017-allow-specification-of-the-i2c-bus.patch @@ -0,0 +1,97 @@ +From 27f0e0e195568c06f21ce380f0736bdd219baf3c Mon Sep 17 00:00:00 2001 +From: Janis Streib +Date: Sun, 15 Oct 2023 21:08:40 +0200 +Subject: [PATCH] overlays: mcp23017: allow specification of the i2c bus + +Analogous to i2c-rtc-overlay.dts + +See: https://github.com/raspberrypi/linux/pull/5650 +--- + arch/arm/boot/dts/overlays/README | 10 ++++++ + .../boot/dts/overlays/mcp23017-overlay.dts | 36 +++++++++++++++++-- + 2 files changed, 44 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -2810,6 +2810,16 @@ Params: gpiopin Gpio pin + + mcp23008 Configure an MCP23008 instead. + noints Disable the interrupt GPIO line. ++ i2c0 Choose the I2C0 bus on GPIOs 0&1 ++ i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ 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) + + + Name: mcp23s17 +--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts ++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts +@@ -7,7 +7,7 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2c1>; ++ target = <&i2cbus>; + __overlay__ { + status = "okay"; + }; +@@ -24,7 +24,7 @@ + }; + + fragment@2 { +- target = <&i2c1>; ++ target = <&i2cbus>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; +@@ -58,12 +58,44 @@ + }; + }; + ++ frag100: fragment@100 { ++ target = <&i2c1>; ++ i2cbus: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@101 { ++ target = <&i2c0if>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@102 { ++ target = <&i2c0mux>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { + gpiopin = <&mcp23017_pins>,"brcm,pins:0", + <&mcp23017_irq>,"interrupts:0"; + addr = <&mcp23017>,"reg:0", <&mcp23017_pins>,"reg:0"; + mcp23008 = <0>,"=3"; + noints = <0>,"!1!4"; ++ i2c0 = <&frag100>, "target:0=",<&i2c0>; ++ i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, ++ <0>,"+101+102"; ++ i2c3 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c3"; ++ i2c4 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c4"; ++ i2c5 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c5"; ++ i2c6 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c6"; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1030-dts-bcm2712-Set-default-I2C-baudrates-to-100kHz.patch b/target/linux/bcm27xx/patches-6.1/950-1030-dts-bcm2712-Set-default-I2C-baudrates-to-100kHz.patch new file mode 100644 index 0000000000..e9422f1daa --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1030-dts-bcm2712-Set-default-I2C-baudrates-to-100kHz.patch @@ -0,0 +1,46 @@ +From 0339c8c61ca6b54c529f699e7bafd65cda9f3733 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 16 Oct 2023 09:06:25 +0100 +Subject: [PATCH] dts: bcm2712: Set default I2C baudrates to 100kHz + +The RP1 I2C interfaces were being left with their default clock rates, +apparently 400kHz. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 ++ + arch/arm/boot/dts/bcm2712-rpi.dtsi | 2 ++ + 2 files changed, 4 insertions(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -250,11 +250,13 @@ i2c0mux: &rp1_gpio {}; + i2c_csi_dsi0: &i2c6 { // Note: This is for MIPI0 connector only + pinctrl-0 = <&rp1_i2c6_38_39>; + pinctrl-names = "default"; ++ clock-frequency = <100000>; + }; + + i2c_csi_dsi1: &i2c4 { // Note: This is for MIPI1 connector only + pinctrl-0 = <&rp1_i2c4_40_41>; + pinctrl-names = "default"; ++ clock-frequency = <100000>; + }; + + i2c_csi_dsi: &i2c_csi_dsi1 { }; // An alias for compatibility +--- a/arch/arm/boot/dts/bcm2712-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm2712-rpi.dtsi +@@ -204,11 +204,13 @@ uart4: &rp1_uart4 { }; + i2c_vc: &i2c0 { // This is pins 27,28 on the header (not MIPI) + pinctrl-0 = <&rp1_i2c0_0_1>; + pinctrl-names = "default"; ++ clock-frequency = <100000>; + }; + + i2c_arm: &i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&rp1_i2c1_2_3>; ++ clock-frequency = <100000>; + }; + + &i2c2 { diff --git a/target/linux/bcm27xx/patches-6.1/950-1031-vc_mem-Add-the-DMA-memcpy-support-from-bcm2708_fb.patch b/target/linux/bcm27xx/patches-6.1/950-1031-vc_mem-Add-the-DMA-memcpy-support-from-bcm2708_fb.patch new file mode 100644 index 0000000000..23d428789f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1031-vc_mem-Add-the-DMA-memcpy-support-from-bcm2708_fb.patch @@ -0,0 +1,345 @@ +From 2a47ccf97c6a91bc56f8cfb387d47f59cc347dd5 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Sat, 14 Oct 2023 14:57:49 +0100 +Subject: [PATCH] vc_mem: Add the DMA memcpy support from bcm2708_fb + +bcm2708_fb is disabled by the vc4-kms-v3d overlay, which means that the +DMA memcpy support it provides is not available to allow vclog to read +the VC logs from the top 16MB on Pi 2 and Pi 3. Add the code to the +vc_mem driver, which will still be enabled. + +It ought to be possible to do a proper DMA_MEM_TO_MEM copy via the +generic DMA customer API, but that can be a later step. + +Signed-off-by: Phil Elwell +--- + drivers/char/broadcom/vc_mem.c | 259 +++++++++++++++++++++++++++++++++ + 1 file changed, 259 insertions(+) + +--- a/drivers/char/broadcom/vc_mem.c ++++ b/drivers/char/broadcom/vc_mem.c +@@ -23,9 +23,21 @@ + #include + #include + #include ++#include ++#include ++#include + + #define DRIVER_NAME "vc-mem" + ++/* N.B. These use a different magic value for compatibility with bmc7208_fb */ ++#define VC_MEM_IOC_DMACOPY _IOW('z', 0x22, struct vc_mem_dmacopy) ++#define VC_MEM_IOC_DMACOPY32 _IOW('z', 0x22, struct vc_mem_dmacopy32) ++ ++/* address with no aliases */ ++#define INTALIAS_NORMAL(x) ((x) & ~0xc0000000) ++/* cache coherent but non-allocating in L1 and L2 */ ++#define INTALIAS_L1L2_NONALLOCATING(x) (((x) & ~0xc0000000) | 0x80000000) ++ + /* Device (/dev) related variables */ + static dev_t vc_mem_devnum; + static struct class *vc_mem_class; +@@ -36,6 +48,20 @@ static int vc_mem_inited; + static struct dentry *vc_mem_debugfs_entry; + #endif + ++struct vc_mem_dmacopy { ++ void *dst; ++ __u32 src; ++ __u32 length; ++}; ++ ++#ifdef CONFIG_COMPAT ++struct vc_mem_dmacopy32 { ++ compat_uptr_t dst; ++ __u32 src; ++ __u32 length; ++}; ++#endif ++ + /* + * Videocore memory addresses and size + * +@@ -62,6 +88,20 @@ static uint phys_addr; + static uint mem_size; + static uint mem_base; + ++struct vc_mem_dma { ++ struct device *dev; ++ int dma_chan; ++ int dma_irq; ++ void __iomem *dma_chan_base; ++ wait_queue_head_t dma_waitq; ++ void *cb_base; /* DMA control blocks */ ++ dma_addr_t cb_handle; ++}; ++ ++struct { u32 base, length; } gpu_mem; ++static struct mutex dma_mutex; ++static struct vc_mem_dma vc_mem_dma; ++ + static int + vc_mem_open(struct inode *inode, struct file *file) + { +@@ -99,6 +139,189 @@ vc_mem_get_current_size(void) + } + EXPORT_SYMBOL_GPL(vc_mem_get_current_size); + ++static int ++vc_mem_dma_init(void) ++{ ++ struct vc_mem_dma *vcdma = &vc_mem_dma; ++ struct platform_device *pdev; ++ struct device_node *fwnode; ++ struct rpi_firmware *fw; ++ struct device *dev; ++ u32 revision; ++ int rc; ++ ++ if (vcdma->dev) ++ return 0; ++ ++ fwnode = of_find_node_by_path("/system"); ++ rc = of_property_read_u32(fwnode, "linux,revision", &revision); ++ revision = (revision >> 12) & 0xf; ++ if (revision != 1 && revision != 2) { ++ /* Only BCM2709 and BCM2710 may have logs where the ARMs ++ * can't see them. ++ */ ++ return -ENXIO; ++ } ++ ++ fwnode = rpi_firmware_find_node(); ++ if (!fwnode) ++ return -ENXIO; ++ ++ pdev = of_find_device_by_node(fwnode); ++ dev = &pdev->dev; ++ ++ rc = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); ++ if (rc) ++ return rc; ++ ++ fw = rpi_firmware_get(fwnode); ++ if (!fw) ++ return -ENXIO; ++ rc = rpi_firmware_property(fw, RPI_FIRMWARE_GET_VC_MEMORY, ++ &gpu_mem, sizeof(gpu_mem)); ++ if (rc) ++ return rc; ++ ++ gpu_mem.base = INTALIAS_NORMAL(gpu_mem.base); ++ ++ if (!gpu_mem.base || !gpu_mem.length) { ++ dev_err(dev, "%s: unable to determine gpu memory (%x,%x)\n", ++ __func__, gpu_mem.base, gpu_mem.length); ++ return -EFAULT; ++ } ++ ++ vcdma->cb_base = dma_alloc_wc(dev, SZ_4K, &vcdma->cb_handle, GFP_KERNEL); ++ if (!vcdma->cb_base) { ++ dev_err(dev, "failed to allocate DMA CBs\n"); ++ return -ENOMEM; ++ } ++ ++ rc = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK, ++ &vcdma->dma_chan_base, ++ &vcdma->dma_irq); ++ if (rc < 0) { ++ dev_err(dev, "failed to allocate a DMA channel\n"); ++ goto free_cb; ++ } ++ ++ vcdma->dma_chan = rc; ++ ++ init_waitqueue_head(&vcdma->dma_waitq); ++ ++ vcdma->dev = dev; ++ ++ return 0; ++ ++free_cb: ++ dma_free_wc(dev, SZ_4K, vcdma->cb_base, vcdma->cb_handle); ++ ++ return rc; ++} ++ ++static void ++vc_mem_dma_uninit(void) ++{ ++ struct vc_mem_dma *vcdma = &vc_mem_dma; ++ ++ if (vcdma->dev) { ++ bcm_dma_chan_free(vcdma->dma_chan); ++ dma_free_wc(vcdma->dev, SZ_4K, vcdma->cb_base, vcdma->cb_handle); ++ vcdma->dev = NULL; ++ } ++} ++ ++static int dma_memcpy(struct vc_mem_dma *vcdma, dma_addr_t dst, dma_addr_t src, ++ int size) ++{ ++ struct bcm2708_dma_cb *cb = vcdma->cb_base; ++ int burst_size = (vcdma->dma_chan == 0) ? 8 : 2; ++ ++ cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH | ++ BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH | ++ BCM2708_DMA_D_INC; ++ cb->dst = dst; ++ cb->src = src; ++ cb->length = size; ++ cb->stride = 0; ++ cb->pad[0] = 0; ++ cb->pad[1] = 0; ++ cb->next = 0; ++ ++ bcm_dma_start(vcdma->dma_chan_base, vcdma->cb_handle); ++ bcm_dma_wait_idle(vcdma->dma_chan_base); ++ ++ return 0; ++} ++ ++static long vc_mem_copy(struct vc_mem_dmacopy *ioparam) ++{ ++ struct vc_mem_dma *vcdma = &vc_mem_dma; ++ size_t size = PAGE_SIZE; ++ const u32 dma_xfer_chunk = 256; ++ u32 *buf = NULL; ++ dma_addr_t bus_addr; ++ long rc = 0; ++ size_t offset; ++ ++ /* restrict this to root user */ ++ if (!uid_eq(current_euid(), GLOBAL_ROOT_UID)) ++ return -EFAULT; ++ ++ if (mutex_lock_interruptible(&dma_mutex)) ++ return -EINTR; ++ ++ rc = vc_mem_dma_init(); ++ if (rc) ++ goto out; ++ ++ vcdma = &vc_mem_dma; ++ ++ if (INTALIAS_NORMAL(ioparam->src) < gpu_mem.base || ++ INTALIAS_NORMAL(ioparam->src) >= gpu_mem.base + gpu_mem.length) { ++ pr_err("%s: invalid memory access %x (%x-%x)", __func__, ++ INTALIAS_NORMAL(ioparam->src), gpu_mem.base, ++ gpu_mem.base + gpu_mem.length); ++ rc = -EFAULT; ++ goto out; ++ } ++ ++ buf = dma_alloc_coherent(vcdma->dev, PAGE_ALIGN(size), &bus_addr, ++ GFP_ATOMIC); ++ if (!buf) { ++ rc = -ENOMEM; ++ goto out; ++ } ++ ++ for (offset = 0; offset < ioparam->length; offset += size) { ++ size_t remaining = ioparam->length - offset; ++ size_t s = min(size, remaining); ++ u8 *p = (u8 *)((uintptr_t)ioparam->src + offset); ++ u8 *q = (u8 *)ioparam->dst + offset; ++ ++ rc = dma_memcpy(vcdma, bus_addr, ++ INTALIAS_L1L2_NONALLOCATING((u32)(uintptr_t)p), ++ (s + dma_xfer_chunk - 1) & ~(dma_xfer_chunk - 1)); ++ if (rc) { ++ dev_err(vcdma->dev, "dma_memcpy failed\n"); ++ break; ++ } ++ if (copy_to_user(q, buf, s) != 0) { ++ pr_err("%s: copy_to_user failed\n", __func__); ++ rc = -EFAULT; ++ break; ++ } ++ } ++ ++out: ++ if (buf) ++ dma_free_coherent(vcdma->dev, PAGE_ALIGN(size), buf, ++ bus_addr); ++ ++ mutex_unlock(&dma_mutex); ++ ++ return rc; ++} ++ + static long + vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { +@@ -163,6 +386,21 @@ vc_mem_ioctl(struct file *file, unsigned + } + break; + } ++ case VC_MEM_IOC_DMACOPY: ++ { ++ struct vc_mem_dmacopy ioparam; ++ /* Get the parameter data. ++ */ ++ if (copy_from_user ++ (&ioparam, (void *)arg, sizeof(ioparam))) { ++ pr_err("%s: copy_from_user failed\n", __func__); ++ rc = -EFAULT; ++ break; ++ } ++ ++ rc = vc_mem_copy(&ioparam); ++ break; ++ } + default: + { + return -ENOTTY; +@@ -193,6 +431,24 @@ vc_mem_compat_ioctl(struct file *file, u + + break; + ++ case VC_MEM_IOC_DMACOPY32: ++ { ++ struct vc_mem_dmacopy32 param32; ++ struct vc_mem_dmacopy param; ++ /* Get the parameter data. ++ */ ++ if (copy_from_user(¶m32, (void *)arg, sizeof(param32))) { ++ pr_err("%s: copy_from_user failed\n", __func__); ++ rc = -EFAULT; ++ break; ++ } ++ param.dst = compat_ptr(param32.dst); ++ param.src = param32.src; ++ param.length = param32.length; ++ rc = vc_mem_copy(¶m); ++ break; ++ } ++ + default: + rc = vc_mem_ioctl(file, cmd, arg); + break; +@@ -330,6 +586,7 @@ vc_mem_init(void) + vc_mem_debugfs_init(dev); + #endif + ++ mutex_init(&dma_mutex); + vc_mem_inited = 1; + return 0; + +@@ -352,6 +609,7 @@ vc_mem_exit(void) + { + pr_debug("%s: called\n", __func__); + ++ vc_mem_dma_uninit(); + if (vc_mem_inited) { + #ifdef CONFIG_DEBUG_FS + vc_mem_debugfs_deinit(); +@@ -360,6 +618,7 @@ vc_mem_exit(void) + class_destroy(vc_mem_class); + cdev_del(&vc_mem_cdev); + unregister_chrdev_region(vc_mem_devnum, 1); ++ vc_mem_inited = 0; + } + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1032-drm-vc4-Correct-address-offset-for-planes-with-src_-.patch b/target/linux/bcm27xx/patches-6.1/950-1032-drm-vc4-Correct-address-offset-for-planes-with-src_-.patch new file mode 100644 index 0000000000..32112f949b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1032-drm-vc4-Correct-address-offset-for-planes-with-src_-.patch @@ -0,0 +1,48 @@ +From 6ab30a5dd3fb2ccbd918f147e91eb9bfe9849970 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 16 Oct 2023 12:13:38 +0100 +Subject: [PATCH] drm/vc4: Correct address offset for planes with src_[xy] + offsets + +11cf37e741b4 switched to using drm_fb_dma_get_gem_addr instead of +drm_fb_dma_get_gem_obj and adding fb->offset[]. + +However the tiled formats need to compute the offset in a more +involved manner than drm_fb_dma_get_gem_addr applies, and we +were ending up with the offset for src_[xy] being applied twice. + +Switch back to using drm_fb_dma_get_gem_obj and fully computing +the offsets ourselves. + +Fixes: 11cf37e741b4 ("drm/vc4: Move the buffer offset out of the vc4_plane_state") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -1447,9 +1447,9 @@ static int vc4_plane_mode_set(struct drm + vc4_state->ptr0_offset[0] = vc4_state->dlist_count; + + for (i = 0; i < num_planes; i++) { +- dma_addr_t paddr = drm_fb_dma_get_gem_addr(fb, state, i); ++ struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, i); + +- vc4_dlist_write(vc4_state, paddr + offsets[i]); ++ vc4_dlist_write(vc4_state, bo->dma_addr + fb->offsets[i] + offsets[i]); + } + + /* Pointer Context Word 0/1/2: Written by the HVS */ +@@ -1842,9 +1842,8 @@ static int vc6_plane_mode_set(struct drm + * TODO: This only covers Raster Scan Order planes + */ + for (i = 0; i < num_planes; i++) { +- dma_addr_t paddr = drm_fb_dma_get_gem_addr(fb, state, i); +- +- paddr += offsets[i]; ++ struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, i); ++ dma_addr_t paddr = bo->dma_addr + fb->offsets[i] + offsets[i]; + + /* Pointer Word 0 */ + vc4_state->ptr0_offset[i] = vc4_state->dlist_count; diff --git a/target/linux/bcm27xx/patches-6.1/950-1033-drivers-media-rp1_cfe-Fix-link-validate-test-for-pix.patch b/target/linux/bcm27xx/patches-6.1/950-1033-drivers-media-rp1_cfe-Fix-link-validate-test-for-pix.patch new file mode 100644 index 0000000000..3e1d504da0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1033-drivers-media-rp1_cfe-Fix-link-validate-test-for-pix.patch @@ -0,0 +1,69 @@ +From c14550658832026e82111f2a89b3f7bf567afc1c Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Tue, 17 Oct 2023 09:35:44 +0100 +Subject: [PATCH] drivers: media: rp1_cfe: Fix link validate test for pixel + format + +Now that we have removed unique PISP media bus codes, the cfe format +table has multiple entries with the same media bus code for 16-bit +formats. The test in cfe_video_link_validate() did not account for this. +Fix it by testing the media bus code and the V4L2 pixelformat 4cc +together. + +As a drive-by, ensure we have a valid CSI2 datatype id when programming +the hardware block. + +Signed-off-by: Naushir Patuck +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -786,6 +786,9 @@ static void cfe_start_channel(struct cfe + width = source_fmt->width; + height = source_fmt->height; + ++ /* Must have a valid CSI2 datatype. */ ++ WARN_ON(!fmt->csi_dt); ++ + /* + * Start the associated CSI2 Channel as well. + * +@@ -809,6 +812,9 @@ static void cfe_start_channel(struct cfe + node_desc[node->id].link_pad - CSI2_NUM_CHANNELS); + fmt = find_format_by_code(source_fmt->code); + ++ /* Must have a valid CSI2 datatype. */ ++ WARN_ON(!fmt->csi_dt); ++ + if (is_image_output_node(node)) { + width = source_fmt->width; + height = source_fmt->height; +@@ -1504,7 +1510,8 @@ static int cfe_video_link_validate(struc + + if (is_image_output_node(node)) { + struct v4l2_pix_format *pix_fmt = &node->fmt.fmt.pix; +- const struct cfe_fmt *fmt; ++ const struct cfe_fmt *fmt = NULL; ++ unsigned int i; + + if (source_fmt->width != pix_fmt->width || + source_fmt->height != pix_fmt->height) { +@@ -1516,8 +1523,14 @@ static int cfe_video_link_validate(struc + goto out; + } + +- fmt = find_format_by_code(source_fmt->code); +- if (!fmt || fmt->fourcc != pix_fmt->pixelformat) { ++ for (i = 0; i < ARRAY_SIZE(formats); i++) { ++ if (formats[i].code == source_fmt->code && ++ formats[i].fourcc == pix_fmt->pixelformat) { ++ fmt = &formats[i]; ++ break; ++ } ++ } ++ if (!fmt) { + cfe_err("Format mismatch!\n"); + ret = -EINVAL; + goto out; diff --git a/target/linux/bcm27xx/patches-6.1/950-1034-dts-bcm2712-Use-the-new-model-name.patch b/target/linux/bcm27xx/patches-6.1/950-1034-dts-bcm2712-Use-the-new-model-name.patch new file mode 100644 index 0000000000..f30456835a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1034-dts-bcm2712-Use-the-new-model-name.patch @@ -0,0 +1,23 @@ +From b6bfece0d9ddf21e1526fead81340ef02f98f6ad Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 17 Oct 2023 17:28:11 +0100 +Subject: [PATCH] dts: bcm2712: Use the new model name + +"Model B" is no more - "Raspberry Pi 5" is the official name. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -52,7 +52,7 @@ + + / { + compatible = "raspberrypi,5-model-b", "brcm,bcm2712"; +- model = "Raspberry Pi 5 Model B"; ++ model = "Raspberry Pi 5"; + + /* Will be filled by the bootloader */ + memory@0 { diff --git a/target/linux/bcm27xx/patches-6.1/950-1035-fbdev-Allow-client-to-request-a-particular-dev-fbN-n.patch b/target/linux/bcm27xx/patches-6.1/950-1035-fbdev-Allow-client-to-request-a-particular-dev-fbN-n.patch new file mode 100644 index 0000000000..df87a1b757 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1035-fbdev-Allow-client-to-request-a-particular-dev-fbN-n.patch @@ -0,0 +1,93 @@ +From 0c7fb448e0e0e47c2b3be64e438208682c6a5e61 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 9 Oct 2023 16:32:45 +0100 +Subject: [PATCH] fbdev: Allow client to request a particular /dev/fbN node + +Add a flag custom_fb_num to denote that the client has +requested a specific fbdev node number via node. + +Signed-off-by: Dave Stevenson +--- + drivers/video/fbdev/core/fbmem.c | 24 +++++++++++++++++------- + include/linux/fb.h | 2 ++ + 2 files changed, 19 insertions(+), 7 deletions(-) + +--- a/drivers/video/fbdev/core/fbmem.c ++++ b/drivers/video/fbdev/core/fbmem.c +@@ -52,6 +52,7 @@ static DEFINE_MUTEX(registration_lock); + + struct fb_info *registered_fb[FB_MAX] __read_mostly; + int num_registered_fb __read_mostly; ++int min_dynamic_fb __read_mostly; + #define for_each_registered_fb(i) \ + for (i = 0; i < FB_MAX; i++) \ + if (!registered_fb[i]) {} else +@@ -1579,19 +1580,22 @@ static int do_register_framebuffer(struc + return -ENXIO; + + num_registered_fb++; +- for (i = 0 ; i < FB_MAX; i++) +- if (!registered_fb[i]) +- break; +- fb_info->node = i; ++ if (!fb_info->custom_fb_num || fb_info->node >= FB_MAX || registered_fb[fb_info->node]) { ++ for (i = min_dynamic_fb ; i < FB_MAX; i++) ++ if (!registered_fb[i]) ++ break; ++ fb_info->node = i; ++ } + refcount_set(&fb_info->count, 1); + mutex_init(&fb_info->lock); + mutex_init(&fb_info->mm_lock); + + fb_info->dev = device_create(fb_class, fb_info->device, +- MKDEV(FB_MAJOR, i), NULL, "fb%d", i); ++ MKDEV(FB_MAJOR, fb_info->node), NULL, "fb%d", fb_info->node); + if (IS_ERR(fb_info->dev)) { + /* Not fatal */ +- printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev)); ++ printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", ++ fb_info->node, PTR_ERR(fb_info->dev)); + fb_info->dev = NULL; + } else + fb_init_device(fb_info); +@@ -1624,7 +1628,7 @@ static int do_register_framebuffer(struc + + fb_var_to_videomode(&mode, &fb_info->var); + fb_add_videomode(&mode, &fb_info->modelist); +- registered_fb[i] = fb_info; ++ registered_fb[fb_info->node] = fb_info; + + #ifdef CONFIG_GUMSTIX_AM200EPD + { +@@ -1719,6 +1723,12 @@ static int fb_aperture_acquire_for_platf + return ret; + } + ++void fb_set_lowest_dynamic_fb(int min_fb_dev) ++{ ++ min_dynamic_fb = min_fb_dev; ++} ++EXPORT_SYMBOL(fb_set_lowest_dynamic_fb); ++ + /** + * register_framebuffer - registers a frame buffer device + * @fb_info: frame buffer info structure +--- a/include/linux/fb.h ++++ b/include/linux/fb.h +@@ -512,6 +512,7 @@ struct fb_info { + } *apertures; + + bool skip_vt_switch; /* no VT switch on suspend/resume required */ ++ bool custom_fb_num; /* Use value in node as the preferred node number */ + }; + + static inline struct apertures_struct *alloc_apertures(unsigned int max_num) { +@@ -614,6 +615,7 @@ extern ssize_t fb_sys_write(struct fb_in + size_t count, loff_t *ppos); + + /* drivers/video/fbmem.c */ ++extern void fb_set_lowest_dynamic_fb(int min_fb_dev); + extern int register_framebuffer(struct fb_info *fb_info); + extern void unregister_framebuffer(struct fb_info *fb_info); + extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); diff --git a/target/linux/bcm27xx/patches-6.1/950-1036-drm-fb-helper-Look-up-preferred-fbdev-node-number-fr.patch b/target/linux/bcm27xx/patches-6.1/950-1036-drm-fb-helper-Look-up-preferred-fbdev-node-number-fr.patch new file mode 100644 index 0000000000..3e360be77b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1036-drm-fb-helper-Look-up-preferred-fbdev-node-number-fr.patch @@ -0,0 +1,41 @@ +From 1216ea56c2e30aee4975b4dcce79ebd199afaf8f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 9 Oct 2023 16:34:36 +0100 +Subject: [PATCH] drm/fb-helper: Look up preferred fbdev node number from DT + +For situations where there are multiple DRM cards in a system, +add a query of DT for "drm_fb" designations for cards to set +their preferred /dev/fbN designation. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_fb_helper.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/drm_fb_helper.c ++++ b/drivers/gpu/drm/drm_fb_helper.c +@@ -1932,7 +1932,7 @@ __drm_fb_helper_initial_config_and_unloc + struct drm_device *dev = fb_helper->dev; + struct fb_info *info; + unsigned int width, height; +- int ret; ++ int ret, id; + + width = dev->mode_config.max_width; + height = dev->mode_config.max_height; +@@ -1967,6 +1967,15 @@ __drm_fb_helper_initial_config_and_unloc + * register the fbdev emulation instance in kernel_fb_helper_list. */ + mutex_unlock(&fb_helper->lock); + ++ id = of_alias_get_highest_id("drm_fb"); ++ if (id >= 0) ++ fb_set_lowest_dynamic_fb(id + 1); ++ ++ id = of_alias_get_id(dev->dev->of_node, "drm_fb"); ++ if (id >= 0) { ++ info->node = id; ++ info->custom_fb_num = true; ++ } + ret = register_framebuffer(info); + if (ret < 0) + return ret; diff --git a/target/linux/bcm27xx/patches-6.1/950-1037-dt-Add-overrides-for-drm-framebuffer-allocations-on-.patch b/target/linux/bcm27xx/patches-6.1/950-1037-dt-Add-overrides-for-drm-framebuffer-allocations-on-.patch new file mode 100644 index 0000000000..924c1b9f19 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1037-dt-Add-overrides-for-drm-framebuffer-allocations-on-.patch @@ -0,0 +1,72 @@ +From 61b138adaeaddefe749f421a3b69c67d4a49a8e3 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 11 Oct 2023 11:03:51 +0100 +Subject: [PATCH] dt: Add overrides for drm framebuffer allocations on Pi5 + +Adds dtparam overrides to the base Pi5 DT such that vc4, +DSI0, DSI1, or DPI can be requested to be /dev/fb[012]. +No override is specified by default, so the order will be +based on probe order (aka semi-random). Any device that +doesn't have an override specified will be placed above +all specified overrides. Having an fb1 or fb2 override but +no fb0 one will result in no console via fbcon. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 12 ++++++++++++ + arch/arm/boot/dts/overlays/README | 24 ++++++++++++++++++++++++ + 2 files changed, 36 insertions(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -824,5 +824,17 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + act_led_trigger = <&act_led>, "linux,default-trigger"; + pwr_led_activelow = <&pwr_led>, "gpios:8"; + pwr_led_trigger = <&pwr_led>, "linux,default-trigger"; ++ drm_fb0_rp1_dsi0 = <&aliases>, "drm_fb0=",&dsi0; ++ drm_fb0_rp1_dsi1 = <&aliases>, "drm_fb0=",&dsi1; ++ drm_fb0_rp1_dpi = <&aliases>, "drm_fb0=",&dpi; ++ drm_fb0_vc4 = <&aliases>, "drm_fb0=",&vc4; ++ drm_fb1_rp1_dsi0 = <&aliases>, "drm_fb1=",&dsi0; ++ drm_fb1_rp1_dsi1 = <&aliases>, "drm_fb1=",&dsi1; ++ drm_fb1_rp1_dpi = <&aliases>, "drm_fb1=",&dpi; ++ drm_fb1_vc4 = <&aliases>, "drm_fb1=",&vc4; ++ drm_fb2_rp1_dsi0 = <&aliases>, "drm_fb2=",&dsi0; ++ drm_fb2_rp1_dsi1 = <&aliases>, "drm_fb2=",&dsi1; ++ drm_fb2_rp1_dpi = <&aliases>, "drm_fb2=",&dpi; ++ drm_fb2_vc4 = <&aliases>, "drm_fb2=",&vc4; + }; + }; +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -173,6 +173,30 @@ Params: + cooling_fan Enables the Pi 5 cooling fan (enabled + automatically by the firmware) + ++ drm_fb0_rp1_dpi Assign /dev/fb0 to the RP1 DPI output ++ ++ drm_fb0_rp1_dsi0 Assign /dev/fb0 to the RP1 DSI0 output ++ ++ drm_fb0_rp1_dsi1 Assign /dev/fb0 to the RP1 DSI1 output ++ ++ drm_fb0_vc4 Assign /dev/fb0 to the vc4 outputs ++ ++ drm_fb1_rp1_dpi Assign /dev/fb1 to the RP1 DPI output ++ ++ drm_fb1_rp1_dsi0 Assign /dev/fb1 to the RP1 DSI0 output ++ ++ drm_fb1_rp1_dsi1 Assign /dev/fb1 to the RP1 DSI1 output ++ ++ drm_fb1_vc4 Assign /dev/fb1 to the vc4 outputs ++ ++ drm_fb2_rp1_dpi Assign /dev/fb2 to the RP1 DPI output ++ ++ drm_fb2_rp1_dsi0 Assign /dev/fb2 to the RP1 DSI0 output ++ ++ drm_fb2_rp1_dsi1 Assign /dev/fb2 to the RP1 DSI1 output ++ ++ drm_fb2_vc4 Assign /dev/fb2 to the vc4 outputs ++ + eee Enable Energy Efficient Ethernet support for + compatible devices (default "on"). See also + "tx_lpi_timer". Pi3B+ only. diff --git a/target/linux/bcm27xx/patches-6.1/950-1039-drm-connector-Change-DRM-card-alias-from-underscore-.patch b/target/linux/bcm27xx/patches-6.1/950-1039-drm-connector-Change-DRM-card-alias-from-underscore-.patch new file mode 100644 index 0000000000..57782d51c3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1039-drm-connector-Change-DRM-card-alias-from-underscore-.patch @@ -0,0 +1,26 @@ +From f429fc1a072d4bb35e622a1012a5a52914eba4e3 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 19 Oct 2023 10:34:58 +0100 +Subject: [PATCH] drm/connector: Change DRM card alias from underscore to + hyphen + +Apparently aliases are only allowed lower case and hyphens, +so swap the use of underscore to hyphen. + +Fixes: 3aa1f2477545 ("drm: Look for an alias for the displays to use as the DRM device name") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_connector.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/drm_connector.c ++++ b/drivers/gpu/drm/drm_connector.c +@@ -112,7 +112,7 @@ static struct drm_conn_prop_enum_list dr + }; + + #define MAX_DT_NODE_NAME_LEN 20 +-#define DT_DRM_NODE_PREFIX "drm_" ++#define DT_DRM_NODE_PREFIX "drm-" + + static void drm_connector_get_of_name(int type, char *node_name, int length) + { diff --git a/target/linux/bcm27xx/patches-6.1/950-1040-dt-Alter-alias-names-from-_-to-for-drm_dsiN.patch b/target/linux/bcm27xx/patches-6.1/950-1040-dt-Alter-alias-names-from-_-to-for-drm_dsiN.patch new file mode 100644 index 0000000000..0536924d05 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1040-dt-Alter-alias-names-from-_-to-for-drm_dsiN.patch @@ -0,0 +1,24 @@ +From e33170e21494279801e9f17eeb910ec45ebd740c Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 19 Oct 2023 10:28:43 +0100 +Subject: [PATCH] dt: Alter alias names from _ to - for drm_dsiN + +Fixes: 7ec42740a45b ("dt: Add DSI1 and DSI2 aliases to 2712") +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -787,8 +787,8 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + gpio4 = &pinctrl_aon; + usb0 = &rp1_usb0; + usb1 = &rp1_usb1; +- drm_dsi1 = &dsi0; +- drm_dsi2 = &dsi1; ++ drm-dsi1 = &dsi0; ++ drm-dsi2 = &dsi1; + }; + + __overrides__ { diff --git a/target/linux/bcm27xx/patches-6.1/950-1041-drm-fb_helper-Change-query-for-FB-designation-from-d.patch b/target/linux/bcm27xx/patches-6.1/950-1041-drm-fb_helper-Change-query-for-FB-designation-from-d.patch new file mode 100644 index 0000000000..78e5b89be4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1041-drm-fb_helper-Change-query-for-FB-designation-from-d.patch @@ -0,0 +1,28 @@ +From 0e9e925112fabdbd448e17947796317a6dbca96e Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 19 Oct 2023 10:32:04 +0100 +Subject: [PATCH] drm/fb_helper: Change query for FB designation from drm_fb to + drm-fb + +Fixes: 1216ea56c2e3 ("drm/fb-helper: Look up preferred fbdev node number from DT") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/drm_fb_helper.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/drm_fb_helper.c ++++ b/drivers/gpu/drm/drm_fb_helper.c +@@ -1967,11 +1967,11 @@ __drm_fb_helper_initial_config_and_unloc + * register the fbdev emulation instance in kernel_fb_helper_list. */ + mutex_unlock(&fb_helper->lock); + +- id = of_alias_get_highest_id("drm_fb"); ++ id = of_alias_get_highest_id("drm-fb"); + if (id >= 0) + fb_set_lowest_dynamic_fb(id + 1); + +- id = of_alias_get_id(dev->dev->of_node, "drm_fb"); ++ id = of_alias_get_id(dev->dev->of_node, "drm-fb"); + if (id >= 0) { + info->node = id; + info->custom_fb_num = true; diff --git a/target/linux/bcm27xx/patches-6.1/950-1042-dt-Alter-alias-names-from-_-to-for-drm_fbN_-override.patch b/target/linux/bcm27xx/patches-6.1/950-1042-dt-Alter-alias-names-from-_-to-for-drm_fbN_-override.patch new file mode 100644 index 0000000000..42865dc7ff --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1042-dt-Alter-alias-names-from-_-to-for-drm_fbN_-override.patch @@ -0,0 +1,43 @@ +From 87be94059193d0bc64d52a9535df4fb1891c72fe Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 19 Oct 2023 10:29:20 +0100 +Subject: [PATCH] dt: Alter alias names from _ to - for drm_fbN_* overrides + +Fixes: 61b138adaead ("dt: Add overrides for drm framebuffer allocations on Pi5") +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -824,17 +824,17 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + act_led_trigger = <&act_led>, "linux,default-trigger"; + pwr_led_activelow = <&pwr_led>, "gpios:8"; + pwr_led_trigger = <&pwr_led>, "linux,default-trigger"; +- drm_fb0_rp1_dsi0 = <&aliases>, "drm_fb0=",&dsi0; +- drm_fb0_rp1_dsi1 = <&aliases>, "drm_fb0=",&dsi1; +- drm_fb0_rp1_dpi = <&aliases>, "drm_fb0=",&dpi; +- drm_fb0_vc4 = <&aliases>, "drm_fb0=",&vc4; +- drm_fb1_rp1_dsi0 = <&aliases>, "drm_fb1=",&dsi0; +- drm_fb1_rp1_dsi1 = <&aliases>, "drm_fb1=",&dsi1; +- drm_fb1_rp1_dpi = <&aliases>, "drm_fb1=",&dpi; +- drm_fb1_vc4 = <&aliases>, "drm_fb1=",&vc4; +- drm_fb2_rp1_dsi0 = <&aliases>, "drm_fb2=",&dsi0; +- drm_fb2_rp1_dsi1 = <&aliases>, "drm_fb2=",&dsi1; +- drm_fb2_rp1_dpi = <&aliases>, "drm_fb2=",&dpi; +- drm_fb2_vc4 = <&aliases>, "drm_fb2=",&vc4; ++ drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0; ++ drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1; ++ drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi; ++ drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4; ++ drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0; ++ drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1; ++ drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi; ++ drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4; ++ drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0; ++ drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1; ++ drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi; ++ drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1044-Typo-in-overlays-README.patch b/target/linux/bcm27xx/patches-6.1/950-1044-Typo-in-overlays-README.patch new file mode 100644 index 0000000000..19720e8645 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1044-Typo-in-overlays-README.patch @@ -0,0 +1,21 @@ +From cb8a4adb586c5e926e415ac0dae3ffb4af30b0a9 Mon Sep 17 00:00:00 2001 +From: Andrew Scheller +Date: Thu, 19 Oct 2023 14:13:36 +0100 +Subject: [PATCH] Typo in overlays README + +touchscreen-size-y for rpi-ft5406 defaults to 480, not 600 +--- + arch/arm/boot/dts/overlays/README | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -3738,7 +3738,7 @@ Name: rpi-ft5406 + Info: Official Raspberry Pi display touchscreen + Load: dtoverlay=rpi-ft5406,= + Params: touchscreen-size-x Touchscreen X resolution (default 800) +- touchscreen-size-y Touchscreen Y resolution (default 600); ++ touchscreen-size-y Touchscreen Y resolution (default 480); + touchscreen-inverted-x Invert touchscreen X coordinates (default 0); + touchscreen-inverted-y Invert touchscreen Y coordinates (default 0); + touchscreen-swapped-x-y Swap X and Y cordinates (default 0); diff --git a/target/linux/bcm27xx/patches-6.1/950-1045-dts-bcm2712-Add-the-krnbt-parameter.patch b/target/linux/bcm27xx/patches-6.1/950-1045-dts-bcm2712-Add-the-krnbt-parameter.patch new file mode 100644 index 0000000000..95940dd830 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1045-dts-bcm2712-Add-the-krnbt-parameter.patch @@ -0,0 +1,23 @@ +From 4cb97982f88d8fb623ace5a9511198e442e993ba Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 20 Oct 2023 17:15:25 +0100 +Subject: [PATCH] dts: bcm2712: Add the krnbt parameter + +Add a Pi 5 implementation of the krnbt parameter, for symmetry and +for tinkering purposes. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -809,6 +809,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + i2c_baudrate = <&i2c_arm>, "clock-frequency:0"; + i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0"; + i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0"; ++ krnbt = <&bluetooth>, "status"; + nvme = <&pciex1>, "status"; + pciex1 = <&pciex1>, "status"; + pciex1_gen = <&pciex1> , "max-link-speed:0"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1047-drm-vc4_fkms-Fix-up-interrupt-handler-for-both-2835-.patch b/target/linux/bcm27xx/patches-6.1/950-1047-drm-vc4_fkms-Fix-up-interrupt-handler-for-both-2835-.patch new file mode 100644 index 0000000000..99b8426e1c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1047-drm-vc4_fkms-Fix-up-interrupt-handler-for-both-2835-.patch @@ -0,0 +1,109 @@ +From 4137b49989ce710305e476d0bd1086d7d906ff50 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 20 Oct 2023 17:09:54 +0100 +Subject: [PATCH] drm/vc4_fkms: Fix up interrupt handler for both 2835/2711 and + 2712 + +2712 has switched from using the SMI peripheral to another interrupt +source for the vsync interrupt, so handle both sources cleanly. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_firmware_kms.c | 48 ++++++++++++++++++++------ + 1 file changed, 38 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c +@@ -47,9 +47,15 @@ struct get_display_cfg { + u32 max_pixel_clock[2]; //Max pixel clock for each display + }; + ++enum vc4_fkms_revision { ++ BCM2835_6_7, ++ BCM2711, ++ BCM2712, ++}; ++ + struct vc4_fkms { + struct get_display_cfg cfg; +- bool bcm2711; ++ enum vc4_fkms_revision revision; + }; + + #define PLANES_PER_CRTC 8 +@@ -1149,7 +1155,7 @@ vc4_crtc_mode_valid(struct drm_crtc *crt + /* Pi4 can't generate odd horizontal timings on HDMI, so reject modes + * that would set them. + */ +- if (fkms->bcm2711 && ++ if (fkms->revision >= BCM2711 && + (vc4_crtc->display_number == 2 || vc4_crtc->display_number == 7) && + !(mode->flags & DRM_MODE_FLAG_DBLCLK) && + ((mode->hdisplay | /* active */ +@@ -1267,6 +1273,20 @@ static irqreturn_t vc4_crtc_irq_handler( + return ret; + } + ++static irqreturn_t vc4_crtc2712_irq_handler(int irq, void *data) ++{ ++ struct vc4_crtc **crtc_list = data; ++ int i; ++ ++ for (i = 0; crtc_list[i]; i++) { ++ if (crtc_list[i]->vblank_enabled) ++ drm_crtc_handle_vblank(&crtc_list[i]->base); ++ vc4_crtc_handle_page_flip(crtc_list[i]); ++ } ++ ++ return IRQ_HANDLED; ++} ++ + static int vc4_fkms_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, +@@ -1352,9 +1372,12 @@ static const struct drm_crtc_helper_func + }; + + static const struct of_device_id vc4_firmware_kms_dt_match[] = { +- { .compatible = "raspberrypi,rpi-firmware-kms" }, ++ { .compatible = "raspberrypi,rpi-firmware-kms", ++ .data = (void *)BCM2835_6_7 }, + { .compatible = "raspberrypi,rpi-firmware-kms-2711", +- .data = (void *)1 }, ++ .data = (void *)BCM2711 }, ++ { .compatible = "raspberrypi,rpi-firmware-kms-2712", ++ .data = (void *)BCM2712 }, + {} + }; + +@@ -1924,8 +1947,7 @@ static int vc4_fkms_bind(struct device * + match = of_match_device(vc4_firmware_kms_dt_match, dev); + if (!match) + return -ENODEV; +- if (match->data) +- fkms->bcm2711 = true; ++ fkms->revision = (enum vc4_fkms_revision)match->data; + + firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0); + vc4->firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node); +@@ -1992,10 +2014,16 @@ static int vc4_fkms_bind(struct device * + if (IS_ERR(crtc_list[0]->regs)) + DRM_ERROR("Oh dear, failed to map registers\n"); + +- writel(0, crtc_list[0]->regs + SMICS); +- ret = devm_request_irq(dev, platform_get_irq(pdev, 0), +- vc4_crtc_irq_handler, 0, +- "vc4 firmware kms", crtc_list); ++ if (fkms->revision >= BCM2712) { ++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), ++ vc4_crtc2712_irq_handler, 0, ++ "vc4 firmware kms", crtc_list); ++ } else { ++ writel(0, crtc_list[0]->regs + SMICS); ++ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), ++ vc4_crtc_irq_handler, 0, ++ "vc4 firmware kms", crtc_list); ++ } + if (ret) + DRM_ERROR("Oh dear, failed to register IRQ\n"); + } else { diff --git a/target/linux/bcm27xx/patches-6.1/950-1048-dt-Switch-bcm2712-firmware-kms-node-to-using-the-271.patch b/target/linux/bcm27xx/patches-6.1/950-1048-dt-Switch-bcm2712-firmware-kms-node-to-using-the-271.patch new file mode 100644 index 0000000000..9dea2d0fff --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1048-dt-Switch-bcm2712-firmware-kms-node-to-using-the-271.patch @@ -0,0 +1,25 @@ +From 5a52cae54a05499a8487f392cf5dfc3d8a837e6f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 20 Oct 2023 17:12:09 +0100 +Subject: [PATCH] dt: Switch bcm2712 firmware-kms node to using the 2712 + compatible + +With the new compatible to handle the interrupts correctly, switch +the base dt to use it. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm2712.dtsi ++++ b/arch/arm/boot/dts/bcm2712.dtsi +@@ -103,7 +103,7 @@ + }; + + firmwarekms: firmwarekms@7d503000 { +- compatible = "raspberrypi,rpi-firmware-kms"; ++ compatible = "raspberrypi,rpi-firmware-kms-2712"; + /* SUN_L2 interrupt reg */ + reg = <0x7d503000 0x18>; + interrupt-parent = <&cpu_l2_irq>; diff --git a/target/linux/bcm27xx/patches-6.1/950-1049-drivers-media-imx477-Disable-the-scaler.patch b/target/linux/bcm27xx/patches-6.1/950-1049-drivers-media-imx477-Disable-the-scaler.patch new file mode 100644 index 0000000000..841fa42440 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1049-drivers-media-imx477-Disable-the-scaler.patch @@ -0,0 +1,35 @@ +From f075893e9b0e241879998c0b12cf8af0ba7737da Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Mon, 23 Oct 2023 10:03:03 +0100 +Subject: [PATCH] drivers: media: imx477: Disable the scaler + +The horizontal scaler was enabled for the 2028x1520 and 2028x1080 modes, +with a scale factor of 1. It caused a single column of bad pixels on the +right edge of the image. Since scaling is not needed for these modes, +disable it entirely. + +Signed-off-by: Naushir Patuck +--- + drivers/media/i2c/imx477.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -632,7 +632,7 @@ static const struct imx477_reg mode_2028 + {0x9e9f, 0x00}, + {0xa2a9, 0x60}, + {0xa2b7, 0x00}, +- {0x0401, 0x01}, ++ {0x0401, 0x00}, + {0x0404, 0x00}, + {0x0405, 0x20}, + {0x0408, 0x00}, +@@ -733,7 +733,7 @@ static const struct imx477_reg mode_2028 + {0x9e9f, 0x00}, + {0xa2a9, 0x60}, + {0xa2b7, 0x00}, +- {0x0401, 0x01}, ++ {0x0401, 0x00}, + {0x0404, 0x00}, + {0x0405, 0x20}, + {0x0408, 0x00}, diff --git a/target/linux/bcm27xx/patches-6.1/950-1050-dt-Add-drm_fbN_vc4-overrides-for-Pi0-4.patch b/target/linux/bcm27xx/patches-6.1/950-1050-dt-Add-drm_fbN_vc4-overrides-for-Pi0-4.patch new file mode 100644 index 0000000000..77f30a345d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1050-dt-Add-drm_fbN_vc4-overrides-for-Pi0-4.patch @@ -0,0 +1,37 @@ +From eccaa8588fca9c9ec950664f1d5894bd826b57b0 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 23 Oct 2023 14:10:15 +0100 +Subject: [PATCH] dt: Add drm_fbN_vc4 overrides for Pi0-4 + +Follows up '61b138adaead ("dt: Add overrides for drm framebuffer +allocations on Pi5")' with an equivalent for Pi0-4. + +These will have no effect on most normal systems, but drm_fb0_vc4 +will stop SPI displays jumping in and claiming /dev/fb0. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm270x-rpi.dtsi | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm270x-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm270x-rpi.dtsi +@@ -1,7 +1,7 @@ + /* Downstream modifications to bcm2835-rpi.dtsi */ + + / { +- aliases { ++ aliases: aliases { + aux = &aux; + sound = &sound; + soc = &soc; +@@ -98,6 +98,9 @@ + sdio_overclock = <&mmc>,"brcm,overclock-50:0", + <&mmcnr>,"brcm,overclock-50:0"; + axiperf = <&axiperf>,"status"; ++ drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4; ++ drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4; ++ drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1051-fixup-overlays-mcp23017-allow-specification-of-the-i.patch b/target/linux/bcm27xx/patches-6.1/950-1051-fixup-overlays-mcp23017-allow-specification-of-the-i.patch new file mode 100644 index 0000000000..5016e78778 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1051-fixup-overlays-mcp23017-allow-specification-of-the-i.patch @@ -0,0 +1,95 @@ +From 3ed6d34d53e94ecbebc64c8fa3d1b6d3c41db8fb Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 24 Oct 2023 09:58:52 +0100 +Subject: [PATCH] fixup! overlays: mcp23017: allow specification of the i2c bus + +The incorrect fragment order (*) caused broke the interrupt usage, and +while it was being fixed the lack of a reference to the pinctrl +declaration was noticed. + +See: https://github.com/raspberrypi/linux/issues/5677 + +Signed-off-by: Phil Elwell + +(*) Ideally all fragments would appear in the file in the order in which +they should be merged, but that is easy to forget and can be awkward, so +the firmware merges all "intra" fragments (those that target other +fragments in the overlay) before "inter" fragments (those that target +the base DTB). However, intra fragments that target other intra +fragments is a level of nesting too far for this logic to cope, so they +must appear before the fragments they target. +--- + .../boot/dts/overlays/mcp23017-overlay.dts | 42 ++++++++++--------- + 1 file changed, 22 insertions(+), 20 deletions(-) + +--- a/arch/arm/boot/dts/overlays/mcp23017-overlay.dts ++++ b/arch/arm/boot/dts/overlays/mcp23017-overlay.dts +@@ -24,30 +24,13 @@ + }; + + fragment@2 { +- target = <&i2cbus>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- +- mcp23017: mcp@20 { +- compatible = "microchip,mcp23017"; +- reg = <0x20>; +- gpio-controller; +- #gpio-cells = <2>; +- +- status = "okay"; +- }; +- }; +- }; +- +- fragment@3 { + target = <&mcp23017>; + __dormant__ { + compatible = "microchip,mcp23008"; + }; + }; + +- fragment@4 { ++ fragment@3 { + target = <&mcp23017>; + mcp23017_irq: __overlay__ { + #interrupt-cells=<2>; +@@ -58,6 +41,25 @@ + }; + }; + ++ fragment@4 { ++ target = <&i2cbus>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp23017: mcp@20 { ++ compatible = "microchip,mcp23017"; ++ pinctrl-name = "default"; ++ pinctrl-0 = <&mcp23017_pins>; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ status = "okay"; ++ }; ++ }; ++ }; ++ + frag100: fragment@100 { + target = <&i2c1>; + i2cbus: __overlay__ { +@@ -83,8 +85,8 @@ + gpiopin = <&mcp23017_pins>,"brcm,pins:0", + <&mcp23017_irq>,"interrupts:0"; + addr = <&mcp23017>,"reg:0", <&mcp23017_pins>,"reg:0"; +- mcp23008 = <0>,"=3"; +- noints = <0>,"!1!4"; ++ mcp23008 = <0>,"=2"; ++ noints = <0>,"!1!3"; + i2c0 = <&frag100>, "target:0=",<&i2c0>; + i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, + <0>,"+101+102"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1052-drivers-media-pisp_be-Add-back-V4L2_PIX_FMT_RPI_BE-f.patch b/target/linux/bcm27xx/patches-6.1/950-1052-drivers-media-pisp_be-Add-back-V4L2_PIX_FMT_RPI_BE-f.patch new file mode 100644 index 0000000000..7fe0c50740 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1052-drivers-media-pisp_be-Add-back-V4L2_PIX_FMT_RPI_BE-f.patch @@ -0,0 +1,54 @@ +From 8d53cc5b4b2a6f9baed7a0aa801a39ad9dce9bf8 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Thu, 26 Oct 2023 08:55:24 +0100 +Subject: [PATCH] drivers: media: pisp_be: Add back V4L2_PIX_FMT_RPI_BE format + +Add the opaque V4L2_PIX_FMT_RPI_BE format back to the format list as it +is needed for the verification test suite. Also set the default format +to YUV420 non-multiplanar. + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/raspberrypi/pisp_be/pisp_be.c | 9 ++++++--- + .../media/platform/raspberrypi/pisp_be/pisp_be_formats.h | 5 +++++ + 2 files changed, 11 insertions(+), 3 deletions(-) + +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c +@@ -1230,8 +1230,11 @@ static int try_format(struct v4l2_format + return verify_be_pix_format(f, node); + + fmt = find_format(pixfmt); +- if (!fmt) +- fmt = find_format(V4L2_PIX_FMT_YUV420M); ++ if (!fmt) { ++ dev_dbg(pispbe->dev, "%s: [%s] Format not found, defaulting to YUV420\n", ++ __func__, NODE_NAME(node)); ++ fmt = find_format(V4L2_PIX_FMT_YUV420); ++ } + + f->fmt.pix_mp.pixelformat = fmt->fourcc; + f->fmt.pix_mp.num_planes = fmt->num_planes; +@@ -1576,7 +1579,7 @@ static void node_set_default_format(stru + } else { + struct v4l2_format f = {0}; + +- f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M; ++ f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420; + f.fmt.pix_mp.width = 1920; + f.fmt.pix_mp.height = 1080; + f.type = node->buf_type; +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h +@@ -457,6 +457,11 @@ static const struct pisp_be_format suppo + .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, + .colorspace_default = V4L2_COLORSPACE_RAW, + }, ++ /* Opaque BE format for HW verification. */ ++ { ++ .fourcc = V4L2_PIX_FMT_RPI_BE, ++ .align = 32, ++ }, + }; + + static const struct pisp_be_format meta_out_supported_formats[] = { diff --git a/target/linux/bcm27xx/patches-6.1/950-1053-dt-bindings-PCI-brcmstb-add-optional-property-brcm-t.patch b/target/linux/bcm27xx/patches-6.1/950-1053-dt-bindings-PCI-brcmstb-add-optional-property-brcm-t.patch new file mode 100644 index 0000000000..3ef42e7967 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1053-dt-bindings-PCI-brcmstb-add-optional-property-brcm-t.patch @@ -0,0 +1,32 @@ +From f1154884295a4bd00d6ebcaf01fa30141145903d Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 20 Sep 2023 10:04:15 +0100 +Subject: [PATCH] dt-bindings: PCI: brcmstb: add optional property - + "brcm,tperst-clk-ms" + +This property can be used to delay deassertion of external fundamental +reset, which may be useful for endpoints that require an extended time for +internal setup to complete. + +Signed-off-by: Jonathan Bell +--- + Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml ++++ b/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml +@@ -77,6 +77,14 @@ properties: + minItems: 1 + maxItems: 3 + ++ brcm,tperst-clk-ms: ++ category: optional ++ type: int ++ description: u32 giving the number of milliseconds to extend ++ the time between internal release of fundamental reset and ++ the deassertion of the external PERST# pin. This has the ++ effect of increasing the Tperst_clk phase of link init. ++ + required: + - compatible + - reg diff --git a/target/linux/bcm27xx/patches-6.1/950-1054-drivers-pci-brcmstb-optionally-extend-Tperst_clk-tim.patch b/target/linux/bcm27xx/patches-6.1/950-1054-drivers-pci-brcmstb-optionally-extend-Tperst_clk-tim.patch new file mode 100644 index 0000000000..021e210591 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1054-drivers-pci-brcmstb-optionally-extend-Tperst_clk-tim.patch @@ -0,0 +1,71 @@ +From 4b0c6453808a662869a43c504913f3b7ed64486a Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 20 Sep 2023 13:01:11 +0100 +Subject: [PATCH] drivers: pci: brcmstb: optionally extend Tperst_clk time + during link-up + +The RC has a feature that allows for manual control over the deassertion +of the PERST# output pin, which allows the time between refclk active +and reset deassert at the EP to be increased. + +Signed-off-by: Jonathan Bell +--- + drivers/pci/controller/pcie-brcmstb.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +--- a/drivers/pci/controller/pcie-brcmstb.c ++++ b/drivers/pci/controller/pcie-brcmstb.c +@@ -138,6 +138,7 @@ + + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG pcie->reg_offsets[PCIE_HARD_DEBUG] + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2 ++#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK 0x8 + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000 + #define PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x00800000 + #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK 0x00200000 +@@ -352,6 +353,7 @@ struct brcm_pcie { + bool (*rc_mode)(struct brcm_pcie *pcie); + struct subdev_regulators *sr; + bool ep_wakeup_capable; ++ u32 tperst_clk_ms; + }; + + static inline bool is_bmips(const struct brcm_pcie *pcie) +@@ -1388,9 +1390,28 @@ static int brcm_pcie_start_link(struct b + u16 nlw, cls, lnksta; + bool ssc_good = false; + int ret, i; ++ u32 tmp; + + /* Unassert the fundamental reset */ +- pcie->perst_set(pcie, 0); ++ if (pcie->tperst_clk_ms) { ++ /* ++ * Increase Tperst_clk time by forcing PERST# output low while ++ * the internal reset is released, so the PLL generates stable ++ * refclk output further in advance of PERST# deassertion. ++ */ ++ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK); ++ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ ++ pcie->perst_set(pcie, 0); ++ msleep(pcie->tperst_clk_ms); ++ ++ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ u32p_replace_bits(&tmp, 0, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK); ++ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG); ++ } else { ++ pcie->perst_set(pcie, 0); ++ } + + /* + * Wait for 100ms after PERST# deassertion; see PCIe CEM specification +@@ -1923,6 +1944,7 @@ static int brcm_pcie_probe(struct platfo + pcie->ssc = of_property_read_bool(np, "brcm,enable-ssc"); + pcie->l1ss = of_property_read_bool(np, "brcm,enable-l1ss"); + pcie->rcb_mps_mode = of_property_read_bool(np, "brcm,enable-mps-rcb"); ++ of_property_read_u32(np, "brcm,tperst-clk-ms", &pcie->tperst_clk_ms); + + ret = clk_prepare_enable(pcie->clk); + if (ret) { diff --git a/target/linux/bcm27xx/patches-6.1/950-1055-arm-dt-add-dtparams-for-PCIe-reset-timing-override.patch b/target/linux/bcm27xx/patches-6.1/950-1055-arm-dt-add-dtparams-for-PCIe-reset-timing-override.patch new file mode 100644 index 0000000000..a81d0383ac --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1055-arm-dt-add-dtparams-for-PCIe-reset-timing-override.patch @@ -0,0 +1,59 @@ +From db90a5e5fc2fbd843b29eb8110ed5e03604a2887 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 20 Sep 2023 13:04:54 +0100 +Subject: [PATCH] arm: dt: add dtparams for PCIe reset timing override + +The Pi 5 variant gets two parameters so that the CM4-compatible +name will also work on Pi 5. + +Signed-off-by: Jonathan Bell +--- + arch/arm/boot/dts/bcm2711-rpi-cm4.dts | 2 ++ + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 ++ + arch/arm/boot/dts/overlays/README | 7 +++++++ + 3 files changed, 11 insertions(+) + +--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dts ++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dts +@@ -446,5 +446,7 @@ i2c_csi_dsi0: &i2c0 { + cam1_reg = <&cam1_reg>,"status"; + cam1_reg_gpio = <&cam1_reg>,"gpio:4", + <&cam1_reg>,"gpio:0=", <&gpio>; ++ ++ pcie_tperst_clk_ms = <&pcie0>,"brcm,tperst-clk-ms:0"; + }; + }; +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -814,6 +814,8 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + pciex1 = <&pciex1>, "status"; + pciex1_gen = <&pciex1> , "max-link-speed:0"; + pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?"; ++ pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; ++ pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; + random = <&random>, "status"; + rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0"; + spi = <&spi0>, "status"; +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -280,6 +280,10 @@ Params: + (2711 only, but not applicable on CM4S) + N.B. USB-A ports on 4B are subsequently disabled + ++ pcie_tperst_clk_ms Add N milliseconds between PCIe reference clock ++ activation and PERST# deassertion ++ (CM4 and 2712, default "0") ++ + pciex1 Set to "on" to enable the external PCIe link + (2712 only, default "off") + +@@ -290,6 +294,9 @@ Params: + PCIe link for devices that have broken + implementations (2712 only, default "off") + ++ pciex1_tperst_clk_ms Alias for pcie_tperst_clk_ms ++ (2712 only, default "0") ++ + spi Set to "on" to enable the spi interfaces + (default "off") + diff --git a/target/linux/bcm27xx/patches-6.1/950-1056-arm-dt-bcm2712-don-t-unconditionally-enable-MPS-read.patch b/target/linux/bcm27xx/patches-6.1/950-1056-arm-dt-bcm2712-don-t-unconditionally-enable-MPS-read.patch new file mode 100644 index 0000000000..b08a5720d5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1056-arm-dt-bcm2712-don-t-unconditionally-enable-MPS-read.patch @@ -0,0 +1,35 @@ +From cb013b6602de32c647ed08faf899596664a18635 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Thu, 26 Oct 2023 13:47:54 +0100 +Subject: [PATCH] arm: dt: bcm2712: don't unconditionally enable MPS read + completions + +RP1 supports it, but it's not a given that an arbitrary EP device +on PCIE2 will. Migrate the property to the rp1_target fragment. + +Signed-off-by: Jonathan Bell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 1 + + arch/arm/boot/dts/bcm2712.dtsi | 1 - + 2 files changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -160,6 +160,7 @@ + }; + + rp1_target: &pcie2 { ++ brcm,enable-mps-rcb; + brcm,vdm-qos-map = <0xbbaa9888>; + aspm-no-l0s; + status = "okay"; +--- a/arch/arm/boot/dts/bcm2712.dtsi ++++ b/arch/arm/boot/dts/bcm2712.dtsi +@@ -1086,7 +1086,6 @@ + 0x00 0x00000000 + 0x10 0x00000000>; + +- brcm,enable-mps-rcb; + brcm,enable-l1ss; + status = "disabled"; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1057-drivers-media-imx477-Set-horizontal-binning-when-dis.patch b/target/linux/bcm27xx/patches-6.1/950-1057-drivers-media-imx477-Set-horizontal-binning-when-dis.patch new file mode 100644 index 0000000000..e6122e1a6b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1057-drivers-media-imx477-Set-horizontal-binning-when-dis.patch @@ -0,0 +1,39 @@ +From 8dcc16f0adc50f5cb8a11a6dde238131d0ca45a0 Mon Sep 17 00:00:00 2001 +From: David Plowman +Date: Fri, 27 Oct 2023 12:14:22 +0100 +Subject: [PATCH] drivers: media: imx477: Set horizontal binning when disabling + the scaler + +The horizontal scaler has been disabled but actually the sensor is not +binning horizontally, resulting in images that are stretched 2x +horizontally (missing the right half of the field of view completely). + +Therefore we must additionally set the horizontal binning mode. There +is only marginal change in output quality and noise levels. + +Signed-off-by: David Plowman +Fixes: f075893e9b0e ("drivers: media: imx477: Disable the scaler") +--- + drivers/media/i2c/imx477.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -607,7 +607,7 @@ static const struct imx477_reg mode_2028 + {0x0385, 0x01}, + {0x0387, 0x01}, + {0x0900, 0x01}, +- {0x0901, 0x12}, ++ {0x0901, 0x22}, + {0x0902, 0x02}, + {0x3140, 0x02}, + {0x3c00, 0x00}, +@@ -708,7 +708,7 @@ static const struct imx477_reg mode_2028 + {0x0385, 0x01}, + {0x0387, 0x01}, + {0x0900, 0x01}, +- {0x0901, 0x12}, ++ {0x0901, 0x22}, + {0x0902, 0x02}, + {0x3140, 0x02}, + {0x3c00, 0x00}, diff --git a/target/linux/bcm27xx/patches-6.1/950-1058-fixup-arch-arm64-Add-Revision-Serial-Model-to-cpuinf.patch b/target/linux/bcm27xx/patches-6.1/950-1058-fixup-arch-arm64-Add-Revision-Serial-Model-to-cpuinf.patch new file mode 100644 index 0000000000..adedaf6d4b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1058-fixup-arch-arm64-Add-Revision-Serial-Model-to-cpuinf.patch @@ -0,0 +1,25 @@ +From e641fd7a50987ad6b7ce1ab36189bc8817295e42 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 31 Oct 2023 16:34:56 +0000 +Subject: [PATCH] fixup! arch/arm64: Add Revision, Serial, Model to cpuinfo + +Delete the Hardware string, which is pointless and misleading. + +See: https://github.com/raspberrypi/bookworm-feedback/issues/129 + +Signed-off-by: Phil Elwell +--- + arch/arm64/kernel/cpuinfo.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/arch/arm64/kernel/cpuinfo.c ++++ b/arch/arm64/kernel/cpuinfo.c +@@ -224,8 +224,6 @@ static int c_show(struct seq_file *m, vo + seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr)); + } + +- seq_printf(m, "Hardware\t: BCM2835\n"); +- + np = of_find_node_by_path("/system"); + if (np) { + if (!of_property_read_u32(np, "linux,revision", &revision)) diff --git a/target/linux/bcm27xx/patches-6.1/950-1060-dts-bcm2710-rpi-zero-2-w-Remove-WLAN-firmwares.patch b/target/linux/bcm27xx/patches-6.1/950-1060-dts-bcm2710-rpi-zero-2-w-Remove-WLAN-firmwares.patch new file mode 100644 index 0000000000..18c12cd10f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1060-dts-bcm2710-rpi-zero-2-w-Remove-WLAN-firmwares.patch @@ -0,0 +1,35 @@ +From e86c43b86179fba90a1d9dd5acb554767af6740f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 12 Jun 2023 15:23:55 +0100 +Subject: [PATCH] dts: bcm2710-rpi-zero-2-w: Remove WLAN firmwares + +With careful use of qualified firmware names there is no need for the +ability to override the device names based on Device Tree properties. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts | 13 ------------- + 1 file changed, 13 deletions(-) + +--- a/arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts ++++ b/arch/arm/boot/dts/bcm2710-rpi-zero-2-w.dts +@@ -161,19 +161,6 @@ + brcmf: wifi@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; +- +- firmwares { +- fw_43436p { +- chipid = <43430>; +- revmask = <4>; +- fw_base = "brcm/brcmfmac43436-sdio"; +- }; +- fw_43436s { +- chipid = <43430>; +- revmask = <2>; +- fw_base = "brcm/brcmfmac43436s-sdio"; +- }; +- }; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1061-drivers-media-cfe-Set-the-CSI-2-link-frequency-corre.patch b/target/linux/bcm27xx/patches-6.1/950-1061-drivers-media-cfe-Set-the-CSI-2-link-frequency-corre.patch new file mode 100644 index 0000000000..d5aeae5333 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1061-drivers-media-cfe-Set-the-CSI-2-link-frequency-corre.patch @@ -0,0 +1,111 @@ +From a11312709f46b71bf320a9dcc8cf4e09056552cd Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 1 Nov 2023 13:25:54 +0000 +Subject: [PATCH] drivers: media: cfe: Set the CSI-2 link frequency correctly + +Use the sensor provided link frequency to set the DPHY timing parameters +on stream_on. This replaces the hard-coded 999 MHz value currently being +used. As a fallback, revert to the original 999 Mhz link frequency. + +As a drive-by, fix a 80-character line formatting error. + +Signed-off-by: Naushir Patuck +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 63 +++++++++++++++++-- + 1 file changed, 58 insertions(+), 5 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -780,7 +780,8 @@ static void cfe_start_channel(struct cfe + __func__, node_desc[FE_OUT0].name, + cfe->fe_csi2_channel); + +- source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, cfe->fe_csi2_channel); ++ source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, ++ cfe->fe_csi2_channel); + fmt = find_format_by_code(source_fmt->code); + + width = source_fmt->width; +@@ -982,6 +983,59 @@ static void cfe_buffer_queue(struct vb2_ + spin_unlock_irqrestore(&cfe->state_lock, flags); + } + ++static u64 sensor_link_frequency(struct cfe_device *cfe) ++{ ++ struct v4l2_mbus_framefmt *source_fmt; ++ struct v4l2_subdev_state *state; ++ struct media_entity *entity; ++ struct v4l2_subdev *subdev; ++ const struct cfe_fmt *fmt; ++ struct media_pad *pad; ++ s64 link_freq; ++ ++ state = v4l2_subdev_lock_and_get_active_state(&cfe->csi2.sd); ++ source_fmt = v4l2_subdev_get_pad_format(&cfe->csi2.sd, state, 0); ++ fmt = find_format_by_code(source_fmt->code); ++ v4l2_subdev_unlock_state(state); ++ ++ /* ++ * Walk up the media graph to find either the sensor entity, or another ++ * entity that advertises the V4L2_CID_LINK_FREQ or V4L2_CID_PIXEL_RATE ++ * control through the subdev. ++ */ ++ entity = &cfe->csi2.sd.entity; ++ while (1) { ++ pad = &entity->pads[0]; ++ if (!(pad->flags & MEDIA_PAD_FL_SINK)) ++ goto err; ++ ++ pad = media_pad_remote_pad_first(pad); ++ if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) ++ goto err; ++ ++ entity = pad->entity; ++ subdev = media_entity_to_v4l2_subdev(entity); ++ if (entity->function == MEDIA_ENT_F_CAM_SENSOR || ++ v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_LINK_FREQ) || ++ v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_PIXEL_RATE)) ++ break; ++ } ++ ++ link_freq = v4l2_get_link_freq(subdev->ctrl_handler, fmt->depth, ++ cfe->csi2.active_data_lanes * 2); ++ if (link_freq < 0) ++ goto err; ++ ++ /* x2 for DDR. */ ++ link_freq *= 2; ++ cfe_info("Using a link frequency of %lld Hz\n", link_freq); ++ return link_freq; ++ ++err: ++ cfe_err("Unable to determine sensor link frequency, using 999 MHz\n"); ++ return 999 * 1000000UL; ++} ++ + static int cfe_start_streaming(struct vb2_queue *vq, unsigned int count) + { + struct v4l2_mbus_config mbus_config = { 0 }; +@@ -1049,10 +1103,11 @@ static int cfe_start_streaming(struct vb + goto err_disable_cfe; + } + +- cfe_dbg("Starting sensor streaming\n"); +- ++ cfe_dbg("Configuring CSI-2 block\n"); ++ cfe->csi2.dphy.dphy_freq = sensor_link_frequency(cfe) / 1000000UL; + csi2_open_rx(&cfe->csi2); + ++ cfe_dbg("Starting sensor streaming\n"); + cfe->sequence = 0; + ret = v4l2_subdev_call(cfe->sensor, video, s_stream, 1); + if (ret < 0) { +@@ -1945,8 +2000,6 @@ static int of_cfe_connect_subdevs(struct + } + } + +- /* TODO: Get the frequency from devicetree */ +- cfe->csi2.dphy.dphy_freq = 999; + cfe->csi2.dphy.num_lanes = ep.bus.mipi_csi2.num_data_lanes; + cfe->csi2.bus_flags = ep.bus.mipi_csi2.flags; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1062-dts-bcm2712-rpi-5-b-Create-some-dummy-nodes.patch b/target/linux/bcm27xx/patches-6.1/950-1062-dts-bcm2712-rpi-5-b-Create-some-dummy-nodes.patch new file mode 100644 index 0000000000..722714d56a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1062-dts-bcm2712-rpi-5-b-Create-some-dummy-nodes.patch @@ -0,0 +1,42 @@ +From fb78b2617e70e58e03e0d50e674758fdd2a80d45 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 Nov 2023 10:39:11 +0000 +Subject: [PATCH] dts: bcm2712-rpi-5-b: Create some dummy nodes + +The kernel now treats multiple fragments targeting the same node as an +error. For this reason, it is important that labels created just for +compatibility with other systems (e.g. i2c0if and i2c0mux) are +attached to unique nodes, not just tacked onto existing nodes. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -157,6 +157,12 @@ + dummy: dummy { + // A target for unwanted overlay fragments + }; ++ ++ ++ // A few extra labels to keep overlays happy ++ ++ i2c0if: i2c0if {}; ++ i2c0mux: i2c0mux {}; + }; + + rp1_target: &pcie2 { +@@ -243,11 +249,6 @@ aux: &dummy {}; + + #include "bcm2712-rpi.dtsi" + +-// A few extra labels to keep overlays happy +- +-i2c0if: &rp1_gpio {}; +-i2c0mux: &rp1_gpio {}; +- + i2c_csi_dsi0: &i2c6 { // Note: This is for MIPI0 connector only + pinctrl-0 = <&rp1_i2c6_38_39>; + pinctrl-names = "default"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1063-dts-rp1-Add-spi6-fix-spi1-address-cells.patch b/target/linux/bcm27xx/patches-6.1/950-1063-dts-rp1-Add-spi6-fix-spi1-address-cells.patch new file mode 100644 index 0000000000..41ab025555 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1063-dts-rp1-Add-spi6-fix-spi1-address-cells.patch @@ -0,0 +1,49 @@ +From cd66a0832351762b496bdce6f2f94a871d11484e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 Nov 2023 13:12:55 +0000 +Subject: [PATCH] dts: rp1: Add spi6, fix spi1 #address-cells + +spi6 won't be useful on Pi 5 because it can't be enabled on the 40-pin +header, but include it for completeness. + +Also fix the #address-cells value for spi1, otherwise the kernel will +reject attempts to apply the, say, spi1-2cs overlay at runtime. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/rp1.dtsi | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/rp1.dtsi ++++ b/arch/arm/boot/dts/rp1.dtsi +@@ -187,7 +187,7 @@ + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; + clock-names = "ssi_clk"; +- #address-cells = <0>; ++ #address-cells = <1>; + #size-cells = <0>; + num-cs = <2>; + dmas = <&rp1_dma RP1_DMA_SPI1_TX>, +@@ -262,6 +262,21 @@ + dma-names = "tx", "rx"; + status = "disabled"; + }; ++ ++ rp1_spi6: spi@68000 { ++ reg = <0xc0 0x40068000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI6_TX>, ++ <&rp1_dma RP1_DMA_SPI6_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; + + // SPI7 is a target/slave interface + rp1_spi7: spi@6c000 { diff --git a/target/linux/bcm27xx/patches-6.1/950-1064-overlays-uart-n-pi5-Add-the-pinctrl-0-property.patch b/target/linux/bcm27xx/patches-6.1/950-1064-overlays-uart-n-pi5-Add-the-pinctrl-0-property.patch new file mode 100644 index 0000000000..b6e0c323db --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1064-overlays-uart-n-pi5-Add-the-pinctrl-0-property.patch @@ -0,0 +1,67 @@ +From 17f135b742c4edb340afb365873c3a574f7e16cb Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 Nov 2023 17:05:46 +0000 +Subject: [PATCH] overlays: uart-pi5: Add the pinctrl-0 property + +Without the pinctrl-0 property in the overlays, the UARTs may not be +mapped correctly. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/uart0-pi5-overlay.dts | 1 + + arch/arm/boot/dts/overlays/uart1-pi5-overlay.dts | 1 + + arch/arm/boot/dts/overlays/uart2-pi5-overlay.dts | 1 + + arch/arm/boot/dts/overlays/uart3-pi5-overlay.dts | 1 + + arch/arm/boot/dts/overlays/uart4-pi5-overlay.dts | 1 + + 5 files changed, 5 insertions(+) + +--- a/arch/arm/boot/dts/overlays/uart0-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/uart0-pi5-overlay.dts +@@ -8,6 +8,7 @@ + target = <&uart0>; + frag0: __overlay__ { + status = "okay"; ++ pinctrl-0 = <&uart0_pins>; + }; + }; + +--- a/arch/arm/boot/dts/overlays/uart1-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/uart1-pi5-overlay.dts +@@ -8,6 +8,7 @@ + target = <&uart1>; + frag0: __overlay__ { + status = "okay"; ++ pinctrl-0 = <&uart1_pins>; + }; + }; + +--- a/arch/arm/boot/dts/overlays/uart2-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/uart2-pi5-overlay.dts +@@ -8,6 +8,7 @@ + target = <&uart2>; + frag0: __overlay__ { + status = "okay"; ++ pinctrl-0 = <&uart2_pins>; + }; + }; + +--- a/arch/arm/boot/dts/overlays/uart3-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/uart3-pi5-overlay.dts +@@ -8,6 +8,7 @@ + target = <&uart3>; + frag0: __overlay__ { + status = "okay"; ++ pinctrl-0 = <&uart3_pins>; + }; + }; + +--- a/arch/arm/boot/dts/overlays/uart4-pi5-overlay.dts ++++ b/arch/arm/boot/dts/overlays/uart4-pi5-overlay.dts +@@ -8,6 +8,7 @@ + target = <&uart4>; + frag0: __overlay__ { + status = "okay"; ++ pinctrl-0 = <&uart4_pins>; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1065-drivers-media-imx477-Add-V4L2_CID_LINK_FREQ-control.patch b/target/linux/bcm27xx/patches-6.1/950-1065-drivers-media-imx477-Add-V4L2_CID_LINK_FREQ-control.patch new file mode 100644 index 0000000000..f0a652b520 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1065-drivers-media-imx477-Add-V4L2_CID_LINK_FREQ-control.patch @@ -0,0 +1,51 @@ +From c9a785d57c302d5f1d4de4e67fa57522e66c7882 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Mon, 6 Nov 2023 09:40:50 +0000 +Subject: [PATCH] drivers: media: imx477: Add V4L2_CID_LINK_FREQ control + +Add V4L2_CID_LINK_FREQ as a read-only control with a value of 450 Mhz. +This will be used by the CFE driver to corretly setup the DPHY timing +parameters in the CSI-2 block. + +Signed-off-by: Naushir Patuck +--- + drivers/media/i2c/imx477.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -164,6 +164,10 @@ struct imx477_mode { + struct imx477_reg_list reg_list; + }; + ++static const s64 imx477_link_freq_menu[] = { ++ IMX477_DEFAULT_LINK_FREQ, ++}; ++ + static const struct imx477_reg mode_common_regs[] = { + {0x0136, 0x18}, + {0x0137, 0x00}, +@@ -1110,6 +1114,7 @@ struct imx477 { + struct v4l2_ctrl_handler ctrl_handler; + /* V4L2 Controls */ + struct v4l2_ctrl *pixel_rate; ++ struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *vflip; + struct v4l2_ctrl *hflip; +@@ -1997,6 +2002,15 @@ static int imx477_init_controls(struct i + IMX477_PIXEL_RATE, 1, + IMX477_PIXEL_RATE); + ++ /* LINK_FREQ is also read only */ ++ imx477->link_freq = ++ v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx477_ctrl_ops, ++ V4L2_CID_LINK_FREQ, ++ ARRAY_SIZE(imx477_link_freq_menu) - 1, 0, ++ imx477_link_freq_menu); ++ if (imx477->link_freq) ++ imx477->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ + /* + * Create the controls here, but mode specific limits are setup + * in the imx477_set_framing_limits() call below. diff --git a/target/linux/bcm27xx/patches-6.1/950-1066-drivers-media-imx477-Correctly-set-IMX477_PIXEL_RATE.patch b/target/linux/bcm27xx/patches-6.1/950-1066-drivers-media-imx477-Correctly-set-IMX477_PIXEL_RATE.patch new file mode 100644 index 0000000000..f62fbbe13d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1066-drivers-media-imx477-Correctly-set-IMX477_PIXEL_RATE.patch @@ -0,0 +1,24 @@ +From 46913ee0590ee0e3f607ab189be19a4d0ce785f2 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Mon, 6 Nov 2023 09:42:37 +0000 +Subject: [PATCH] drivers: media: imx477: Correctly set IMX477_PIXEL_RATE as a + r/o control + +This control is meant to be read-only, mark it as such. + +Signed-off-by: Naushir Patuck +--- + drivers/media/i2c/imx477.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -2001,6 +2001,8 @@ static int imx477_init_controls(struct i + IMX477_PIXEL_RATE, + IMX477_PIXEL_RATE, 1, + IMX477_PIXEL_RATE); ++ if (imx477->pixel_rate) ++ imx477->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + /* LINK_FREQ is also read only */ + imx477->link_freq = diff --git a/target/linux/bcm27xx/patches-6.1/950-1067-drm-vc4-Correct-logic-on-stopping-an-HVS-channel.patch b/target/linux/bcm27xx/patches-6.1/950-1067-drm-vc4-Correct-logic-on-stopping-an-HVS-channel.patch new file mode 100644 index 0000000000..948d79bfdb --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1067-drm-vc4-Correct-logic-on-stopping-an-HVS-channel.patch @@ -0,0 +1,52 @@ +From 6e9f68bba01b9c36a77b68c4b3167c317da986da Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 26 Oct 2023 17:46:13 +0100 +Subject: [PATCH] drm/vc4: Correct logic on stopping an HVS channel + +When factoring out __vc4_hvs_stop_channel, the logic got inverted from + if (condition) + // stop channel +to + if (condition) + goto out + //stop channel + out: +and also changed the exact register writes used to stop the channel. + +Correct the logic so that the channel is actually stopped, and revert +to the original register writes. + +Fixes: 6d01a106b4c8 ("drm/vc4: crtc: Move HVS init and close to a function") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -992,13 +992,11 @@ static void __vc4_hvs_stop_channel(struc + if (!drm_dev_enter(drm, &idx)) + return; + +- if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE) ++ if (!(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)) + goto out; + +- HVS_WRITE(SCALER_DISPCTRLX(chan), +- HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET); +- HVS_WRITE(SCALER_DISPCTRLX(chan), +- HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE); ++ HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET); ++ HVS_WRITE(SCALER_DISPCTRLX(chan), 0); + + /* Once we leave, the scaler should be disabled and its fifo empty. */ + WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET); +@@ -1026,7 +1024,7 @@ static void __vc6_hvs_stop_channel(struc + if (!drm_dev_enter(drm, &idx)) + return; + +- if (HVS_READ(SCALER6_DISPX_CTRL0(chan)) & SCALER6_DISPX_CTRL0_ENB) ++ if (!(HVS_READ(SCALER6_DISPX_CTRL0(chan)) & SCALER6_DISPX_CTRL0_ENB)) + goto out; + + HVS_WRITE(SCALER6_DISPX_CTRL0(chan), diff --git a/target/linux/bcm27xx/patches-6.1/950-1068-drm-vc4-Drop-WARN-for-HVS-FIFOs-not-being-empty.patch b/target/linux/bcm27xx/patches-6.1/950-1068-drm-vc4-Drop-WARN-for-HVS-FIFOs-not-being-empty.patch new file mode 100644 index 0000000000..627f22c845 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1068-drm-vc4-Drop-WARN-for-HVS-FIFOs-not-being-empty.patch @@ -0,0 +1,30 @@ +From 31c4c359aa2dbb1a7c095f0a6ef4e13cd46cfd14 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 26 Oct 2023 18:05:09 +0100 +Subject: [PATCH] drm/vc4: Drop WARN for HVS FIFOs not being empty + +The reset condition for the EMPTY flag in DISPSTATx is 0, +so seeing as we've just reset the pipeline there is no +guarantee that the flag will denote empty if it hasn't been +enabled. + +Drop the WARN. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1005,10 +1005,6 @@ static void __vc4_hvs_stop_channel(struc + SCALER_DISPSTATX_MODE) != + SCALER_DISPSTATX_MODE_DISABLED); + +- WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) & +- (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) != +- SCALER_DISPSTATX_EMPTY); +- + out: + drm_dev_exit(idx); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-1069-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch b/target/linux/bcm27xx/patches-6.1/950-1069-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch new file mode 100644 index 0000000000..ce03224c39 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1069-drm-vc4-Free-all-stale-dlists-if-channel-is-disabled.patch @@ -0,0 +1,85 @@ +From 8b7078d1bbd8bb548cc97d5214adb828e9f0037c Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 26 Oct 2023 18:23:31 +0100 +Subject: [PATCH] drm/vc4: Free all stale dlists if channel is disabled + +The code handling freeing stale dlists had 2 issues: +- it disabled the interrupt as soon as the first EOF interrupt + occurred, even if it didn't clear all stale allocations, thus + leading to stale entries +- It didn't free stale entries from disabled channels, so eg + "kmstest -c 0" could leave a stale alloc on channel 1 floating + around. + +Keep the interrupt enabled whilst there are any outstanding +allocs, and discard those on disabled channels. This second +channel does require us to call vc4_hvs_stop_channel from +vc4_crtc_atomic_disable so that the channel actually gets stopped. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++ + drivers/gpu/drm/vc4/vc4_hvs.c | 27 +++++++++++++++++++++++++-- + 2 files changed, 27 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -660,6 +660,8 @@ static void vc4_crtc_atomic_disable(stru + + vc4_crtc_disable(crtc, encoder, state, old_vc4_state->assigned_channel); + ++ vc4_hvs_atomic_disable(crtc, state); ++ + /* + * Make sure we issue a vblank event after disabling the CRTC if + * someone was waiting it. +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -697,7 +697,8 @@ static void vc4_hvs_schedule_dlist_sweep + if (!list_empty(&hvs->stale_dlist_entries)) + queue_work(system_unbound_wq, &hvs->free_dlist_work); + +- vc4_hvs_irq_clear_eof(hvs, channel); ++ if (list_empty(&hvs->stale_dlist_entries)) ++ vc4_hvs_irq_clear_eof(hvs, channel); + + spin_unlock_irqrestore(&hvs->mm_lock, flags); + } +@@ -712,6 +713,27 @@ static bool vc4_hvs_frcnt_lte(u8 cnt1, u + return (s8)((cnt1 << 2) - (cnt2 << 2)) <= 0; + } + ++bool vc4_hvs_check_channel_active(struct vc4_hvs *hvs, unsigned int fifo) ++{ ++ struct vc4_dev *vc4 = hvs->vc4; ++ struct drm_device *drm = &vc4->base; ++ bool enabled = false; ++ int idx; ++ ++ WARN_ON_ONCE(vc4->gen > VC4_GEN_6); ++ ++ if (!drm_dev_enter(drm, &idx)) ++ return 0; ++ ++ if (vc4->gen >= VC4_GEN_6) ++ enabled = HVS_READ(SCALER6_DISPX_CTRL0(fifo)) & SCALER6_DISPX_CTRL0_ENB; ++ else ++ enabled = HVS_READ(SCALER_DISPCTRLX(fifo)) & SCALER_DISPCTRLX_ENABLE; ++ ++ drm_dev_exit(idx); ++ return enabled; ++} ++ + /* + * Some atomic commits (legacy cursor updates, mostly) will not wait for + * the next vblank and will just return once the commit has been pushed +@@ -746,7 +768,8 @@ static void vc4_hvs_dlist_free_work(stru + u8 frcnt; + + frcnt = vc4_hvs_get_fifo_frame_count(hvs, cur->channel); +- if (!vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt)) ++ if (vc4_hvs_check_channel_active(hvs, cur->channel) && ++ !vc4_hvs_frcnt_lte(cur->target_frame_count, frcnt)) + continue; + + vc4_hvs_free_dlist_entry_locked(hvs, cur); diff --git a/target/linux/bcm27xx/patches-6.1/950-1070-drm-vc4-Add-hvs_dlist_allocs-debugfs-function.patch b/target/linux/bcm27xx/patches-6.1/950-1070-drm-vc4-Add-hvs_dlist_allocs-debugfs-function.patch new file mode 100644 index 0000000000..b16489a12d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1070-drm-vc4-Add-hvs_dlist_allocs-debugfs-function.patch @@ -0,0 +1,64 @@ +From 665e9810340abc37769b317445907bac1843dd64 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 27 Oct 2023 16:46:04 +0100 +Subject: [PATCH] drm/vc4: Add hvs_dlist_allocs debugfs function. + +Users are reporting running out of DLIST memory. Add a +debugfs file to dump out all the allocations. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -347,6 +347,36 @@ static int vc5_hvs_debugfs_gamma(struct + return 0; + } + ++static int vc4_hvs_debugfs_dlist_allocs(struct seq_file *m, void *data) ++{ ++ struct drm_info_node *node = m->private; ++ struct drm_device *dev = node->minor->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ struct vc4_hvs *hvs = vc4->hvs; ++ struct drm_printer p = drm_seq_file_printer(m); ++ struct vc4_hvs_dlist_allocation *cur, *next; ++ struct drm_mm_node *mm_node; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&hvs->mm_lock, flags); ++ ++ drm_printf(&p, "Allocated nodes:\n"); ++ list_for_each_entry(mm_node, drm_mm_nodes(&hvs->dlist_mm), node_list) { ++ drm_printf(&p, "node [%08llx + %08llx]\n", mm_node->start, mm_node->size); ++ } ++ ++ drm_printf(&p, "Stale nodes:\n"); ++ list_for_each_entry_safe(cur, next, &hvs->stale_dlist_entries, node) { ++ drm_printf(&p, "node [%08llx + %08llx] channel %u frcnt %u\n", ++ cur->mm_node.start, cur->mm_node.size, cur->channel, ++ cur->target_frame_count); ++ } ++ ++ spin_unlock_irqrestore(&hvs->mm_lock, flags); ++ ++ return 0; ++} ++ + /* The filter kernel is composed of dwords each containing 3 9-bit + * signed integers packed next to each other. + */ +@@ -1602,6 +1632,11 @@ int vc4_hvs_debugfs_init(struct drm_mino + if (ret) + return ret; + ++ ret = vc4_debugfs_add_file(minor, "hvs_dlist_allocs", ++ vc4_hvs_debugfs_dlist_allocs, NULL); ++ if (ret) ++ return ret; ++ + ret = vc4_debugfs_add_regset32(minor, "hvs_regs", + &hvs->regset); + if (ret) diff --git a/target/linux/bcm27xx/patches-6.1/950-1071-drm-vc4-Log-the-size-of-the-dlist-allocation-that-wa.patch b/target/linux/bcm27xx/patches-6.1/950-1071-drm-vc4-Log-the-size-of-the-dlist-allocation-that-wa.patch new file mode 100644 index 0000000000..aa38b182ba --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1071-drm-vc4-Log-the-size-of-the-dlist-allocation-that-wa.patch @@ -0,0 +1,23 @@ +From 23ea21ef5f6efb3082c184843b35a2f8f2e4374c Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 31 Oct 2023 11:15:38 +0000 +Subject: [PATCH] drm/vc4: Log the size of the dlist allocation that was + attempted + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -659,7 +659,8 @@ vc4_hvs_alloc_dlist_entry(struct vc4_hvs + dlist_count); + spin_unlock_irqrestore(&hvs->mm_lock, flags); + if (ret) { +- drm_err(dev, "Failed to allocate DLIST entry: %d\n", ret); ++ drm_err(dev, "Failed to allocate DLIST entry. Requested size=%zu. ret=%d\n", ++ dlist_count, ret); + return ERR_PTR(ret); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1072-drm-vc4-crtc-Support-odd-horizontal-timings-on-BCM27.patch b/target/linux/bcm27xx/patches-6.1/950-1072-drm-vc4-crtc-Support-odd-horizontal-timings-on-BCM27.patch new file mode 100644 index 0000000000..a72e3b8e5b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1072-drm-vc4-crtc-Support-odd-horizontal-timings-on-BCM27.patch @@ -0,0 +1,104 @@ +From f9f480b04f1dc280bd4411477f5ee7336361367b Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Tue, 24 Oct 2023 16:20:42 +0100 +Subject: [PATCH] drm/vc4: crtc: Support odd horizontal timings on BCM2712 + +BCM2711 runs pixelvalve at two pixels per clock cycle which results +in an unfortunate limitation that odd horizontal timings are not +possible. This is apparent on the standard DMT mode of 1366x768@60 +which cannot be driven with correct timing. + +BCM2712 defaults to the same behaviour, but has a mode to support +odd timings. While internally it still runs at two pixels per clock, +setting the PV_VCONTROL_ODD_TIMING bit makes it appear externally +to behave as it is one pixel per clock. + +Switching to this mode fixes 1366x768@60 mode, and other custom +resultions with odd horizontal timings. + +Signed-off-by: Dom Cobley +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 12 ++++-------- + drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++-- + drivers/gpu/drm/vc4/vc4_regs.h | 1 + + 3 files changed, 7 insertions(+), 10 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -398,12 +398,6 @@ static void vc4_crtc_config_pv(struct dr + + vc4_crtc_pixelvalve_reset(crtc); + +- /* +- * NOTE: The BCM2712 has a H_OTE (Horizontal Odd Timing Enable) +- * bit that, when set, will allow to specify the timings in +- * pixels instead of cycles, thus allowing to specify odd +- * timings. +- */ + CRTC_WRITE(PV_HORZA, + VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc, + PV_HORZA_HBP) | +@@ -448,6 +442,7 @@ static void vc4_crtc_config_pv(struct dr + */ + CRTC_WRITE(PV_V_CONTROL, + PV_VCONTROL_CONTINUOUS | ++ (vc4->gen >= VC4_GEN_6 ? PV_VCONTROL_ODD_TIMING : 0) | + (is_dsi ? PV_VCONTROL_DSI : 0) | + PV_VCONTROL_INTERLACE | + (odd_field_first +@@ -459,6 +454,7 @@ static void vc4_crtc_config_pv(struct dr + } else { + CRTC_WRITE(PV_V_CONTROL, + PV_VCONTROL_CONTINUOUS | ++ (vc4->gen >= VC4_GEN_6 ? PV_VCONTROL_ODD_TIMING : 0) | + (is_dsi ? PV_VCONTROL_DSI : 0)); + CRTC_WRITE(PV_VSYNCD_EVEN, 0); + } +@@ -1334,7 +1330,7 @@ const struct vc4_pv_data bcm2712_pv0_dat + .hvs_output = 0, + }, + .fifo_depth = 64, +- .pixels_per_clock = 2, ++ .pixels_per_clock = 1, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_HDMI0, + }, +@@ -1347,7 +1343,7 @@ const struct vc4_pv_data bcm2712_pv1_dat + .hvs_output = 1, + }, + .fifo_depth = 64, +- .pixels_per_clock = 2, ++ .pixels_per_clock = 1, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_HDMI1, + }, +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -3958,7 +3958,7 @@ static const struct vc4_hdmi_variant bcm + PHY_LANE_2, + PHY_LANE_CK, + }, +- .unsupported_odd_h_timings = true, ++ .unsupported_odd_h_timings = false, + .external_irq_controller = true, + + .init_resources = vc5_hdmi_init_resources, +@@ -3985,7 +3985,7 @@ static const struct vc4_hdmi_variant bcm + PHY_LANE_2, + PHY_LANE_CK, + }, +- .unsupported_odd_h_timings = true, ++ .unsupported_odd_h_timings = false, + .external_irq_controller = true, + + .init_resources = vc5_hdmi_init_resources, +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -155,6 +155,7 @@ + # define PV_CONTROL_EN BIT(0) + + #define PV_V_CONTROL 0x04 ++# define PV_VCONTROL_ODD_TIMING BIT(29) + # define PV_VCONTROL_ODD_DELAY_MASK VC4_MASK(22, 6) + # define PV_VCONTROL_ODD_DELAY_SHIFT 6 + # define PV_VCONTROL_ODD_FIRST BIT(5) diff --git a/target/linux/bcm27xx/patches-6.1/950-1073-spi-dw-dma-Get-the-last-DMA-scoop-out-of-the-FIFO.patch b/target/linux/bcm27xx/patches-6.1/950-1073-spi-dw-dma-Get-the-last-DMA-scoop-out-of-the-FIFO.patch new file mode 100644 index 0000000000..caf8b1a462 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1073-spi-dw-dma-Get-the-last-DMA-scoop-out-of-the-FIFO.patch @@ -0,0 +1,41 @@ +From 686fe776309fba5cad642c40177d39bf1fb320b2 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 7 Nov 2023 14:49:47 +0000 +Subject: [PATCH] spi: dw-dma: Get the last DMA scoop out of the FIFO + +With a DMA FIFO threshold greater than 1 (encoded as 0), it is possible +for data in the FIFO to be inaccessible, causing the transfer to fail +after a timeout. If the transfer includes a transmission, reduce the +RX threshold when the TX completes, otherwise use 1 for the whole +transfer (inefficient, but not catastrophic at SPI data rates). + +See: https://github.com/raspberrypi/linux/issues/5696 + +Signed-off-by: Phil Elwell +--- + drivers/spi/spi-dw-dma.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-dw-dma.c ++++ b/drivers/spi/spi-dw-dma.c +@@ -275,8 +275,10 @@ static void dw_spi_dma_tx_done(void *arg + struct dw_spi *dws = arg; + + clear_bit(DW_SPI_TX_BUSY, &dws->dma_chan_busy); +- if (test_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy)) ++ if (test_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy)) { ++ dw_writel(dws, DW_SPI_DMARDLR, 0); + return; ++ } + + complete(&dws->dma_completion); + } +@@ -602,6 +604,8 @@ static int dw_spi_dma_transfer(struct dw + + nents = max(xfer->tx_sg.nents, xfer->rx_sg.nents); + ++ dw_writel(dws, DW_SPI_DMARDLR, xfer->tx_buf ? (dws->rxburst - 1) : 0); ++ + /* + * Execute normal DMA-based transfer (which submits the Rx and Tx SG + * lists directly to the DMA engine at once) if either full hardware diff --git a/target/linux/bcm27xx/patches-6.1/950-1075-drivers-mmc-sdhci-add-SPURIOUS_INT_RESP-quirk.patch b/target/linux/bcm27xx/patches-6.1/950-1075-drivers-mmc-sdhci-add-SPURIOUS_INT_RESP-quirk.patch new file mode 100644 index 0000000000..2ab224df05 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1075-drivers-mmc-sdhci-add-SPURIOUS_INT_RESP-quirk.patch @@ -0,0 +1,62 @@ +From 4d2261fe86ce08bbee3c000718000e9f86593d88 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 8 Nov 2023 11:52:16 +0000 +Subject: [PATCH] drivers: mmc: sdhci: add SPURIOUS_INT_RESP quirk + +Certain controllers (dwc-mshc) generate timeout conditions separately to +command-completion conditions, where the end result is interrupts are +separated in time depending on the current SDCLK frequency. + +This causes spurious interrupts if SDCLK is slow compared to the CPU's +ability to process and return from interrupt. This occurs during card +probe with an empty slot where all commands that would generate a +response time out. + +Add a quirk to squelch command response interrupts when a command +timeout interrupt is received. + +Signed-off-by: Jonathan Bell +--- + drivers/mmc/host/sdhci.c | 11 +++++++++++ + drivers/mmc/host/sdhci.h | 3 +++ + 2 files changed, 14 insertions(+) + +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -1728,6 +1728,12 @@ static bool sdhci_send_command(struct sd + if (host->use_external_dma) + sdhci_external_dma_pre_transfer(host, cmd); + ++ if (host->quirks2 & SDHCI_QUIRK2_SPURIOUS_INT_RESP) { ++ host->ier |= SDHCI_INT_RESPONSE; ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ } ++ + sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); + + return true; +@@ -3330,6 +3336,11 @@ static void sdhci_cmd_irq(struct sdhci_h + if (intmask & SDHCI_INT_TIMEOUT) { + host->cmd->error = -ETIMEDOUT; + sdhci_err_stats_inc(host, CMD_TIMEOUT); ++ if (host->quirks2 & SDHCI_QUIRK2_SPURIOUS_INT_RESP) { ++ host->ier &= ~SDHCI_INT_RESPONSE; ++ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); ++ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); ++ } + } else { + host->cmd->error = -EILSEQ; + if (!mmc_op_tuning(host->cmd->opcode)) +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -486,6 +486,9 @@ struct sdhci_host { + #define SDHCI_QUIRK2_NO_SDR50 (1<<20) + #define SDHCI_QUIRK2_NO_SDR104 (1<<21) + ++/* Command timeouts may generate a trailing INT_RESPONSE later */ ++#define SDHCI_QUIRK2_SPURIOUS_INT_RESP (1<<31) ++ + int irq; /* Device IRQ */ + void __iomem *ioaddr; /* Mapped address */ + phys_addr_t mapbase; /* physical address base */ diff --git a/target/linux/bcm27xx/patches-6.1/950-1076-dt-bindings-mmc-sdhci-of-dwcmhsc-Add-Raspberry-Pi-RP.patch b/target/linux/bcm27xx/patches-6.1/950-1076-dt-bindings-mmc-sdhci-of-dwcmhsc-Add-Raspberry-Pi-RP.patch new file mode 100644 index 0000000000..ffdc1b1c5d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1076-dt-bindings-mmc-sdhci-of-dwcmhsc-Add-Raspberry-Pi-RP.patch @@ -0,0 +1,42 @@ +From ebe13d0d4314255d226ba740e37a14172a8b9091 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 8 Nov 2023 16:10:13 +0000 +Subject: [PATCH] dt-bindings: mmc: sdhci-of-dwcmhsc: Add Raspberry Pi RP1 + support + +The DWC MSHC controller on RP1 needs differentiating from the generic +version. + +Signed-off-by: Jonathan Bell +--- + .../devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml ++++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml +@@ -16,6 +16,7 @@ allOf: + properties: + compatible: + enum: ++ - raspberrypi,rp1-dwcmshc + - rockchip,rk3568-dwcmshc + - rockchip,rk3588-dwcmshc + - snps,dwcmshc-sdhci +@@ -34,6 +35,8 @@ properties: + - description: axi clock for rockchip specified + - description: block clock for rockchip specified + - description: timer clock for rockchip specified ++ - description: timeout clock for rp1 specified ++ - description: sdio clock generator for rp1 specified + + + clock-names: +@@ -44,6 +47,8 @@ properties: + - const: axi + - const: block + - const: timer ++ - const: timeout ++ - const: sdio + + rockchip,txclk-tapnum: + description: Specify the number of delay for tx sampling. diff --git a/target/linux/bcm27xx/patches-6.1/950-1077-drivers-mmc-sdhci-of-dwcmshc-add-RP1-dt-ID-and-quirk.patch b/target/linux/bcm27xx/patches-6.1/950-1077-drivers-mmc-sdhci-of-dwcmshc-add-RP1-dt-ID-and-quirk.patch new file mode 100644 index 0000000000..54b719c6ec --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1077-drivers-mmc-sdhci-of-dwcmshc-add-RP1-dt-ID-and-quirk.patch @@ -0,0 +1,41 @@ +From 80dd8795ca631ac692fd3079487aea6d934a829c Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 8 Nov 2023 16:12:59 +0000 +Subject: [PATCH] drivers: mmc: sdhci-of-dwcmshc: add RP1 dt ID and quirks + +Differentiate the RP1 variant of the Designware MSHC controller(s). + +Signed-off-by: Jonathan Bell +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -373,6 +373,15 @@ static const struct sdhci_pltfm_data sdh + }; + #endif + ++static const struct sdhci_pltfm_data sdhci_dwcmshc_rp1_pdata = { ++ .ops = &sdhci_dwcmshc_ops, ++ .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | ++ SDHCI_QUIRK_BROKEN_CARD_DETECTION, ++ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | ++ SDHCI_QUIRK2_BROKEN_HS200 | ++ SDHCI_QUIRK2_SPURIOUS_INT_RESP, ++}; ++ + static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = { + .ops = &sdhci_dwcmshc_rk35xx_ops, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | +@@ -441,6 +450,10 @@ static void dwcmshc_rk35xx_postinit(stru + + static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { + { ++ .compatible = "raspberrypi,rp1-dwcmshc", ++ .data = &sdhci_dwcmshc_rp1_pdata, ++ }, ++ { + .compatible = "rockchip,rk3588-dwcmshc", + .data = &sdhci_dwcmshc_rk35xx_pdata, + }, diff --git a/target/linux/bcm27xx/patches-6.1/950-1078-arm-dts-change-RP1-SDHCI-controller-compatible-strin.patch b/target/linux/bcm27xx/patches-6.1/950-1078-arm-dts-change-RP1-SDHCI-controller-compatible-strin.patch new file mode 100644 index 0000000000..c708bf1f71 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1078-arm-dts-change-RP1-SDHCI-controller-compatible-strin.patch @@ -0,0 +1,104 @@ +From 51cdff455e3c3df29764f71bc0c9dd0e099945d6 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Wed, 8 Nov 2023 16:14:25 +0000 +Subject: [PATCH] arm: dts: change RP1 SDHCI controller compatible string + +Also add a sdio-pi5 overlay which enables mmc0 on GPIOs 22-27, as was +possible with earlier models of Pi. + +Signed-off-by: Jonathan Bell +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 7 ++++++ + arch/arm/boot/dts/overlays/overlay_map.dts | 4 ++++ + .../boot/dts/overlays/sdio-pi5-overlay.dts | 24 +++++++++++++++++++ + arch/arm/boot/dts/rp1.dtsi | 4 ++-- + 5 files changed, 38 insertions(+), 2 deletions(-) + create mode 100644 arch/arm/boot/dts/overlays/sdio-pi5-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -225,6 +225,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + sc16is752-spi1.dtbo \ + sdhost.dtbo \ + sdio.dtbo \ ++ sdio-pi5.dtbo \ + seeed-can-fd-hat-v1.dtbo \ + seeed-can-fd-hat-v2.dtbo \ + sh1106-spi.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -3932,6 +3932,13 @@ Info: This overlay is now deprecated. + Load: + + ++Name: sdio-pi5 ++Info: Selects the rp1_mmc0 interface and enables it on GPIOs 22-27. ++ Pi 5 only. ++Load: dtoverlay=sdio-pi5 ++Params: ++ ++ + Name: sdtweak + Info: This overlay is now deprecated. Use the sd_* dtparams in the + base DTB, e.g. "dtoverlay=sdtweak,poll_once" becomes +--- a/arch/arm/boot/dts/overlays/overlay_map.dts ++++ b/arch/arm/boot/dts/overlays/overlay_map.dts +@@ -250,6 +250,10 @@ + deprecated = "use sdio,bus_width=1,gpios_22_25"; + }; + ++ sdio-pi5 { ++ bcm2712; ++ }; ++ + sdtweak { + deprecated = "use 'dtparam=sd_poll_once' etc."; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/sdio-pi5-overlay.dts +@@ -0,0 +1,24 @@ ++/dts-v1/; ++/plugin/; ++ ++/* SDIO/SD/MMC on RP1 bank 0 */ ++ ++/{ ++ compatible = "brcm,bcm2712"; ++ ++ fragment@0 { ++ target = <&rp1_mmc0>; ++ frag0: __overlay__ { ++ status = "okay"; ++ pinctrl-0 = <&rp1_sdio0_22_27>; ++ pinctrl-names = "default"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&rp1_sdio_clk0>; ++ frag1: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/rp1.dtsi ++++ b/arch/arm/boot/dts/rp1.dtsi +@@ -962,7 +962,7 @@ + + rp1_mmc0: mmc@180000 { + reg = <0xc0 0x40180000 0x0 0x100>; +- compatible = "snps,dwcmshc-sdhci"; ++ compatible = "raspberrypi,rp1-dwcmshc"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core + &rp1_clocks RP1_CLK_SDIO_TIMER +@@ -978,7 +978,7 @@ + + rp1_mmc1: mmc@184000 { + reg = <0xc0 0x40184000 0x0 0x100>; +- compatible = "snps,dwcmshc-sdhci"; ++ compatible = "raspberrypi,rp1-dwcmshc"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core + &rp1_clocks RP1_CLK_SDIO_TIMER diff --git a/target/linux/bcm27xx/patches-6.1/950-1079-ASoC-bcm-audioinjector_octo-Add-soundcard-owner.patch b/target/linux/bcm27xx/patches-6.1/950-1079-ASoC-bcm-audioinjector_octo-Add-soundcard-owner.patch new file mode 100644 index 0000000000..aa025125e7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1079-ASoC-bcm-audioinjector_octo-Add-soundcard-owner.patch @@ -0,0 +1,22 @@ +From 020ee5029ab0b11e47696f538418105ccfdb44de Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 8 Nov 2023 19:17:33 +0000 +Subject: [PATCH] ASoC: bcm: audioinjector_octo: Add soundcard "owner" + +See: https://github.com/raspberrypi/linux/issues/5697 + +Signed-off-by: Phil Elwell +--- + sound/soc/bcm/audioinjector-octo-soundcard.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/soc/bcm/audioinjector-octo-soundcard.c ++++ b/sound/soc/bcm/audioinjector-octo-soundcard.c +@@ -252,6 +252,7 @@ static const struct snd_soc_dapm_route a + + static struct snd_soc_card snd_soc_audioinjector_octo = { + .name = "audioinjector-octo-soundcard", ++ .owner = THIS_MODULE, + .dai_link = audioinjector_octo_dai, + .num_links = ARRAY_SIZE(audioinjector_octo_dai), + diff --git a/target/linux/bcm27xx/patches-6.1/950-1080-drivers-media-imx708-Adjust-broken-line-correction-p.patch b/target/linux/bcm27xx/patches-6.1/950-1080-drivers-media-imx708-Adjust-broken-line-correction-p.patch new file mode 100644 index 0000000000..60f489c6c0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1080-drivers-media-imx708-Adjust-broken-line-correction-p.patch @@ -0,0 +1,139 @@ +From f364e0eb8f973e1aa24a3c451d18e84247a8efcd Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 8 Nov 2023 10:57:45 +0000 +Subject: [PATCH] drivers: media: imx708: Adjust broken line correction + parameter + +In full-resolution mode, the LPF_INTENSITY_EN and LPF_INTENSITY +registers control Quad Bayer Re-mosaic broken line correction. +Expose this as a module parameter "qbc_adjust": zero disables +the correction and values in the range 2 to 5 set its strength. + +There is a trade-off between coloured and monochrome patterns. +The previous fixed value 4 could produce ladder/spots artefacts +in coloured textures. The new default value 2 may suit a wider +range of scenes. + +Signed-off-by: Nick Hollinghurst +--- + drivers/media/i2c/imx708.c | 50 ++++++++++++++++++++++++++++++++------ + 1 file changed, 42 insertions(+), 8 deletions(-) + +--- a/drivers/media/i2c/imx708.c ++++ b/drivers/media/i2c/imx708.c +@@ -20,6 +20,14 @@ + #include + #include + ++/* ++ * Parameter to adjust Quad Bayer re-mosaic broken line correction ++ * strength, used in full-resolution mode only. Set zero to disable. ++ */ ++static int qbc_adjust = 2; ++module_param(qbc_adjust, int, 0644); ++MODULE_PARM_DESC(qbc_adjust, "Quad Bayer broken line correction strength [0,2-5]"); ++ + #define IMX708_REG_VALUE_08BIT 1 + #define IMX708_REG_VALUE_16BIT 2 + +@@ -99,11 +107,17 @@ + + /* HDR exposure ratio (long:med == med:short) */ + #define IMX708_HDR_EXPOSURE_RATIO 4 +-#define IMX708_REG_MID_EXPOSURE 0x3116 +-#define IMX708_REG_SHT_EXPOSURE 0x0224 ++#define IMX708_REG_MID_EXPOSURE 0x3116 ++#define IMX708_REG_SHT_EXPOSURE 0x0224 + #define IMX708_REG_MID_ANALOG_GAIN 0x3118 + #define IMX708_REG_SHT_ANALOG_GAIN 0x0216 + ++/* QBC Re-mosaic broken line correction registers */ ++#define IMX708_LPF_INTENSITY_EN 0xC428 ++#define IMX708_LPF_INTENSITY_ENABLED 0x00 ++#define IMX708_LPF_INTENSITY_DISABLED 0x01 ++#define IMX708_LPF_INTENSITY 0xC429 ++ + /* + * Metadata buffer holds a variety of data, all sent with the same VC/DT (0x12). + * It comprises two scanlines (of up to 5760 bytes each, for 4608 pixels) +@@ -171,6 +185,9 @@ struct imx708_mode { + + /* HDR flag, used for checking if the current mode is HDR */ + bool hdr; ++ ++ /* Quad Bayer Re-mosaic flag */ ++ bool remosaic; + }; + + /* Default PDAF pixel correction gains */ +@@ -363,8 +380,6 @@ static const struct imx708_reg mode_4608 + {0x341f, 0x20}, + {0x3420, 0x00}, + {0x3421, 0xd8}, +- {0xC428, 0x00}, +- {0xC429, 0x04}, + {0x3366, 0x00}, + {0x3367, 0x00}, + {0x3368, 0x00}, +@@ -677,7 +692,8 @@ static const struct imx708_mode supporte + .pixel_rate = 595200000, + .exposure_lines_min = 8, + .exposure_lines_step = 1, +- .hdr = false ++ .hdr = false, ++ .remosaic = true + }, + { + /* regular 2x2 binned. */ +@@ -699,7 +715,8 @@ static const struct imx708_mode supporte + .pixel_rate = 585600000, + .exposure_lines_min = 4, + .exposure_lines_step = 2, +- .hdr = false ++ .hdr = false, ++ .remosaic = false + }, + { + /* 2x2 binned and cropped for 720p. */ +@@ -721,7 +738,8 @@ static const struct imx708_mode supporte + .pixel_rate = 566400000, + .exposure_lines_min = 4, + .exposure_lines_step = 2, +- .hdr = false ++ .hdr = false, ++ .remosaic = false + }, + }; + +@@ -746,7 +764,8 @@ static const struct imx708_mode supporte + .pixel_rate = 777600000, + .exposure_lines_min = 8 * IMX708_HDR_EXPOSURE_RATIO * IMX708_HDR_EXPOSURE_RATIO, + .exposure_lines_step = 2 * IMX708_HDR_EXPOSURE_RATIO * IMX708_HDR_EXPOSURE_RATIO, +- .hdr = true ++ .hdr = true, ++ .remosaic = false + } + }; + +@@ -1515,6 +1534,21 @@ static int imx708_start_streaming(struct + return ret; + } + ++ /* Quad Bayer re-mosaic adjustments (for full-resolution mode only) */ ++ if (imx708->mode->remosaic && qbc_adjust > 0) { ++ imx708_write_reg(imx708, IMX708_LPF_INTENSITY, ++ IMX708_REG_VALUE_08BIT, qbc_adjust); ++ imx708_write_reg(imx708, ++ IMX708_LPF_INTENSITY_EN, ++ IMX708_REG_VALUE_08BIT, ++ IMX708_LPF_INTENSITY_ENABLED); ++ } else { ++ imx708_write_reg(imx708, ++ IMX708_LPF_INTENSITY_EN, ++ IMX708_REG_VALUE_08BIT, ++ IMX708_LPF_INTENSITY_DISABLED); ++ } ++ + /* Apply customized values from user */ + ret = __v4l2_ctrl_handler_setup(imx708->sd.ctrl_handler); + if (ret) diff --git a/target/linux/bcm27xx/patches-6.1/950-1082-drivers-media-cfe-Don-t-confuse-MHz-and-Mbps.patch b/target/linux/bcm27xx/patches-6.1/950-1082-drivers-media-cfe-Don-t-confuse-MHz-and-Mbps.patch new file mode 100644 index 0000000000..ea0ea396ba --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1082-drivers-media-cfe-Don-t-confuse-MHz-and-Mbps.patch @@ -0,0 +1,96 @@ +From 65407c54fb4119e528b70b329448269657e0941e Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 8 Nov 2023 10:05:05 +0000 +Subject: [PATCH] drivers: media: cfe: Don't confuse MHz and Mbps + +The driver was interchaning these units when talking about link rate. +Fix this to avoid confusion. Apart from the logging message change, +there is no function change in this commit. + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 8 ++++---- + drivers/media/platform/raspberrypi/rp1_cfe/dphy.c | 10 +++++----- + drivers/media/platform/raspberrypi/rp1_cfe/dphy.h | 2 +- + 3 files changed, 10 insertions(+), 10 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -983,7 +983,7 @@ static void cfe_buffer_queue(struct vb2_ + spin_unlock_irqrestore(&cfe->state_lock, flags); + } + +-static u64 sensor_link_frequency(struct cfe_device *cfe) ++static u64 sensor_link_rate(struct cfe_device *cfe) + { + struct v4l2_mbus_framefmt *source_fmt; + struct v4l2_subdev_state *state; +@@ -1028,11 +1028,11 @@ static u64 sensor_link_frequency(struct + + /* x2 for DDR. */ + link_freq *= 2; +- cfe_info("Using a link frequency of %lld Hz\n", link_freq); ++ cfe_info("Using a link rate of %lld Mbps\n", link_freq / (1000 * 1000)); + return link_freq; + + err: +- cfe_err("Unable to determine sensor link frequency, using 999 MHz\n"); ++ cfe_err("Unable to determine sensor link rate, using 999 Mbps\n"); + return 999 * 1000000UL; + } + +@@ -1104,7 +1104,7 @@ static int cfe_start_streaming(struct vb + } + + cfe_dbg("Configuring CSI-2 block\n"); +- cfe->csi2.dphy.dphy_freq = sensor_link_frequency(cfe) / 1000000UL; ++ cfe->csi2.dphy.dphy_rate = sensor_link_rate(cfe) / 1000000UL; + csi2_open_rx(&cfe->csi2); + + cfe_dbg("Starting sensor streaming\n"); +--- a/drivers/media/platform/raspberrypi/rp1_cfe/dphy.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.c +@@ -96,7 +96,7 @@ static uint8_t dphy_transaction(struct d + return get_tstdout(dphy); + } + +-static void dphy_set_hsfreqrange(struct dphy_data *dphy, uint32_t freq_mhz) ++static void dphy_set_hsfreqrange(struct dphy_data *dphy, uint32_t mbps) + { + /* See Table 5-1 on page 65 of dphy databook */ + static const u16 hsfreqrange_table[][2] = { +@@ -116,11 +116,11 @@ static void dphy_set_hsfreqrange(struct + }; + unsigned int i; + +- if (freq_mhz < 80 || freq_mhz > 1500) +- dphy_err("DPHY: Frequency %u MHz out of range\n", freq_mhz); ++ if (mbps < 80 || mbps > 1500) ++ dphy_err("DPHY: Datarate %u Mbps out of range\n", mbps); + + for (i = 0; i < ARRAY_SIZE(hsfreqrange_table) - 1; i++) { +- if (freq_mhz <= hsfreqrange_table[i][0]) ++ if (mbps <= hsfreqrange_table[i][0]) + break; + } + +@@ -139,7 +139,7 @@ static void dphy_init(struct dphy_data * + set_tstclr(dphy, 0); + usleep_range(15, 20); + +- dphy_set_hsfreqrange(dphy, dphy->dphy_freq); ++ dphy_set_hsfreqrange(dphy, dphy->dphy_rate); + + usleep_range(5, 10); + dw_csi2_host_write(dphy, PHY_SHUTDOWNZ, 1); +--- a/drivers/media/platform/raspberrypi/rp1_cfe/dphy.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/dphy.h +@@ -15,7 +15,7 @@ struct dphy_data { + + void __iomem *base; + +- u32 dphy_freq; ++ u32 dphy_rate; + u32 num_lanes; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1083-overlays-imx296-Fix-cam-port-override-for-regulators.patch b/target/linux/bcm27xx/patches-6.1/950-1083-overlays-imx296-Fix-cam-port-override-for-regulators.patch new file mode 100644 index 0000000000..1b6d2041f1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1083-overlays-imx296-Fix-cam-port-override-for-regulators.patch @@ -0,0 +1,25 @@ +From 6137fb168c08bd8c41c8421bf26f09ed29479f08 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 15 Nov 2023 08:25:11 +0000 +Subject: [PATCH] overlays: imx296: Fix cam port override for regulators + +The override was missing/incorrect for the regulator labels. + +Signed-off-by: Naushir Patuck +--- + arch/arm/boot/dts/overlays/imx296-overlay.dts | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/overlays/imx296-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx296-overlay.dts +@@ -97,8 +97,9 @@ + cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, ++ <®_frag>, "target:0=",<&cam0_reg>, + <&imx296>, "clocks:0=",<&cam0_clk>, +- <&imx296>, "VANA-supply:0=",<&cam0_reg>; ++ <&imx296>, "avdd-supply:0=",<&cam0_reg>; + clock-frequency = <&clk_over>, "clock-frequency:0"; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1148-overlays-ov5647-Regularise-vcm-node-label-name.patch b/target/linux/bcm27xx/patches-6.1/950-1148-overlays-ov5647-Regularise-vcm-node-label-name.patch new file mode 100644 index 0000000000..28017989a9 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1148-overlays-ov5647-Regularise-vcm-node-label-name.patch @@ -0,0 +1,32 @@ +From 7443b602cb503b42dd0ae8e957e26decb420d632 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 20 Nov 2023 10:15:15 +0000 +Subject: [PATCH] overlays: ov5647: Regularise vcm node label name + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/ov5647-overlay.dts | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts +@@ -15,7 +15,7 @@ + + #include "ov5647.dtsi" + +- vcm: ad5398@c { ++ vcm_node: ad5398@c { + compatible = "adi,ad5398"; + reg = <0x0c>; + status = "disabled"; +@@ -78,8 +78,8 @@ + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, + <&cam_node>, "avdd-supply:0=",<&cam0_reg>; +- vcm = <&vcm>, "status=okay", +- <&cam_node>,"lens-focus:0=", <&vcm>; ++ vcm = <&vcm_node>, "status=okay", ++ <&cam_node>,"lens-focus:0=", <&vcm_node>; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1149-overlays-ov5647-cam0-mode-should-use-cam0_reg.patch b/target/linux/bcm27xx/patches-6.1/950-1149-overlays-ov5647-cam0-mode-should-use-cam0_reg.patch new file mode 100644 index 0000000000..f079756133 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1149-overlays-ov5647-cam0-mode-should-use-cam0_reg.patch @@ -0,0 +1,27 @@ +From d484bef133af9c87d64899fc1e1d0be2a7c7785b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 20 Nov 2023 10:16:10 +0000 +Subject: [PATCH] overlays: ov5647: cam0 mode should use cam0_reg + +When the cam0 parameter is used, the vcm should be updated to refer to +the cam0 regulator. + +See: https://github.com/raspberrypi/linux/issues/5722 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/ov5647-overlay.dts | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/overlays/ov5647-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ov5647-overlay.dts +@@ -77,7 +77,8 @@ + <®_frag>, "target:0=",<&cam0_reg>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <&cam_node>, "clocks:0=",<&cam0_clk>, +- <&cam_node>, "avdd-supply:0=",<&cam0_reg>; ++ <&cam_node>, "avdd-supply:0=",<&cam0_reg>, ++ <&vcm_node>, "VANA-supply:0=",<&cam0_reg>; + vcm = <&vcm_node>, "status=okay", + <&cam_node>,"lens-focus:0=", <&vcm_node>; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1150-w1-Disable-kernel-log-spam.patch b/target/linux/bcm27xx/patches-6.1/950-1150-w1-Disable-kernel-log-spam.patch new file mode 100644 index 0000000000..457a0e9ec5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1150-w1-Disable-kernel-log-spam.patch @@ -0,0 +1,25 @@ +From 0924b74687bd195b98f223814ff88b4227654e85 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 20 Nov 2023 14:46:14 +0000 +Subject: [PATCH] w1: Disable kernel log spam + +See: https://forums.raspberrypi.com/viewtopic.php?p=2159344 + +Signed-off-by: Phil Elwell +--- + drivers/w1/w1.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/w1/w1.c ++++ b/drivers/w1/w1.c +@@ -742,8 +742,10 @@ int w1_attach_slave_device(struct w1_mas + atomic_set(&sl->refcnt, 1); + atomic_inc(&sl->master->refcnt); + dev->slave_count++; ++#if 0 + dev_info(&dev->dev, "Attaching one wire slave %02x.%012llx crc %02x\n", + rn->family, (unsigned long long)rn->id, rn->crc); ++#endif + + /* slave modules need to be loaded in a context with unlocked mutex */ + mutex_unlock(&dev->mutex); diff --git a/target/linux/bcm27xx/patches-6.1/950-1151-include-uapi-mbus-Add-a-media-bus-format-enum-for-16.patch b/target/linux/bcm27xx/patches-6.1/950-1151-include-uapi-mbus-Add-a-media-bus-format-enum-for-16.patch new file mode 100644 index 0000000000..b8933bcbb6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1151-include-uapi-mbus-Add-a-media-bus-format-enum-for-16.patch @@ -0,0 +1,21 @@ +From be8ca764e0530ec8ac18ca03c49e3cda13562d3a Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Thu, 16 Nov 2023 14:21:05 +0000 +Subject: [PATCH] include: uapi: mbus: Add a media bus format enum for 16-bit + mono output + +Signed-off-by: Naushir Patuck +--- + include/uapi/linux/media-bus-format.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/include/uapi/linux/media-bus-format.h ++++ b/include/uapi/linux/media-bus-format.h +@@ -95,6 +95,7 @@ + #define MEDIA_BUS_FMT_YUYV12_2X12 0x201e + #define MEDIA_BUS_FMT_YVYU12_2X12 0x201f + #define MEDIA_BUS_FMT_Y14_1X14 0x202d ++#define MEDIA_BUS_FMT_Y16_1X16 0x202e + #define MEDIA_BUS_FMT_UYVY8_1X16 0x200f + #define MEDIA_BUS_FMT_VYUY8_1X16 0x2010 + #define MEDIA_BUS_FMT_YUYV8_1X16 0x2011 diff --git a/target/linux/bcm27xx/patches-6.1/950-1152-include-uapi-v4l2-Add-additional-pixel-formats-for-u.patch b/target/linux/bcm27xx/patches-6.1/950-1152-include-uapi-v4l2-Add-additional-pixel-formats-for-u.patch new file mode 100644 index 0000000000..56855184be --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1152-include-uapi-v4l2-Add-additional-pixel-formats-for-u.patch @@ -0,0 +1,73 @@ +From 9abab2e8e5cfbeae6e1b33cc3a5ed773e4e31774 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Thu, 16 Nov 2023 14:25:39 +0000 +Subject: [PATCH] include: uapi: v4l2: Add additional pixel formats for use + with PiSP + +Add the following formats: + +- V4L2_PIX_FMT_RGB48/V4L2_PIX_FMT_BGR48 + 48-bit RGB where each colour sample is 16-bits. + +- V4L2_PIX_FMT_PISP_COMP1_MONO/V4L2_PIX_FMT_PISP_COMP2_MONO + 16-bit to 8-bit pisp compressed monochrome pixel format. + +Signed-off-by: Naushir Patuck +--- + drivers/media/v4l2-core/v4l2-ioctl.c | 8 ++++++-- + include/uapi/linux/videodev2.h | 6 ++++++ + 2 files changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -1304,6 +1304,8 @@ static void v4l_fill_fmtdesc(struct v4l2 + case V4L2_PIX_FMT_BGRX32: descr = "32-bit XBGR 8-8-8-8"; break; + case V4L2_PIX_FMT_RGBA32: descr = "32-bit RGBA 8-8-8-8"; break; + case V4L2_PIX_FMT_RGBX32: descr = "32-bit RGBX 8-8-8-8"; break; ++ case V4L2_PIX_FMT_BGR48: descr = "48-bit BGR 16-16-16"; break; ++ case V4L2_PIX_FMT_RGB48: descr = "48-bit RGB 16-16-16"; break; + case V4L2_PIX_FMT_GREY: descr = "8-bit Greyscale"; break; + case V4L2_PIX_FMT_Y4: descr = "4-bit Greyscale"; break; + case V4L2_PIX_FMT_Y6: descr = "6-bit Greyscale"; break; +@@ -1510,11 +1512,13 @@ static void v4l_fill_fmtdesc(struct v4l2 + 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_COMP1_BGGR: ++ case V4L2_PIX_FMT_PISP_COMP1_MONO: 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; ++ case V4L2_PIX_FMT_PISP_COMP2_BGGR: ++ case V4L2_PIX_FMT_PISP_COMP2_MONO: descr = "PiSP Bayer Comp 2"; break; + default: + if (fmt->description[0]) + return; +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -582,6 +582,10 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_ARGB32 v4l2_fourcc('B', 'A', '2', '4') /* 32 ARGB-8-8-8-8 */ + #define V4L2_PIX_FMT_XRGB32 v4l2_fourcc('B', 'X', '2', '4') /* 32 XRGB-8-8-8-8 */ + ++/* RGB formats (6 bytes per pixel) */ ++#define V4L2_PIX_FMT_BGR48 v4l2_fourcc('B', 'G', 'R', '6') /* 16 BGR-16-16-16 */ ++#define V4L2_PIX_FMT_RGB48 v4l2_fourcc('R', 'G', 'B', '6') /* 16 RGB-16-16-16 */ ++ + /* Grey formats */ + #define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */ + #define V4L2_PIX_FMT_Y4 v4l2_fourcc('Y', '0', '4', ' ') /* 4 Greyscale */ +@@ -799,10 +803,12 @@ struct v4l2_pix_format { + #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_COMP1_MONO v4l2_fourcc('P', 'C', '1', 'M') + #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') ++#define V4L2_PIX_FMT_PISP_COMP2_MONO v4l2_fourcc('P', 'C', '2', 'M') + + /* SDR formats - used only for Software Defined Radio devices */ + #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ diff --git a/target/linux/bcm27xx/patches-6.1/950-1153-drivers-media-cfe-Add-16-bit-and-compressed-mono-for.patch b/target/linux/bcm27xx/patches-6.1/950-1153-drivers-media-cfe-Add-16-bit-and-compressed-mono-for.patch new file mode 100644 index 0000000000..607f23eeb3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1153-drivers-media-cfe-Add-16-bit-and-compressed-mono-for.patch @@ -0,0 +1,52 @@ +From 88d06a674009ad5b77234537527a800e6e0e88a3 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Thu, 16 Nov 2023 14:28:55 +0000 +Subject: [PATCH] drivers: media: cfe: Add 16-bit and compressed mono format + support + +Signed-off-by: Naushir Patuck +--- + .../media/platform/raspberrypi/rp1_cfe/cfe_fmts.h | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h +@@ -249,28 +249,34 @@ static const struct cfe_fmt formats[] = + .code = MEDIA_BUS_FMT_Y10_1X10, + .depth = 10, + .csi_dt = 0x2b, +- .remap = { V4L2_PIX_FMT_Y16 }, ++ .remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO }, + }, + { + .fourcc = V4L2_PIX_FMT_Y12P, + .code = MEDIA_BUS_FMT_Y12_1X12, + .depth = 12, + .csi_dt = 0x2c, +- .remap = { V4L2_PIX_FMT_Y16 }, ++ .remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO }, + }, + { + .fourcc = V4L2_PIX_FMT_Y14P, + .code = MEDIA_BUS_FMT_Y14_1X14, + .depth = 14, + .csi_dt = 0x2d, +- .remap = { V4L2_PIX_FMT_Y16 }, ++ .remap = { V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_PISP_COMP1_MONO }, + }, + { + .fourcc = V4L2_PIX_FMT_Y16, ++ .code = MEDIA_BUS_FMT_Y16_1X16, + .depth = 16, + .flags = CFE_FORMAT_FLAG_FE_OUT, + }, +- ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_MONO, ++ .code = MEDIA_BUS_FMT_Y16_1X16, ++ .depth = 8, ++ .flags = CFE_FORMAT_FLAG_FE_OUT, ++ }, + /* Embedded data format */ + { + .fourcc = V4L2_META_FMT_SENSOR_DATA, diff --git a/target/linux/bcm27xx/patches-6.1/950-1154-drivers-media-pisp_be-Add-mono-and-48-bit-RGB-pixel-.patch b/target/linux/bcm27xx/patches-6.1/950-1154-drivers-media-pisp_be-Add-mono-and-48-bit-RGB-pixel-.patch new file mode 100644 index 0000000000..2ea4abd112 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1154-drivers-media-pisp_be-Add-mono-and-48-bit-RGB-pixel-.patch @@ -0,0 +1,72 @@ +From 2affda8d2b172aa0fd22778983d983fc9522e621 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Thu, 16 Nov 2023 14:29:47 +0000 +Subject: [PATCH] drivers: media: pisp_be: Add mono and 48-bit RGB pixel format + support + +Signed-off-by: Naushir Patuck +--- + .../raspberrypi/pisp_be/pisp_be_formats.h | 45 +++++++++++++++++++ + 1 file changed, 45 insertions(+) + +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h +@@ -234,6 +234,24 @@ static const struct pisp_be_format suppo + .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, + .colorspace_default = V4L2_COLORSPACE_SRGB, + }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB48, ++ .align = 64, ++ .bit_depth = 48, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_BGR48, ++ .align = 64, ++ .bit_depth = 48, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, ++ .colorspace_default = V4L2_COLORSPACE_SRGB, ++ }, + /* Bayer formats - 8-bit */ + { + .fourcc = V4L2_PIX_FMT_SRGGB8, +@@ -457,6 +475,33 @@ static const struct pisp_be_format suppo + .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, + .colorspace_default = V4L2_COLORSPACE_RAW, + }, ++ /* Greyscale Formats */ ++ { ++ .fourcc = V4L2_PIX_FMT_GREY, ++ .bit_depth = 8, ++ .align = 32, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_Y16, ++ .bit_depth = 16, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_PISP_COMP1_MONO, ++ .bit_depth = 8, ++ .align = 32, ++ .plane_factor = { P3(1.0) }, ++ .num_planes = 1, ++ .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, ++ .colorspace_default = V4L2_COLORSPACE_RAW, ++ }, + /* Opaque BE format for HW verification. */ + { + .fourcc = V4L2_PIX_FMT_RPI_BE, diff --git a/target/linux/bcm27xx/patches-6.1/950-1155-ASoC-dwc-Remove-check-in-set_bclk_ratio-handling.patch b/target/linux/bcm27xx/patches-6.1/950-1155-ASoC-dwc-Remove-check-in-set_bclk_ratio-handling.patch new file mode 100644 index 0000000000..88bb61a4c3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1155-ASoC-dwc-Remove-check-in-set_bclk_ratio-handling.patch @@ -0,0 +1,32 @@ +From 52545628c07be2fd1c9df598a17130d92f12da23 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 20 Nov 2023 15:17:34 +0000 +Subject: [PATCH] ASoC: dwc: Remove check in set_bclk_ratio handling + +A check added to dw_i2s_set_bclk_ratio that the data format is +consistent with the ratio seems reasonable but breaks when the +ratio is changed before the format. Remove the check - it is +unnecessary. + +See: https://github.com/raspberrypi/linux/issues/5724 +Fixes: 9c6694c24f26 ("ASOC: dwc: Fix 16-bit audio handling") + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -427,11 +427,8 @@ static int dw_i2s_set_bclk_ratio(struct + unsigned int ratio) + { + struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); +- struct i2s_clk_config_data *config = &dev->config; + + dev_dbg(dev->dev, "%s(%d)\n", __func__, ratio); +- if (ratio < config->data_width * 2) +- return -EINVAL; + + switch (ratio) { + case 32: diff --git a/target/linux/bcm27xx/patches-6.1/950-1159-overlays-README-Fix-cut-and-paste-errors.patch b/target/linux/bcm27xx/patches-6.1/950-1159-overlays-README-Fix-cut-and-paste-errors.patch new file mode 100644 index 0000000000..30cc82b0cd --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1159-overlays-README-Fix-cut-and-paste-errors.patch @@ -0,0 +1,39 @@ +From 5a0aa24b8ff58ceaf98c62670156bef7f48ed32b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 21 Nov 2023 15:08:38 +0000 +Subject: [PATCH] overlays: README: Fix cut-and-paste errors + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/README | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -1673,7 +1673,7 @@ Params: 24db_digital_gain Allow ga + responsibility of the user to ensure that + the Digital volume control is set to a value + that does not result in clipping/distortion!) +- slave Force DAC+ Pro into slave mode, using Pi as ++ slave Force AMP100 into slave mode, using Pi as + master for bit clock and frame clock. + leds_off If set to 'true' the onboard indicator LEDs + are switched off at all times. +@@ -1713,7 +1713,7 @@ Params: 24db_digital_gain Allow ga + responsibility of the user to ensure that + the Digital volume control is set to a value + that does not result in clipping/distortion!) +- slave Force DAC+ Pro into slave mode, using Pi as ++ slave Force DAC+ into slave mode, using Pi as + master for bit clock and frame clock. + leds_off If set to 'true' the onboard indicator LEDs + are switched off at all times. +@@ -1736,7 +1736,7 @@ Params: 24db_digital_gain Allow ga + responsibility of the user to ensure that + the Digital volume control is set to a value + that does not result in clipping/distortion!) +- slave Force DAC+ Pro into slave mode, using Pi as ++ slave Force DAC+ADC into slave mode, using Pi as + master for bit clock and frame clock. + leds_off If set to 'true' the onboard indicator LEDs + are switched off at all times. diff --git a/target/linux/bcm27xx/patches-6.1/950-1160-media-i2c-ov7251-Switch-from-V4L2_CID_GAIN-to-V4L2_C.patch b/target/linux/bcm27xx/patches-6.1/950-1160-media-i2c-ov7251-Switch-from-V4L2_CID_GAIN-to-V4L2_C.patch new file mode 100644 index 0000000000..36565bf2d6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1160-media-i2c-ov7251-Switch-from-V4L2_CID_GAIN-to-V4L2_C.patch @@ -0,0 +1,38 @@ +From e60fbc34aa98b3ba2c9338ad628fc8d8137e9065 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 14 Nov 2023 18:36:19 +0000 +Subject: [PATCH] media/i2c: ov7251: Switch from V4L2_CID_GAIN to + V4L2_CID_ANALOGUE_GAIN + +The mainline driver has implemented analogue gain using the control +V4L2_CID_GAIN instead of V4L2_CID_ANALOGUE_GAIN. + +libcamera requires V4L2_CID_ANALOGUE_GAIN, and therefore fails. + +Update the driver to use V4L2_CID_ANALOGUE_GAIN. + +Signed-off-by: Dave Stevenson +--- + drivers/media/i2c/ov7251.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/i2c/ov7251.c ++++ b/drivers/media/i2c/ov7251.c +@@ -1063,7 +1063,7 @@ static int ov7251_s_ctrl(struct v4l2_ctr + case V4L2_CID_EXPOSURE: + ret = ov7251_set_exposure(ov7251, ctrl->val); + break; +- case V4L2_CID_GAIN: ++ case V4L2_CID_ANALOGUE_GAIN: + ret = ov7251_set_gain(ov7251, ctrl->val); + break; + case V4L2_CID_TEST_PATTERN: +@@ -1588,7 +1588,7 @@ static int ov7251_init_ctrls(struct ov72 + ov7251->exposure = v4l2_ctrl_new_std(&ov7251->ctrls, &ov7251_ctrl_ops, + V4L2_CID_EXPOSURE, 1, 32, 1, 32); + ov7251->gain = v4l2_ctrl_new_std(&ov7251->ctrls, &ov7251_ctrl_ops, +- V4L2_CID_GAIN, 16, 1023, 1, 16); ++ V4L2_CID_ANALOGUE_GAIN, 16, 1023, 1, 16); + v4l2_ctrl_new_std_menu_items(&ov7251->ctrls, &ov7251_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(ov7251_test_pattern_menu) - 1, diff --git a/target/linux/bcm27xx/patches-6.1/950-1161-drm-vc4-Drop-planes-that-are-completely-off-screen.patch b/target/linux/bcm27xx/patches-6.1/950-1161-drm-vc4-Drop-planes-that-are-completely-off-screen.patch new file mode 100644 index 0000000000..8cdbb51d55 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1161-drm-vc4-Drop-planes-that-are-completely-off-screen.patch @@ -0,0 +1,63 @@ +From 444884f7b62bfe5ef313dd1d47f81a40e695ab0b Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 17 Nov 2023 14:43:44 +0000 +Subject: [PATCH] drm/vc4: Drop planes that are completely off-screen + +It is permitted for a plane to be configured such that none +of it is on-screen via either negative dest rectangle X,Y +offset, or just an offset that is greater than the crtc +dimensions. + +These planes were resized via drm_atomic_helper_check_plane_state +such that the source rectangle had a zero width or height, but +they still created a dlist entry even though they contributed +no pixels. In the case of vc6_plane_mode_set, that it could result +in negative values being written into registers, which caused +incorrect behaviour. + +Drop planes that result in a source width or height of 0 pixels +to avoid the incorrect rendering. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -1108,6 +1108,12 @@ static int vc4_plane_mode_set(struct drm + width = vc4_state->src_w[0] >> 16; + height = vc4_state->src_h[0] >> 16; + ++ if (!width || !height) { ++ /* 0 source size probably means the plane is offscreen */ ++ vc4_state->dlist_initialized = 1; ++ return 0; ++ } ++ + /* SCL1 is used for Cb/Cr scaling of planar formats. For RGB + * and 4:4:4, scl1 should be set to scl0 so both channels of + * the scaler do the same thing. For YUV, the Y plane needs +@@ -1623,6 +1629,12 @@ static int vc6_plane_mode_set(struct drm + width = vc4_state->src_w[0] >> 16; + height = vc4_state->src_h[0] >> 16; + ++ if (!width || !height) { ++ /* 0 source size probably means the plane is offscreen */ ++ vc4_state->dlist_initialized = 1; ++ return 0; ++ } ++ + /* SCL1 is used for Cb/Cr scaling of planar formats. For RGB + * and 4:4:4, scl1 should be set to scl0 so both channels of + * the scaler do the same thing. For YUV, the Y plane needs +@@ -1994,6 +2006,9 @@ int vc4_plane_atomic_check(struct drm_pl + if (ret) + return ret; + ++ if (!vc4_state->src_w[0] || !vc4_state->src_h[0]) ++ return 0; ++ + ret = vc4_plane_allocate_lbm(new_plane_state); + if (ret) + return ret; diff --git a/target/linux/bcm27xx/patches-6.1/950-1162-drm-bridge-display-connector-Select-DRM_KMS_HELPER.patch b/target/linux/bcm27xx/patches-6.1/950-1162-drm-bridge-display-connector-Select-DRM_KMS_HELPER.patch new file mode 100644 index 0000000000..270975e587 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1162-drm-bridge-display-connector-Select-DRM_KMS_HELPER.patch @@ -0,0 +1,29 @@ +From 91ad217f93232fb3a0b52487fec67860fb29e93a Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 17 Nov 2023 14:50:11 +0000 +Subject: [PATCH] drm/bridge: display-connector: Select DRM_KMS_HELPER + +Commit 7cd70656d128 ("drm/bridge: display-connector: implement +bus fmts callbacks") added use of drm_atomic_helper_bridge_* +functions, but didn't select the dependency of DRM_KMS_HELPER. +If nothing else selected that dependency it resulted in a +build failure. + +Select the missing dependency. + +Fixes: 7cd70656d128 ("drm/bridge: display-connector: implement bus fmts callbacks") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/bridge/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/bridge/Kconfig ++++ b/drivers/gpu/drm/bridge/Kconfig +@@ -67,6 +67,7 @@ config DRM_CROS_EC_ANX7688 + config DRM_DISPLAY_CONNECTOR + tristate "Display connector support" + depends on OF ++ select DRM_KMS_HELPER + help + Driver for display connectors with support for DDC and hot-plug + detection. Most display controllers handle display connectors diff --git a/target/linux/bcm27xx/patches-6.1/950-1163-drm-vc4-Free-the-dlist-alloc-immediately-if-it-never.patch b/target/linux/bcm27xx/patches-6.1/950-1163-drm-vc4-Free-the-dlist-alloc-immediately-if-it-never.patch new file mode 100644 index 0000000000..49359362fe --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1163-drm-vc4-Free-the-dlist-alloc-immediately-if-it-never.patch @@ -0,0 +1,56 @@ +From 51712a6493bf8824419f51ca7950e7d88f48b699 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 22 Nov 2023 18:36:54 +0000 +Subject: [PATCH] drm: vc4: Free the dlist alloc immediately if it never hit + the hw + +atomic_check creates a state, and allocates the dlist memory for +it such that atomic_flush can not fail. + +On destroy that dlist allocation was being put in the stale list, +even though it had never been programmed into the hardware, +therefore doing lots of atomic_checks could consume all the dlist +memory and fail. + +If the dlist has never been programmed into the hardware, then +free it immediately. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_hvs.c | 6 +++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -696,6 +696,7 @@ struct vc4_hvs_dlist_allocation { + struct drm_mm_node mm_node; + unsigned int channel; + u8 target_frame_count; ++ bool dlist_programmed; + }; + + struct vc4_crtc_state { +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -697,8 +697,11 @@ void vc4_hvs_mark_dlist_entry_stale(stru + * Kunit tests run with a mock device and we consider any hardware + * access a test failure. Let's free the dlist allocation right away if + * we're running under kunit, we won't risk a dlist corruption anyway. ++ * ++ * Likewise if the allocation was only checked and never programmed, we ++ * can destroy the allocation immediately. + */ +- if (kunit_get_current_test()) { ++ if (kunit_get_current_test() || !alloc->dlist_programmed) { + spin_lock_irqsave(&hvs->mm_lock, flags); + vc4_hvs_free_dlist_entry_locked(hvs, alloc); + spin_unlock_irqrestore(&hvs->mm_lock, flags); +@@ -1201,6 +1204,7 @@ static void vc4_hvs_install_dlist(struct + return; + + WARN_ON(!vc4_state->mm); ++ vc4_state->mm->dlist_programmed = true; + + if (vc4->gen >= VC4_GEN_6) + HVS_WRITE(SCALER6_DISPX_LPTRS(vc4_state->assigned_channel), diff --git a/target/linux/bcm27xx/patches-6.1/950-1164-input-edt-ft5x06-Include-I2C-details-in-names-for-th.patch b/target/linux/bcm27xx/patches-6.1/950-1164-input-edt-ft5x06-Include-I2C-details-in-names-for-th.patch new file mode 100644 index 0000000000..131e502406 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1164-input-edt-ft5x06-Include-I2C-details-in-names-for-th.patch @@ -0,0 +1,48 @@ +From 2a6c3115f4142e23ca10c984d7f65ac8fb901cc2 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 8 Nov 2023 15:50:39 +0000 +Subject: [PATCH] input: edt-ft5x06: Include I2C details in names for the + devices + +libinput uses the input device name alone. If you have two +identical input devices, then there is no way to differentiate +between them, and in the case of touchscreens that means no +way to associate them with the appropriate display device. + +Add the I2C bus and address to the start of the input device +name so that the name is always unique within the system. + +Signed-off-by: Dave Stevenson +--- + drivers/input/touchscreen/edt-ft5x06.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -67,6 +67,7 @@ + #define TOUCH_EVENT_RESERVED 0x03 + + #define EDT_NAME_LEN 23 ++#define EDT_NAME_PREFIX_LEN 8 + #define EDT_SWITCH_MODE_RETRIES 10 + #define EDT_SWITCH_MODE_DELAY 5 /* msec */ + #define EDT_RAW_DATA_RETRIES 100 +@@ -134,7 +135,7 @@ struct edt_ft5x06_ts_data { + int max_support_points; + unsigned int known_ids; + +- char name[EDT_NAME_LEN]; ++ char name[EDT_NAME_PREFIX_LEN + EDT_NAME_LEN]; + char fw_version[EDT_NAME_LEN]; + int init_td_status; + +@@ -965,6 +966,9 @@ static int edt_ft5x06_ts_identify(struct + char *model_name = tsdata->name; + char *fw_version = tsdata->fw_version; + ++ snprintf(model_name, EDT_NAME_PREFIX_LEN, "%s ", dev_name(&client->dev)); ++ model_name += strlen(model_name); ++ + /* see what we find if we assume it is a M06 * + * if we get less than EDT_NAME_LEN, we don't want + * to have garbage in there diff --git a/target/linux/bcm27xx/patches-6.1/950-1165-input-goodix-Include-I2C-details-in-names-for-the-de.patch b/target/linux/bcm27xx/patches-6.1/950-1165-input-goodix-Include-I2C-details-in-names-for-the-de.patch new file mode 100644 index 0000000000..4b529e66f5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1165-input-goodix-Include-I2C-details-in-names-for-the-de.patch @@ -0,0 +1,52 @@ +From a420bbde05f8a6691b0c3e0830092e443365aaa7 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 8 Nov 2023 16:20:27 +0000 +Subject: [PATCH] input: goodix: Include I2C details in names for the devices + +libinput uses the input device name alone. If you have two +identical input devices, then there is no way to differentiate +between them, and in the case of touchscreens that means no +way to associate them with the appropriate display device. + +Add the I2C bus and address to the start of the input device +name so that the name is always unique within the system. + +Signed-off-by: Dave Stevenson +--- + drivers/input/touchscreen/goodix.c | 5 ++++- + drivers/input/touchscreen/goodix.h | 3 +++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/input/touchscreen/goodix.c ++++ b/drivers/input/touchscreen/goodix.c +@@ -1211,7 +1211,10 @@ static int goodix_configure_dev(struct g + return -ENOMEM; + } + +- ts->input_dev->name = "Goodix Capacitive TouchScreen"; ++ snprintf(ts->name, GOODIX_NAME_MAX_LEN, "%s Goodix Capacitive TouchScreen", ++ dev_name(&ts->client->dev)); ++ ++ ts->input_dev->name = ts->name; + ts->input_dev->phys = "input/ts"; + ts->input_dev->id.bustype = BUS_I2C; + ts->input_dev->id.vendor = 0x0416; +--- a/drivers/input/touchscreen/goodix.h ++++ b/drivers/input/touchscreen/goodix.h +@@ -57,6 +57,8 @@ + #define GOODIX_CONFIG_MAX_LENGTH 240 + #define GOODIX_MAX_KEYS 7 + ++#define GOODIX_NAME_MAX_LEN 38 ++ + enum goodix_irq_pin_access_method { + IRQ_PIN_ACCESS_NONE, + IRQ_PIN_ACCESS_GPIO, +@@ -91,6 +93,7 @@ struct goodix_ts_data { + enum gpiod_flags gpiod_rst_flags; + char id[GOODIX_ID_MAX_LEN + 1]; + char cfg_name[64]; ++ char name[GOODIX_NAME_MAX_LEN]; + u16 version; + bool reset_controller_at_probe; + bool load_cfg_from_disk; diff --git a/target/linux/bcm27xx/patches-6.1/950-1166-drm-vc4-Block-swiotlb-bounce-buffers-being-imported-.patch b/target/linux/bcm27xx/patches-6.1/950-1166-drm-vc4-Block-swiotlb-bounce-buffers-being-imported-.patch new file mode 100644 index 0000000000..c40b77c957 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1166-drm-vc4-Block-swiotlb-bounce-buffers-being-imported-.patch @@ -0,0 +1,84 @@ +From a984fda6b2c24dbf1ca21924f99c8f9418f5765e Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 22 Nov 2023 19:17:44 +0000 +Subject: [PATCH] drm: vc4: Block swiotlb bounce buffers being imported as + dmabuf + +The dmabuf import already checks that the backing buffer is contiguous +and rejects it if it isn't. vc4 also requires that the buffer is +in the bottom 1GB of RAM, and this is all correctly defined via +dma-ranges. + +However the kernel silently uses swiotlb to bounce dma buffers +around if they are in the wrong region. This relies on dma sync +functions to be called in order to copy the data to/from the +bounce buffer. + +DRM is based on all memory allocations being coherent with the +GPU so that any updates to a framebuffer will be acted on without +the need for any additional update. This is fairly fundamentally +incompatible with needing to call dma_sync_ to handle the bounce +buffer copies, and therefore we have to detect and reject mappings +that use bounce buffers. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_drv.c | 26 ++++++++++++++++++++++++-- + 1 file changed, 24 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.c ++++ b/drivers/gpu/drm/vc4/vc4_drv.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -175,6 +176,19 @@ static void vc4_close(struct drm_device + kfree(vc4file); + } + ++struct drm_gem_object * ++vc4_prime_import_sg_table(struct drm_device *dev, ++ struct dma_buf_attachment *attach, ++ struct sg_table *sgt) ++{ ++ phys_addr_t phys = dma_to_phys(dev->dev, sg_dma_address(sgt->sgl)); ++ ++ if (is_swiotlb_buffer(dev->dev, phys)) ++ return ERR_PTR(-EINVAL); ++ ++ return drm_gem_dma_prime_import_sg_table(dev, attach, sgt); ++} ++ + DEFINE_DRM_GEM_FOPS(vc4_drm_fops); + + static const struct drm_ioctl_desc vc4_drm_ioctls[] = { +@@ -211,7 +225,11 @@ const struct drm_driver vc4_drm_driver = + + .gem_create_object = vc4_create_object, + +- DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(vc4_bo_dumb_create), ++ .dumb_create = vc4_bo_dumb_create, ++ .prime_handle_to_fd = drm_gem_prime_handle_to_fd, ++ .prime_fd_to_handle = drm_gem_prime_fd_to_handle, ++ .gem_prime_import_sg_table = vc4_prime_import_sg_table, ++ .gem_prime_mmap = drm_gem_prime_mmap, + + .ioctls = vc4_drm_ioctls, + .num_ioctls = ARRAY_SIZE(vc4_drm_ioctls), +@@ -234,7 +252,11 @@ const struct drm_driver vc5_drm_driver = + .debugfs_init = vc4_debugfs_init, + #endif + +- DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(vc5_dumb_create), ++ .dumb_create = vc5_dumb_create, ++ .prime_handle_to_fd = drm_gem_prime_handle_to_fd, ++ .prime_fd_to_handle = drm_gem_prime_fd_to_handle, ++ .gem_prime_import_sg_table = vc4_prime_import_sg_table, ++ .gem_prime_mmap = drm_gem_prime_mmap, + + .fops = &vc4_drm_fops, + diff --git a/target/linux/bcm27xx/patches-6.1/950-1167-overlays-i2c-sensor-Add-adt7410-support.patch b/target/linux/bcm27xx/patches-6.1/950-1167-overlays-i2c-sensor-Add-adt7410-support.patch new file mode 100644 index 0000000000..c7c9daba3f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1167-overlays-i2c-sensor-Add-adt7410-support.patch @@ -0,0 +1,75 @@ +From 77a01f7da77446277139d8e9ce63f078cbe1ecfe Mon Sep 17 00:00:00 2001 +From: Kenny +Date: Wed, 22 Nov 2023 16:22:37 -0800 +Subject: [PATCH] overlays: i2c-sensor: Add adt7410 support + +See https://github.com/raspberrypi/linux/pull/5738 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/README | 12 ++++++++---- + .../boot/dts/overlays/i2c-sensor-common.dtsi | 18 +++++++++++++++++- + 2 files changed, 25 insertions(+), 5 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -2144,10 +2144,14 @@ Name: i2c-sensor + Info: Adds support for a number of I2C barometric pressure, temperature, + light level and chemical sensors on i2c_arm + Load: dtoverlay=i2c-sensor,= +-Params: addr Set the address for the BH1750, BME280, BME680, +- BMP280, BMP380, CCS811, DS1621, HDC100X, JC42, +- LM75, MCP980x, MPU6050, MPU9250, MS5637, MS5803, +- MS5805, MS5837, MS8607, SHT3x or TMP102 ++Params: addr Set the address for the ADT7410, BH1750, BME280, ++ BME680, BMP280, BMP380, CCS811, DS1621, HDC100X, ++ JC42, LM75, MCP980x, MPU6050, MPU9250, MS5637, ++ MS5803, MS5805, MS5837, MS8607, SHT3x or TMP102 ++ ++ adt7410 Select the Analog Devices ADT7410 and ADT7420 ++ temperature sensors ++ Valid address 0x48-0x4b, default 0x48 + + aht10 Select the Aosong AHT10 temperature and humidity + sensor +--- a/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi ++++ b/arch/arm/boot/dts/overlays/i2c-sensor-common.dtsi +@@ -508,6 +508,21 @@ + }; + }; + ++ fragment@34 { ++ target = <&i2cbus>; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ adt7410: adt7410@48 { ++ compatible = "adi,adt7410", "adi,adt7420"; ++ reg = <0x48>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ + __overrides__ { + bme280 = <0>,"+0"; + bmp085 = <0>,"+1"; +@@ -543,6 +558,7 @@ + mpu9250 = <0>,"+29"; + bno055 = <0>,"+31"; + sht4x = <0>,"+32"; ++ adt7410 = <0>,"+34"; + + addr = <&bme280>,"reg:0", <&bmp280>,"reg:0", <&tmp102>,"reg:0", + <&lm75>,"reg:0", <&hdc100x>,"reg:0", <&sht3x>,"reg:0", +@@ -552,7 +568,7 @@ + <&ms5837>,"reg:0", <&ms8607>,"reg:0", + <&mpu6050>,"reg:0", <&mpu9250>,"reg:0", + <&bno055>,"reg:0", <&sht4x>,"reg:0", +- <&bmp380>,"reg:0"; ++ <&bmp380>,"reg:0", <&adt7410>,"reg:0"; + int_pin = <&max30102>, "interrupts:0", + <&mpu6050>, "interrupts:0", + <&mpu9250>, "interrupts:0"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1168-overlays-hat_map-Add-pisound-mapping.patch b/target/linux/bcm27xx/patches-6.1/950-1168-overlays-hat_map-Add-pisound-mapping.patch new file mode 100644 index 0000000000..2620a598f7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1168-overlays-hat_map-Add-pisound-mapping.patch @@ -0,0 +1,26 @@ +From 7c185b18a1c6a6cd6ab8805fef03a4a8c9931656 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 24 Nov 2023 13:57:09 +0000 +Subject: [PATCH] overlays: hat_map: Add pisound mapping + +See: https://github.com/raspberrypi/linux/issues/5741 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/hat_map.dts | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/arch/arm/boot/dts/overlays/hat_map.dts ++++ b/arch/arm/boot/dts/overlays/hat_map.dts +@@ -6,6 +6,11 @@ + overlay = "iqaudio-codec"; + }; + ++ pisound { ++ uuid = [ a7ee5d28 da03 41f5 bbd7 20438a4bec5d ]; ++ overlay = "pisound"; ++ }; ++ + recalbox-rgbdual { + uuid = [ 1c955808 681f 4bbc a2ef b7ea47cd388e ]; + overlay = "recalboxrgbdual"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1169-drm-vc4-Set-TV-margins-on-the-composite-connector-st.patch b/target/linux/bcm27xx/patches-6.1/950-1169-drm-vc4-Set-TV-margins-on-the-composite-connector-st.patch new file mode 100644 index 0000000000..05da5d38c5 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1169-drm-vc4-Set-TV-margins-on-the-composite-connector-st.patch @@ -0,0 +1,47 @@ +From bc76ab2e772242d0d92d38b2a5648485ee1a1b44 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20B=C3=BCchler?= +Date: Sun, 19 Nov 2023 01:22:20 +0100 +Subject: [PATCH] drm/vc4: Set TV margins on the composite connector state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Raspberry Pi bootloader can pass a set of margin values to the +kernel cmdline as part of the video= option. These should result in +black borders on the output to compensate for TVs where the visible area +on the screen is smaller than the full extents of the video image. + +With the VC4 driver this currently works on an HDMI connector, but not +on a composite video connector. + +The TV margins from the kernel cmdline are available in the +drm_cmdline_mode structure of the composite video connector. Apply them +to the connector state in the connector reset function. This is how it +is implemented for the VC4 HDMI connector. + +Signed-off-by: Michael Büchler +--- + drivers/gpu/drm/vc4/vc4_vec.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/gpu/drm/vc4/vc4_vec.c ++++ b/drivers/gpu/drm/vc4/vc4_vec.c +@@ -436,6 +436,9 @@ static void vc4_vec_connector_reset(stru + /* preserve TV standard */ + if (connector->state) + connector->state->tv.mode = vc4_vec_get_default_mode(connector); ++ ++ /* apply TV margins from the cmdline_mode */ ++ drm_atomic_helper_connector_tv_reset(connector); + } + + static int vc4_vec_connector_atomic_check(struct drm_connector *conn, +@@ -483,6 +486,8 @@ static int vc4_vec_connector_init(struct + + drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs); + ++ drm_connector_attach_tv_margin_properties(connector); ++ + drm_object_attach_property(&connector->base, + dev->mode_config.tv_mode_property, + vc4_vec_get_default_mode(connector)); diff --git a/target/linux/bcm27xx/patches-6.1/950-1170-drm-panel-jdi-lt070me05000-Add-prepare_upstream_firs.patch b/target/linux/bcm27xx/patches-6.1/950-1170-drm-panel-jdi-lt070me05000-Add-prepare_upstream_firs.patch new file mode 100644 index 0000000000..62e408b514 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1170-drm-panel-jdi-lt070me05000-Add-prepare_upstream_firs.patch @@ -0,0 +1,26 @@ +From 63d8c0f5185169058384142547655fc038aae0bf Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 9 Aug 2023 21:04:40 +0100 +Subject: [PATCH] drm: panel: jdi-lt070me05000: Add prepare_upstream_first flag + +The panel driver wants to send DCS commands from the prepare +hook, therefore the DSI host wants to be pre_enabled first. +Set the flag to achieve this. + +https://forums.raspberrypi.com/viewtopic.php?t=354708 + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/panel/panel-jdi-lt070me05000.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c ++++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c +@@ -437,6 +437,7 @@ static int jdi_panel_add(struct jdi_pane + return ret; + } + ++ jdi->base.prepare_upstream_first = true; + drm_panel_init(&jdi->base, &jdi->dsi->dev, &jdi_panel_funcs, + DRM_MODE_CONNECTOR_DSI); + diff --git a/target/linux/bcm27xx/patches-6.1/950-1172-drivers-media-cfe-Find-the-source-pads-on-the-sensor.patch b/target/linux/bcm27xx/patches-6.1/950-1172-drivers-media-cfe-Find-the-source-pads-on-the-sensor.patch new file mode 100644 index 0000000000..e1f16d0171 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1172-drivers-media-cfe-Find-the-source-pads-on-the-sensor.patch @@ -0,0 +1,55 @@ +From 76b1bbf3ec3be0afdc768863ab7e9bbd2734b97b Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 24 Nov 2023 14:29:57 +0000 +Subject: [PATCH] drivers: media: cfe: Find the source pads on the sensor + entity + +The driver was assuming that pad 0 on the sensor entity was the +appropriate source pad, but this isn't necessarily the case. +With video-mux, it has the sink pads first, and then the source +pad as the last one. + +Iterate through the sensor pads to find the relevant source pads. + +Signed-off-by: Dave Stevenson +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -1826,7 +1826,7 @@ static void cfe_unregister_nodes(struct + + static int cfe_link_node_pads(struct cfe_device *cfe) + { +- unsigned int i; ++ unsigned int i, source_pad = 0; + int ret; + + for (i = 0; i < CSI2_NUM_CHANNELS; i++) { +@@ -1835,14 +1835,23 @@ static int cfe_link_node_pads(struct cfe + if (!check_state(cfe, NODE_REGISTERED, i)) + continue; + +- if (i < cfe->sensor->entity.num_pads) { ++ /* Find next source pad */ ++ while (source_pad < cfe->sensor->entity.num_pads && ++ !(cfe->sensor->entity.pads[source_pad].flags & ++ MEDIA_PAD_FL_SOURCE)) ++ source_pad++; ++ ++ if (source_pad < cfe->sensor->entity.num_pads) { + /* Sensor -> CSI2 */ +- ret = media_create_pad_link(&cfe->sensor->entity, i, ++ ret = media_create_pad_link(&cfe->sensor->entity, source_pad, + &cfe->csi2.sd.entity, i, + MEDIA_LNK_FL_IMMUTABLE | + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; ++ ++ /* Dealt with that source_pad, look at the next one next time */ ++ source_pad++; + } + + /* CSI2 channel # -> /dev/video# */ diff --git a/target/linux/bcm27xx/patches-6.1/950-1173-dtoverlays-Add-option-for-cam0-to-camera-mux-Nport-o.patch b/target/linux/bcm27xx/patches-6.1/950-1173-dtoverlays-Add-option-for-cam0-to-camera-mux-Nport-o.patch new file mode 100644 index 0000000000..09cdcc7928 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1173-dtoverlays-Add-option-for-cam0-to-camera-mux-Nport-o.patch @@ -0,0 +1,101 @@ +From 08c5904ad00ffc54d37058ead19814f8a85f6f39 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 27 Nov 2023 14:50:58 +0000 +Subject: [PATCH] dtoverlays: Add option for cam0 to camera-mux-Nport overlays + +Seeing as the mux can be connected to either CAM/DISP1 or +CAM/DISP0 on a Pi5, add a cam0 override to allow configuration +of which is used. Default (as with all camera overlays) is CAM/DISP1. + +The overlay does NOT update the camera regulator used by all the +sensors as doing so would be a nightmare. The Arducam mulitplexer +boards these overlays are initially supporting seem to tie the +regulator GPIO for all the sensors high anyway. +If it was viewed as necessary, then creating an additional +regulator that listed cam[01]_reg as the parent should work. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/overlays/README | 4 ++++ + arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts | 7 +++++-- + arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts | 7 +++++-- + 3 files changed, 14 insertions(+), 4 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -823,6 +823,8 @@ Params: cam0-arducam-64mp Select A + cam1-ov9281 Select OV9281 for camera on port 1 + cam1-imx290-clk-freq Set clock frequency for an IMX290 on port 1 + ++ cam0 Connect the mux to CAM0 port (default is CAM1) ++ + + Name: camera-mux-4port + Info: Configures a 4 port camera multiplexer +@@ -878,6 +880,8 @@ Params: cam0-arducam-64mp Select A + cam3-ov9281 Select OV9281 for camera on port 3 + cam3-imx290-clk-freq Set clock frequency for an IMX290 on port 3 + ++ cam0 Connect the mux to CAM0 port (default is CAM1) ++ + + Name: cap1106 + Info: Enables the ability to use the cap1106 touch sensor as a keyboard +--- a/arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts ++++ b/arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts +@@ -77,7 +77,7 @@ + }; + + /* Mux define */ +- fragment@200 { ++ i2c_frag: fragment@200 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; +@@ -294,7 +294,7 @@ + }; + }; + +- fragment@201 { ++ csi_frag: fragment@201 { + target = <&csi1>; + __overlay__ { + status = "okay"; +@@ -501,5 +501,8 @@ + <&imx290_0>,"clock-frequency:0"; + cam1-imx290-clk-freq = <&clk_imx290>,"clock-frequency:0", + <&imx290_1>,"clock-frequency:0"; ++ ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, ++ <&csi_frag>, "target:0=",<&csi0>; + }; + }; +--- a/arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts ++++ b/arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts +@@ -135,7 +135,7 @@ + }; + + /* Mux define */ +- fragment@200 { ++ i2c_frag: fragment@200 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; +@@ -552,7 +552,7 @@ + }; + }; + +- fragment@201 { ++ csi_frag: fragment@201 { + target = <&csi1>; + __overlay__ { + status = "okay"; +@@ -872,5 +872,8 @@ + <&imx290_2>,"clock-frequency:0"; + cam3-imx290-clk-freq = <&clk_imx290>,"clock-frequency:0", + <&imx290_3>,"clock-frequency:0"; ++ ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, ++ <&csi_frag>, "target:0=",<&csi0>; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1174-ASoC-dwc-Permit-sample-rates-up-to-384kHz.patch b/target/linux/bcm27xx/patches-6.1/950-1174-ASoC-dwc-Permit-sample-rates-up-to-384kHz.patch new file mode 100644 index 0000000000..258b9de01c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1174-ASoC-dwc-Permit-sample-rates-up-to-384kHz.patch @@ -0,0 +1,26 @@ +From 6fac5d5ed6d023733ef7304afc88c8d89467a204 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 27 Nov 2023 12:16:04 +0000 +Subject: [PATCH] ASoC: dwc: Permit sample rates up to 384kHz + +The BCM2835 I2S block advertises clock rates up to 384kHz, and there's +no reason why RP1's DWC I2S block shouldn't do the same. + +See: https://github.com/raspberrypi/linux/issues/5748 + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -667,7 +667,7 @@ static int dw_configure_dai_by_dt(struct + if (WARN_ON(idx >= ARRAY_SIZE(bus_widths))) + return -EINVAL; + +- ret = dw_configure_dai(dev, dw_i2s_dai, SNDRV_PCM_RATE_8000_192000); ++ ret = dw_configure_dai(dev, dw_i2s_dai, SNDRV_PCM_RATE_8000_384000); + if (ret < 0) + return ret; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1176-ASoC-dwc-Fix-full-duplex-mode.patch b/target/linux/bcm27xx/patches-6.1/950-1176-ASoC-dwc-Fix-full-duplex-mode.patch new file mode 100644 index 0000000000..f4b7098fae --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1176-ASoC-dwc-Fix-full-duplex-mode.patch @@ -0,0 +1,63 @@ +From cbc65d9c95088d1437a5a84c7d6628b8d27a86f1 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 28 Nov 2023 12:14:03 +0000 +Subject: [PATCH] ASoC: dwc: Fix full-duplex mode + +Configuration of the DMA register was carelessly zeroing bits that may +used by a stream in the other direction. Preserve them instead. + +See: https://github.com/raspberrypi/linux/issues/5741 + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -189,10 +189,17 @@ static void dw_i2s_config(struct dw_i2s_ + { + struct i2s_clk_config_data *config = &dev->config; + u32 ch_reg; +- u32 dmacr = 0; ++ u32 dmacr; + + i2s_disable_channels(dev, stream); + ++ dmacr = i2s_read_reg(dev->i2s_base, DMACR); ++ ++ if (stream == SNDRV_PCM_STREAM_PLAYBACK) ++ dmacr &= ~(DMACR_DMAEN_TXCH0 * 0xf); ++ else ++ dmacr &= ~(DMACR_DMAEN_RXCH0 * 0xf); ++ + for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) { + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + i2s_write_reg(dev->i2s_base, TCR(ch_reg), +@@ -210,10 +217,6 @@ static void dw_i2s_config(struct dw_i2s_ + 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); + } +@@ -319,10 +322,13 @@ static int dw_i2s_startup(struct snd_pcm + + dw_i2s_config(dev, substream->stream); + dmacr = i2s_read_reg(dev->i2s_base, DMACR); +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dma_data = &dev->play_dma_data; +- else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ++ dmacr |= DMACR_DMAEN_TX; ++ } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + dma_data = &dev->capture_dma_data; ++ dmacr |= DMACR_DMAEN_RX; ++ } + + snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data); + i2s_write_reg(dev->i2s_base, DMACR, dmacr); diff --git a/target/linux/bcm27xx/patches-6.1/950-1179-ASoC-pcm512x-Adds-bindings-for-TAS575x-devices.patch b/target/linux/bcm27xx/patches-6.1/950-1179-ASoC-pcm512x-Adds-bindings-for-TAS575x-devices.patch new file mode 100644 index 0000000000..8472c3e9e1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1179-ASoC-pcm512x-Adds-bindings-for-TAS575x-devices.patch @@ -0,0 +1,45 @@ +From a7ac27fbac1aa3fb8316cf1ff6dd2f81109d46d2 Mon Sep 17 00:00:00 2001 +From: Joerg Schambacher +Date: Fri, 29 Sep 2023 17:05:55 +0200 +Subject: [PATCH] ASoC: pcm512x: Adds bindings for TAS575x devices + +commit 736b884a7b68c4eeb66dbf75b97c8ec9b9eeff7f upstream. + +The TAS5754/6 power amplifiers use the same pcm512x driver with +only minor restictions described in the bindings document. + +Signed-off-by: Joerg Schambacher +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20230929150555.405388-1-joerg.hifiberry@gmail.com +Signed-off-by: Mark Brown +--- + Documentation/devicetree/bindings/sound/pcm512x.txt | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/Documentation/devicetree/bindings/sound/pcm512x.txt ++++ b/Documentation/devicetree/bindings/sound/pcm512x.txt +@@ -1,12 +1,12 @@ +-PCM512x audio CODECs ++PCM512x and TAS575x audio CODECs/amplifiers + + These devices support both I2C and SPI (configured with pin strapping +-on the board). ++on the board). The TAS575x devices only support I2C. + + Required properties: + +- - compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141" or +- "ti,pcm5142" ++ - compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141", ++ "ti,pcm5142", "ti,tas5754" or "ti,tas5756" + + - reg : the I2C address of the device for I2C, the chip select + number for SPI. +@@ -25,6 +25,7 @@ Optional properties: + through <6>. The device will be configured for clock input on the + given pll-in pin and PLL output on the given pll-out pin. An + external connection from the pll-out pin to the SCLK pin is assumed. ++ Caution: the TAS-desvices only support gpios 1,2 and 3 + + Examples: + diff --git a/target/linux/bcm27xx/patches-6.1/950-1180-ASoC-Adds-support-for-TAS575x-to-the-pcm512x-driver.patch b/target/linux/bcm27xx/patches-6.1/950-1180-ASoC-Adds-support-for-TAS575x-to-the-pcm512x-driver.patch new file mode 100644 index 0000000000..5009b225a3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1180-ASoC-Adds-support-for-TAS575x-to-the-pcm512x-driver.patch @@ -0,0 +1,102 @@ +From a535dd07aff73f3a6eb40174ab5dc413d05f36a1 Mon Sep 17 00:00:00 2001 +From: Joerg Schambacher +Date: Fri, 29 Sep 2023 17:07:20 +0200 +Subject: [PATCH] ASoC: Adds support for TAS575x to the pcm512x driver + +commit 1f817805262c2c34142291da376d4932d3c493bc upstream. + +Enables the existing pcm512x driver to control the almost +compatible TAS5754 and -76 amplifers. Both amplifiers support +only an I2C interface and the internal PLL must be always +on to provide necessary clocks to the amplifier section. +Tested on TAS5756 with support from Andreas Arbesser-Krasser +from Texas Instruments + +Signed-off-by: Joerg Schambacher +Link: https://lore.kernel.org/r/20230929150722.405415-1-joerg.hifiberry@gmail.com +Signed-off-by: Mark Brown +--- + sound/soc/codecs/pcm512x-i2c.c | 4 ++++ + sound/soc/codecs/pcm512x.c | 36 +++++++++++++++++++++++++++++++--- + 2 files changed, 37 insertions(+), 3 deletions(-) + +--- a/sound/soc/codecs/pcm512x-i2c.c ++++ b/sound/soc/codecs/pcm512x-i2c.c +@@ -39,6 +39,8 @@ static const struct i2c_device_id pcm512 + { "pcm5122", }, + { "pcm5141", }, + { "pcm5142", }, ++ { "tas5754", }, ++ { "tas5756", }, + { } + }; + MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); +@@ -49,6 +51,8 @@ static const struct of_device_id pcm512x + { .compatible = "ti,pcm5122", }, + { .compatible = "ti,pcm5141", }, + { .compatible = "ti,pcm5142", }, ++ { .compatible = "ti,tas5754", }, ++ { .compatible = "ti,tas5756", }, + { } + }; + MODULE_DEVICE_TABLE(of, pcm512x_of_match); +--- a/sound/soc/codecs/pcm512x.c ++++ b/sound/soc/codecs/pcm512x.c +@@ -48,6 +48,7 @@ struct pcm512x_priv { + int mute; + struct mutex mutex; + unsigned int bclk_ratio; ++ int force_pll_on; + }; + + /* +@@ -1258,10 +1259,34 @@ static int pcm512x_hw_params(struct snd_ + return ret; + } + +- ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_EN, +- PCM512x_PLLE, 0); ++ if (!pcm512x->force_pll_on) { ++ ret = regmap_update_bits(pcm512x->regmap, ++ PCM512x_PLL_EN, PCM512x_PLLE, 0); ++ } else { ++ /* provide minimum PLL config for TAS575x clocking ++ * and leave PLL enabled ++ */ ++ ret = regmap_write(pcm512x->regmap, ++ PCM512x_PLL_COEFF_0, 0x01); ++ if (ret != 0) { ++ dev_err(component->dev, ++ "Failed to set pll coefficient: %d\n", ret); ++ return ret; ++ } ++ ret = regmap_write(pcm512x->regmap, ++ PCM512x_PLL_COEFF_1, 0x04); ++ if (ret != 0) { ++ dev_err(component->dev, ++ "Failed to set pll coefficient: %d\n", ret); ++ return ret; ++ } ++ ret = regmap_write(pcm512x->regmap, ++ PCM512x_PLL_EN, 0x01); ++ dev_dbg(component->dev, "Enabling PLL for TAS575x\n"); ++ } ++ + if (ret != 0) { +- dev_err(component->dev, "Failed to disable pll: %d\n", ret); ++ dev_err(component->dev, "Failed to set pll mode: %d\n", ret); + return ret; + } + } +@@ -1659,6 +1684,11 @@ int pcm512x_probe(struct device *dev, st + ret = -EINVAL; + goto err_pm; + } ++ ++ if (!strcmp(np->name, "tas5756") || ++ !strcmp(np->name, "tas5754")) ++ pcm512x->force_pll_on = 1; ++ dev_dbg(dev, "Device ID: %s\n", np->name); + } + #endif + diff --git a/target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch b/target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch new file mode 100644 index 0000000000..d914ab6d04 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1182-drm-panel-add-panel-dsi.patch @@ -0,0 +1,176 @@ +From 0a0084b8621682ad96d001e798aa239b11a3cf00 Mon Sep 17 00:00:00 2001 +From: Timon Skerutsch +Date: Mon, 13 Nov 2023 22:53:12 +0100 +Subject: [PATCH] drm/panel: add panel-dsi + +Equivalent to panel-dpi for configuring a simple DSI panel with +device tree side timings and bus settings. +Motiviation is the same as for panel-dpi of wanting to support +new simple panels without needing to patch the kernel. + +Signed-off-by: Timon Skerutsch +--- + drivers/gpu/drm/panel/panel-simple.c | 123 ++++++++++++++++++++++++++- + 1 file changed, 122 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/panel/panel-simple.c ++++ b/drivers/gpu/drm/panel/panel-simple.c +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include + + /** + * struct panel_desc - Describes a simple panel. +@@ -4660,6 +4661,9 @@ static const struct panel_desc_dsi osd10 + .lanes = 4, + }; + ++// for panels using generic panel-dsi binding ++static struct panel_desc_dsi panel_dsi; ++ + static const struct of_device_id dsi_of_match[] = { + { + .compatible = "auo,b080uan01", +@@ -4683,14 +4687,118 @@ static const struct of_device_id dsi_of_ + .compatible = "osddisplays,osd101t2045-53ts", + .data = &osd101t2045_53ts + }, { ++ /* Must be the last entry */ ++ .compatible = "panel-dsi", ++ .data = &panel_dsi, ++ }, { + /* sentinel */ + } + }; + MODULE_DEVICE_TABLE(of, dsi_of_match); + ++ ++/* Checks for DSI panel definition in device-tree, analog to panel_dpi */ ++static int panel_dsi_dt_probe(struct device *dev, ++ struct panel_desc_dsi *desc_dsi) ++{ ++ struct panel_desc *desc; ++ struct display_timing *timing; ++ const struct device_node *np; ++ const char *dsi_color_format; ++ const char *dsi_mode_flags; ++ struct property *prop; ++ int dsi_lanes, ret; ++ ++ np = dev->of_node; ++ ++ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ ++ timing = devm_kzalloc(dev, sizeof(*timing), GFP_KERNEL); ++ if (!timing) ++ return -ENOMEM; ++ ++ ret = of_get_display_timing(np, "panel-timing", timing); ++ if (ret < 0) { ++ dev_err(dev, "%pOF: no panel-timing node found for \"panel-dsi\" binding\n", ++ np); ++ return ret; ++ } ++ ++ desc->timings = timing; ++ desc->num_timings = 1; ++ ++ of_property_read_u32(np, "width-mm", &desc->size.width); ++ of_property_read_u32(np, "height-mm", &desc->size.height); ++ ++ dsi_lanes = drm_of_get_data_lanes_count_ep(np, 0, 0, 1, 4); ++ ++ if (dsi_lanes < 0) { ++ dev_err(dev, "%pOF: no or too many data-lanes defined", np); ++ return dsi_lanes; ++ } ++ ++ desc_dsi->lanes = dsi_lanes; ++ ++ of_property_read_string(np, "dsi-color-format", &dsi_color_format); ++ if (!strcmp(dsi_color_format, "RGB888")) { ++ desc_dsi->format = MIPI_DSI_FMT_RGB888; ++ desc->bpc = 8; ++ } else if (!strcmp(dsi_color_format, "RGB565")) { ++ desc_dsi->format = MIPI_DSI_FMT_RGB565; ++ desc->bpc = 6; ++ } else if (!strcmp(dsi_color_format, "RGB666")) { ++ desc_dsi->format = MIPI_DSI_FMT_RGB666; ++ desc->bpc = 6; ++ } else if (!strcmp(dsi_color_format, "RGB666_PACKED")) { ++ desc_dsi->format = MIPI_DSI_FMT_RGB666_PACKED; ++ desc->bpc = 6; ++ } else { ++ dev_err(dev, "%pOF: no valid dsi-color-format defined", np); ++ return -EINVAL; ++ } ++ ++ ++ of_property_for_each_string(np, "mode", prop, dsi_mode_flags) { ++ if (!strcmp(dsi_mode_flags, "MODE_VIDEO")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_BURST")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_BURST; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_SYNC_PULSE")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_AUTO_VERT")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_AUTO_VERT; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_HSE")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_HSE; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HFP")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HFP; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HBP")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HBP; ++ else if (!strcmp(dsi_mode_flags, "MODE_VIDEO_NO_HSA")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VIDEO_NO_HSA; ++ else if (!strcmp(dsi_mode_flags, "MODE_VSYNC_FLUSH")) ++ desc_dsi->flags |= MIPI_DSI_MODE_VSYNC_FLUSH; ++ else if (!strcmp(dsi_mode_flags, "MODE_NO_EOT_PACKET")) ++ desc_dsi->flags |= MIPI_DSI_MODE_NO_EOT_PACKET; ++ else if (!strcmp(dsi_mode_flags, "CLOCK_NON_CONTINUOUS")) ++ desc_dsi->flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS; ++ else if (!strcmp(dsi_mode_flags, "MODE_LPM")) ++ desc_dsi->flags |= MIPI_DSI_MODE_LPM; ++ else if (!strcmp(dsi_mode_flags, "HS_PKT_END_ALIGNED")) ++ desc_dsi->flags |= MIPI_DSI_HS_PKT_END_ALIGNED; ++ } ++ ++ desc->connector_type = DRM_MODE_CONNECTOR_DSI; ++ desc_dsi->desc = *desc; ++ ++ return 0; ++} ++ + static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi) + { + const struct panel_desc_dsi *desc; ++ struct panel_desc_dsi *dt_desc; + const struct of_device_id *id; + int err; + +@@ -4698,7 +4806,20 @@ static int panel_simple_dsi_probe(struct + if (!id) + return -ENODEV; + +- desc = id->data; ++ if (id->data == &panel_dsi) { ++ /* Handle the generic panel-dsi binding */ ++ dt_desc = devm_kzalloc(&dsi->dev, sizeof(*dt_desc), GFP_KERNEL); ++ if (!dt_desc) ++ return -ENOMEM; ++ ++ err = panel_dsi_dt_probe(&dsi->dev, dt_desc); ++ if (err < 0) ++ return err; ++ ++ desc = dt_desc; ++ } else { ++ desc = id->data; ++ } + + err = panel_simple_probe(&dsi->dev, &desc->desc); + if (err < 0) diff --git a/target/linux/bcm27xx/patches-6.1/950-1183-dt-bindings-display-panel-dsi-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-1183-dt-bindings-display-panel-dsi-bindings.patch new file mode 100644 index 0000000000..c75ca8e8ac --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1183-dt-bindings-display-panel-dsi-bindings.patch @@ -0,0 +1,136 @@ +From e14ceeadfa5b9d8a41e73edfa416bbe92dd5b20d Mon Sep 17 00:00:00 2001 +From: Timon Skerutsch +Date: Mon, 13 Nov 2023 22:53:22 +0100 +Subject: [PATCH] dt-bindings: display: panel-dsi bindings + +Bindings for the panel-dsi specific additions to panel-simple. +Allow for DSI specific bus settings and panel timing +to be define in devicetree. Very similar to panel-dpi. + +Signed-off-by: Timon Skerutsch +--- + .../bindings/display/panel/panel-dsi.yaml | 118 ++++++++++++++++++ + 1 file changed, 118 insertions(+) + create mode 100644 Documentation/devicetree/bindings/display/panel/panel-dsi.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/display/panel/panel-dsi.yaml +@@ -0,0 +1,118 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/display/panel/panel-dsi.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Generic MIPI DSI Panel ++ ++maintainers: ++ - Timon Skerutsch ++ ++allOf: ++ - $ref: panel-common.yaml# ++ ++properties: ++ compatible: ++ description: ++ Shall contain a panel specific compatible and "panel-dsi" ++ in that order. ++ items: ++ - {} ++ - const: panel-dsi ++ ++ dsi-color-format: ++ description: | ++ The color format used by the panel. Only DSI supported formats are allowed. ++ enum: ++ - RGB888 ++ - RGB666 ++ - RGB666_PACKED ++ - RGB565 ++ ++ port: ++ $ref: /schemas/graph.yaml#/$defs/port-base ++ unevaluatedProperties: false ++ description: ++ Panel MIPI DSI input ++ ++ properties: ++ endpoint: ++ $ref: /schemas/media/video-interfaces.yaml# ++ unevaluatedProperties: false ++ ++ properties: ++ data-lanes: true ++ ++ required: ++ - data-lanes ++ ++ mode: ++ description: | ++ DSI mode flags. See DSI Specs for details. ++ These are driver independent features of the DSI bus. ++ items: ++ - const: MODE_VIDEO ++ - const: MODE_VIDEO_BURST ++ - const: MODE_VIDEO_SYNC_PULSE ++ - const: MODE_VIDEO_AUTO_VERT ++ - const: MODE_VIDEO_HSE ++ - const: MODE_VIDEO_NO_HFP ++ - const: MODE_VIDEO_NO_HBP ++ - const: MODE_VIDEO_NO_HSA ++ - const: MODE_VSYNC_FLUSH ++ - const: MODE_NO_EOT_PACKET ++ - const: CLOCK_NON_CONTINUOUS ++ - const: MODE_LPM ++ - const: HS_PKT_END_ALIGNED ++ ++ reg: true ++ backlight: true ++ enable-gpios: true ++ width-mm: true ++ height-mm: true ++ panel-timing: true ++ power-supply: true ++ reset-gpios: true ++ ddc-i2c-bus: true ++ ++required: ++ - panel-timing ++ - reg ++ - power-supply ++ - dsi-color-format ++ - port ++ ++additionalProperties: false ++ ++examples: ++ - | ++ panel { ++ compatible = "panel-mfgr,generic-dsi-panel","panel-dsi"; ++ power-supply = <&vcc_supply>; ++ backlight = <&backlight>; ++ dsi-color-format = "RGB888"; ++ reg = <0>; ++ mode = "MODE_VIDEO", "MODE_VIDEO_BURST", "MODE_NO_EOT_PACKET"; ++ ++ port { ++ panel_dsi_port: endpoint { ++ data-lanes = <1 2>; ++ remote-endpoint = <&dsi_out>; ++ }; ++ }; ++ ++ panel-timing { ++ clock-frequency = <9200000>; ++ hactive = <800>; ++ vactive = <480>; ++ hfront-porch = <8>; ++ hback-porch = <4>; ++ hsync-len = <41>; ++ vback-porch = <2>; ++ vfront-porch = <4>; ++ vsync-len = <10>; ++ }; ++ }; ++ ++... diff --git a/target/linux/bcm27xx/patches-6.1/950-1184-overlays-example-overlay-for-using-panel-dsi-on-RPi.patch b/target/linux/bcm27xx/patches-6.1/950-1184-overlays-example-overlay-for-using-panel-dsi-on-RPi.patch new file mode 100644 index 0000000000..28a82d596d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1184-overlays-example-overlay-for-using-panel-dsi-on-RPi.patch @@ -0,0 +1,176 @@ +From ccf75f2a6f4045484c4539f7d47264f8f6b8453c Mon Sep 17 00:00:00 2001 +From: Timon Skerutsch +Date: Mon, 13 Nov 2023 22:52:35 +0100 +Subject: [PATCH] overlays: example overlay for using panel-dsi on RPi + +Analog to the generic panel-dpi overlay to use panel-dsi with dtparam +to not require a panel specific overlay for simple use cases that +do not require setting more niche DSI modes. + +Signed-off-by: Timon Skerutsch +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 31 +++++ + .../overlays/vc4-kms-dsi-generic-overlay.dts | 106 ++++++++++++++++++ + 3 files changed, 138 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-dsi-generic-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -293,6 +293,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + vc4-kms-dpi-hyperpixel4sq.dtbo \ + vc4-kms-dpi-panel.dtbo \ + vc4-kms-dsi-7inch.dtbo \ ++ vc4-kms-dsi-generic.dtbo \ + vc4-kms-dsi-lt070me05000.dtbo \ + vc4-kms-dsi-lt070me05000-v2.dtbo \ + vc4-kms-dsi-waveshare-panel.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -4785,6 +4785,37 @@ Params: sizex Touchscr + the default DSI1 and i2c_csi_dsi). + + ++Name: vc4-kms-dsi-generic ++Info: Enable a generic DSI display under KMS. ++ Default timings are for a 840x480 RGB888 panel. ++ Requires vc4-kms-v3d to be loaded. ++Load: dtoverlay=vc4-kms-dsi-generic,= ++Params: clock-frequency Display clock frequency (Hz) ++ hactive Horizontal active pixels ++ hfp Horizontal front porch ++ hsync Horizontal sync pulse width ++ hbp Horizontal back porch ++ vactive Vertical active lines ++ vfp Vertical front porch ++ vsync Vertical sync pulse width ++ vbp Vertical back porch ++ width-mm Define the screen width in mm ++ height-mm Define the screen height in mm ++ rgb565 Change to RGB565 output ++ rgb666 Change to RGB666 output ++ rgb666p Change to RGB666 output with pixel packing ++ rgb888 Change to RGB888 output, this is the default ++ one-lane Use one DSI lane for data transmission ++ This is the default ++ two-lane Use two DSI lanes for data transmission ++ three-lane Use three DSI lanes for data transmission ++ Only supported on Pi5 and CM ++ four-lane Use four DSI lanes for data transmission ++ Only supported on Pi5 and CM ++ dsi0 Switch DSI port to DSI0 ++ Only supported on Pi5 and CM ++ ++ + Name: vc4-kms-dsi-lt070me05000 + Info: Enable a JDI LT070ME05000 DSI display on DSI1. + Note that this is a 4 lane DSI device, so it will only work on a Compute +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-generic-overlay.dts +@@ -0,0 +1,106 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835"; ++ ++ dsi_frag: fragment@0 { ++ target = <&dsi1>; ++ __overlay__{ ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port { ++ dsi_out:endpoint { ++ remote-endpoint = <&panel_dsi_port>; ++ }; ++ }; ++ panel: panel-dsi-generic@0 { ++ // See panel-dsi.yaml binding ++ // Using dummy name for panel model ++ compatible = "Generic,panel-dsi","panel-dsi"; ++ reg = <0>; ++ power-supply = <0>; ++ backlight = <0>; ++ dsi-color-format = "RGB888"; ++ mode = "MODE_VIDEO"; ++ width-mm = <0>; ++ height-mm = <0>; ++ ++ port { ++ panel_dsi_port: endpoint { ++ data-lanes = <1>; ++ remote-endpoint = <&dsi_out>; ++ }; ++ }; ++ ++ timing: panel-timing { ++ clock-frequency = <30000000>; ++ hactive = <840>; ++ vactive = <480>; ++ hback-porch = <44>; ++ hfront-porch = <46>; ++ hsync-len = <2>; ++ vback-porch = <18>; ++ vfront-porch = <16>; ++ vsync-len = <2>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&panel_dsi_port>; ++ __dormant__ { ++ data-lanes = <1>; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&panel_dsi_port>; ++ __dormant__ { ++ data-lanes = <1 2>; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&panel_dsi_port>; ++ __dormant__ { ++ data-lanes = <1 2 3>; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&panel_dsi_port>; ++ __dormant__ { ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ ++ __overrides__ { ++ dsi0 = <&dsi_frag>, "target:0=",<&dsi0>; ++ ++ clock-frequency = <&timing>, "clock-frequency:0"; ++ hactive = <&timing>, "hactive:0"; ++ hfp = <&timing>, "hfront-porch:0"; ++ hsync = <&timing>, "hsync-len:0"; ++ hbp = <&timing>, "hback-porch:0"; ++ vactive = <&timing>, "vactive:0"; ++ vfp = <&timing>, "vfront-porch:0"; ++ vsync = <&timing>, "vsync-len:0"; ++ vbp = <&timing>, "vback-porch:0"; ++ ++ width-mm = <&panel>, "width-mm:0"; ++ height-mm = <&panel>, "height-mm:0"; ++ ++ rgb565 = <&panel>, "dsi-color-format=RGB565"; ++ rgb666p = <&panel>, "dsi-color-format=RGB666_PACKED"; ++ rgb666 = <&panel>, "dsi-color-format=RGB666"; ++ rgb888 = <&panel>, "dsi-color-format=RGB888"; ++ one-lane = <0>,"+1"; ++ two-lane = <0>,"+2"; ++ three-lane = <0>,"+3"; ++ four-lane = <0>,"+4"; ++ }; ++ ++}; diff --git a/target/linux/bcm27xx/patches-6.1/950-1185-overlays-ADS1115-allow-specification-of-the-i2c-bus.patch b/target/linux/bcm27xx/patches-6.1/950-1185-overlays-ADS1115-allow-specification-of-the-i2c-bus.patch new file mode 100644 index 0000000000..ef9328bd6f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1185-overlays-ADS1115-allow-specification-of-the-i2c-bus.patch @@ -0,0 +1,159 @@ +From a477a6351575aa173f9f82857f5797e384fbc704 Mon Sep 17 00:00:00 2001 +From: JinShil +Date: Tue, 28 Nov 2023 17:05:44 +0900 +Subject: [PATCH] overlays: ADS1115: allow specification of the i2c bus + +--- + arch/arm/boot/dts/overlays/README | 10 +++ + .../arm/boot/dts/overlays/ads1115-overlay.dts | 80 +++++++++++++------ + 2 files changed, 66 insertions(+), 24 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -489,6 +489,16 @@ Params: addr I2C bus + cha_gain Set the gain of the Programmable Gain + Amplifier for this channel. (Default 1 sets the + full scale of the channel to 4.096 Volts) ++ i2c0 Choose the I2C0 bus on GPIOs 0&1 ++ i2c_csi_dsi Choose the I2C0 bus on GPIOs 44&45 ++ 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) + + Channel parameters can be set for each enabled channel. + A maximum of 4 channels can be enabled (letters a thru d). +--- a/arch/arm/boot/dts/overlays/ads1115-overlay.dts ++++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts +@@ -9,23 +9,6 @@ + compatible = "brcm,bcm2835"; + + fragment@0 { +- target = <&i2c_arm>; +- __overlay__ { +- #address-cells = <1>; +- #size-cells = <0>; +- status = "okay"; +- +- ads1115: ads1115@48 { +- compatible = "ti,ads1115"; +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- reg = <0x48>; +- }; +- }; +- }; +- +- fragment@1 { + target = <&ads1115>; + __dormant__ { + #address-cells = <1>; +@@ -39,7 +22,7 @@ + }; + }; + +- fragment@2 { ++ fragment@1 { + target = <&ads1115>; + __dormant__ { + #address-cells = <1>; +@@ -53,7 +36,7 @@ + }; + }; + +- fragment@3 { ++ fragment@2 { + target = <&ads1115>; + __dormant__ { + #address-cells = <1>; +@@ -67,7 +50,7 @@ + }; + }; + +- fragment@4 { ++ fragment@3 { + target = <&ads1115>; + __dormant__ { + #address-cells = <1>; +@@ -81,23 +64,72 @@ + }; + }; + ++ fragment@4 { ++ target = <&i2cbus>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ ads1115: ads1115@48 { ++ compatible = "ti,ads1115"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x48>; ++ }; ++ }; ++ }; ++ ++ frag100: fragment@100 { ++ target = <&i2c1>; ++ i2cbus: __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@101 { ++ target = <&i2c0if>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@102 { ++ target = <&i2c0mux>; ++ __dormant__ { ++ status = "okay"; ++ }; ++ }; ++ + __overrides__ { + addr = <&ads1115>,"reg:0"; +- cha_enable = <0>,"=1"; ++ cha_enable = <0>,"=0"; + cha_cfg = <&channel_a>,"reg:0"; + cha_gain = <&channel_a>,"ti,gain:0"; + cha_datarate = <&channel_a>,"ti,datarate:0"; +- chb_enable = <0>,"=2"; ++ chb_enable = <0>,"=1"; + chb_cfg = <&channel_b>,"reg:0"; + chb_gain = <&channel_b>,"ti,gain:0"; + chb_datarate = <&channel_b>,"ti,datarate:0"; +- chc_enable = <0>,"=3"; ++ chc_enable = <0>,"=2"; + chc_cfg = <&channel_c>,"reg:0"; + chc_gain = <&channel_c>,"ti,gain:0"; + chc_datarate = <&channel_c>,"ti,datarate:0"; +- chd_enable = <0>,"=4"; ++ chd_enable = <0>,"=3"; + chd_cfg = <&channel_d>,"reg:0"; + chd_gain = <&channel_d>,"ti,gain:0"; + chd_datarate = <&channel_d>,"ti,datarate:0"; ++ i2c0 = <&frag100>, "target:0=",<&i2c0>; ++ i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>, ++ <0>,"+101+102"; ++ i2c3 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c3"; ++ i2c4 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c4"; ++ i2c5 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c5"; ++ i2c6 = <&frag100>, "target?=0", ++ <&frag100>, "target-path=i2c6"; + }; + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1186-dts-bcm2712-put-usb-under-axi-not-soc.patch b/target/linux/bcm27xx/patches-6.1/950-1186-dts-bcm2712-put-usb-under-axi-not-soc.patch new file mode 100644 index 0000000000..b66265f5a1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1186-dts-bcm2712-put-usb-under-axi-not-soc.patch @@ -0,0 +1,59 @@ +From 82069a7a02632aa60fa5c69415bf891ede7d6fd4 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Tue, 5 Dec 2023 16:55:17 +0000 +Subject: [PATCH] dts: bcm2712: put usb under /axi not /soc + +On 2712, the DWC USB controller is no longer attached to the Videocore +30-bit bus with its associated aliases, and can see the bottom 4GB of +RAM directly. + +Ideally it should make use of IOMMU6 but for now software bounce buffers +get it working. + +Signed-off-by: Jonathan Bell +--- + arch/arm/boot/dts/bcm2712.dtsi | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +--- a/arch/arm/boot/dts/bcm2712.dtsi ++++ b/arch/arm/boot/dts/bcm2712.dtsi +@@ -133,19 +133,6 @@ + status = "disabled"; + }; + +- usb: usb@7c480000 { +- compatible = "brcm,bcm2835-usb"; +- reg = <0x7c480000 0x10000>; +- interrupts = ; +- #address-cells = <1>; +- #size-cells = <0>; +- clocks = <&clk_usb>; +- clock-names = "otg"; +- phys = <&usbphy>; +- phy-names = "usb2-phy"; +- status = "disabled"; +- }; +- + mop: mop@7c500000 { + compatible = "brcm,bcm2712-mop"; + reg = <0x7c500000 0x20>; +@@ -1145,6 +1132,19 @@ + reg = <0x10 0x00400018 0x0 0x18>; + }; + ++ usb: usb@480000 { ++ compatible = "brcm,bcm2835-usb"; ++ reg = <0x10 0x00480000 0x0 0x10000>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clocks = <&clk_usb>; ++ clock-names = "otg"; ++ phys = <&usbphy>; ++ phy-names = "usb2-phy"; ++ status = "disabled"; ++ }; ++ + rpivid: codec@800000 { + compatible = "raspberrypi,rpivid-vid-decoder"; + reg = <0x10 0x00800000 0x0 0x10000>, /* HEVC */ diff --git a/target/linux/bcm27xx/patches-6.1/950-1187-drm-vc4-Correct-HVS-muxing-setup-for-the-moplet.patch b/target/linux/bcm27xx/patches-6.1/950-1187-drm-vc4-Correct-HVS-muxing-setup-for-the-moplet.patch new file mode 100644 index 0000000000..be02fd27fa --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1187-drm-vc4-Correct-HVS-muxing-setup-for-the-moplet.patch @@ -0,0 +1,26 @@ +From 01139e4e9141d031c6f4f00371e5eb52fa78839e Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 5 Dec 2023 18:28:19 +0000 +Subject: [PATCH] drm/vc4: Correct HVS muxing setup for the moplet + +The moplet registers as VC4_ENCODER_TYPE_TXP1 and can be +fed from mux output 2 of HVS channel 1. + +Correct the option which checked for VC4_ENCODER_TYPE_TXP0 + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_kms.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_kms.c ++++ b/drivers/gpu/drm/vc4/vc4_kms.c +@@ -365,7 +365,7 @@ static void vc6_hvs_pv_muxing_commit(str + mux = 0; + break; + +- case VC4_ENCODER_TYPE_TXP0: ++ case VC4_ENCODER_TYPE_TXP1: + mux = 2; + break; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1188-drm-vc4-Mop-and-moplet-have-different-register-offse.patch b/target/linux/bcm27xx/patches-6.1/950-1188-drm-vc4-Mop-and-moplet-have-different-register-offse.patch new file mode 100644 index 0000000000..f1bb26a26b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1188-drm-vc4-Mop-and-moplet-have-different-register-offse.patch @@ -0,0 +1,68 @@ +From cc948130d3e1c70ef21ae9963b56e0d500cef70b Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 5 Dec 2023 18:29:34 +0000 +Subject: [PATCH] drm/vc4: Mop and moplet have different register offsets for + high addr + +MOP uses register offset 0x24 for the high bits of the address, +whilst Moplet uses 0x1c. + +Handle this difference between the block types. + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_txp.c | 8 ++++++-- + 2 files changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -564,6 +564,7 @@ struct vc4_crtc_data { + struct vc4_txp_data { + struct vc4_crtc_data base; + enum vc4_encoder_type encoder_type; ++ unsigned int high_addr_ptr_reg; + unsigned int has_byte_enable:1; + unsigned int size_minus_one:1; + unsigned int supports_40bit_addresses:1; +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -145,7 +145,8 @@ + /* Number of lines received and committed to memory. */ + #define TXP_PROGRESS 0x10 + +-#define TXP_DST_PTR_HIGH 0x1c ++#define TXP_DST_PTR_HIGH_MOPLET 0x1c ++#define TXP_DST_PTR_HIGH_MOP 0x24 + + #define TXP_READ(offset) \ + ({ \ +@@ -338,10 +339,11 @@ static void vc4_txp_connector_atomic_com + + gem = drm_fb_dma_get_gem_obj(fb, 0); + addr = gem->dma_addr + fb->offsets[0]; ++ + TXP_WRITE(TXP_DST_PTR, lower_32_bits(addr)); + + if (txp_data->supports_40bit_addresses) +- TXP_WRITE(TXP_DST_PTR_HIGH, upper_32_bits(addr) & 0xff); ++ TXP_WRITE(txp_data->high_addr_ptr_reg, upper_32_bits(addr) & 0xff); + + TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]); + +@@ -520,6 +522,7 @@ const struct vc4_txp_data bcm2712_mop_da + .hvs_output = 2, + }, + .encoder_type = VC4_ENCODER_TYPE_TXP0, ++ .high_addr_ptr_reg = TXP_DST_PTR_HIGH_MOP, + .has_byte_enable = true, + .size_minus_one = true, + .supports_40bit_addresses = true, +@@ -533,6 +536,7 @@ const struct vc4_txp_data bcm2712_moplet + .hvs_output = 4, + }, + .encoder_type = VC4_ENCODER_TYPE_TXP1, ++ .high_addr_ptr_reg = TXP_DST_PTR_HIGH_MOPLET, + .size_minus_one = true, + .supports_40bit_addresses = true, + }; diff --git a/target/linux/bcm27xx/patches-6.1/950-1189-arm-dt-bcm2712-Correct-the-size-of-the-register-rang.patch b/target/linux/bcm27xx/patches-6.1/950-1189-arm-dt-bcm2712-Correct-the-size-of-the-register-rang.patch new file mode 100644 index 0000000000..ece5c716e7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1189-arm-dt-bcm2712-Correct-the-size-of-the-register-rang.patch @@ -0,0 +1,25 @@ +From 36593e2e27769d635ef18301f25b5e219a23949a Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Tue, 5 Dec 2023 18:31:25 +0000 +Subject: [PATCH] arm: dt: bcm2712: Correct the size of the register range for + MOP + +The Mop covers 0x28 bytes of registers, so ensure the range is +defined appropriately. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/bcm2712.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm2712.dtsi ++++ b/arch/arm/boot/dts/bcm2712.dtsi +@@ -135,7 +135,7 @@ + + mop: mop@7c500000 { + compatible = "brcm,bcm2712-mop"; +- reg = <0x7c500000 0x20>; ++ reg = <0x7c500000 0x28>; + interrupt-parent = <&disp_intr>; + interrupts = <1>; + status = "disabled"; diff --git a/target/linux/bcm27xx/patches-6.1/950-1192-media-Add-MIPI-CCI-register-access-helper-functions.patch b/target/linux/bcm27xx/patches-6.1/950-1192-media-Add-MIPI-CCI-register-access-helper-functions.patch new file mode 100644 index 0000000000..3305e66986 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1192-media-Add-MIPI-CCI-register-access-helper-functions.patch @@ -0,0 +1,388 @@ +From ae0e1b70f675f6ac7966e427f0d8f57812dbc312 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 27 Jun 2023 14:51:04 +0200 +Subject: [PATCH] media: Add MIPI CCI register access helper functions + +The CSI2 specification specifies a standard method to access camera sensor +registers called "Camera Control Interface (CCI)". + +This uses either 8 or 16 bit (big-endian wire order) register addresses +and supports 8, 16, 24 or 32 bit (big-endian wire order) register widths. + +Currently a lot of Linux camera sensor drivers all have their own custom +helpers for this, often copy and pasted from other drivers. + +Add a set of generic helpers for this so that all sensor drivers can +switch to a single common implementation. + +These helpers take an extra optional "int *err" function parameter, +this can be used to chain a bunch of register accesses together with +only a single error check at the end, rather than needing to error +check each individual register access. The first failing call will +set the contents of err to a non 0 value and all other calls will +then become no-ops. + +Link: https://lore.kernel.org/linux-media/59aefa7f-7bf9-6736-6040-39551329cd0a@redhat.com/ + +Reviewed-by: Andy Shevchenko +Tested-by: Tommaso Merciai +Reviewed-by: Tommaso Merciai +Signed-off-by: Hans de Goede +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 613cbb91e9cee7cf5a61f0816d2acab7bc117407) +--- + Documentation/driver-api/media/v4l2-cci.rst | 5 + + Documentation/driver-api/media/v4l2-core.rst | 1 + + drivers/media/v4l2-core/Kconfig | 9 + + drivers/media/v4l2-core/Makefile | 1 + + drivers/media/v4l2-core/v4l2-cci.c | 166 +++++++++++++++++++ + include/media/v4l2-cci.h | 125 ++++++++++++++ + 6 files changed, 307 insertions(+) + create mode 100644 Documentation/driver-api/media/v4l2-cci.rst + create mode 100644 drivers/media/v4l2-core/v4l2-cci.c + create mode 100644 include/media/v4l2-cci.h + +--- /dev/null ++++ b/Documentation/driver-api/media/v4l2-cci.rst +@@ -0,0 +1,5 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++V4L2 CCI kAPI ++^^^^^^^^^^^^^ ++.. kernel-doc:: include/media/v4l2-cci.h +--- a/Documentation/driver-api/media/v4l2-core.rst ++++ b/Documentation/driver-api/media/v4l2-core.rst +@@ -22,6 +22,7 @@ Video4Linux devices + v4l2-mem2mem + v4l2-async + v4l2-fwnode ++ v4l2-cci + v4l2-rect + v4l2-tuner + v4l2-common +--- a/drivers/media/v4l2-core/Kconfig ++++ b/drivers/media/v4l2-core/Kconfig +@@ -74,6 +74,15 @@ config V4L2_FWNODE + config V4L2_ASYNC + tristate + ++config V4L2_CCI ++ tristate ++ ++config V4L2_CCI_I2C ++ tristate ++ depends on I2C ++ select REGMAP_I2C ++ select V4L2_CCI ++ + # Used by drivers that need Videobuf modules + config VIDEOBUF_GEN + tristate +--- a/drivers/media/v4l2-core/Makefile ++++ b/drivers/media/v4l2-core/Makefile +@@ -25,6 +25,7 @@ videodev-$(CONFIG_VIDEO_V4L2_I2C) += v4l + # (e. g. LC_ALL=C sort Makefile) + + obj-$(CONFIG_V4L2_ASYNC) += v4l2-async.o ++obj-$(CONFIG_V4L2_CCI) += v4l2-cci.o + obj-$(CONFIG_V4L2_FLASH_LED_CLASS) += v4l2-flash-led-class.o + obj-$(CONFIG_V4L2_FWNODE) += v4l2-fwnode.o + obj-$(CONFIG_V4L2_H264) += v4l2-h264.o +--- /dev/null ++++ b/drivers/media/v4l2-core/v4l2-cci.c +@@ -0,0 +1,166 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * MIPI Camera Control Interface (CCI) register access helpers. ++ * ++ * Copyright (C) 2023 Hans de Goede ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) ++{ ++ unsigned int len; ++ u8 buf[8]; ++ int ret; ++ ++ if (err && *err) ++ return *err; ++ ++ len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); ++ reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); ++ ++ ret = regmap_bulk_read(map, reg, buf, len); ++ if (ret) { ++ dev_err(regmap_get_device(map), "Error reading reg 0x%4x: %d\n", ++ reg, ret); ++ goto out; ++ } ++ ++ switch (len) { ++ case 1: ++ *val = buf[0]; ++ break; ++ case 2: ++ *val = get_unaligned_be16(buf); ++ break; ++ case 3: ++ *val = get_unaligned_be24(buf); ++ break; ++ case 4: ++ *val = get_unaligned_be32(buf); ++ break; ++ case 8: ++ *val = get_unaligned_be64(buf); ++ break; ++ default: ++ dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n", ++ len, reg); ++ ret = -EINVAL; ++ break; ++ } ++ ++out: ++ if (ret && err) ++ *err = ret; ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(cci_read); ++ ++int cci_write(struct regmap *map, u32 reg, u64 val, int *err) ++{ ++ unsigned int len; ++ u8 buf[8]; ++ int ret; ++ ++ if (err && *err) ++ return *err; ++ ++ len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); ++ reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); ++ ++ switch (len) { ++ case 1: ++ buf[0] = val; ++ break; ++ case 2: ++ put_unaligned_be16(val, buf); ++ break; ++ case 3: ++ put_unaligned_be24(val, buf); ++ break; ++ case 4: ++ put_unaligned_be32(val, buf); ++ break; ++ case 8: ++ put_unaligned_be64(val, buf); ++ break; ++ default: ++ dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n", ++ len, reg); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ ret = regmap_bulk_write(map, reg, buf, len); ++ if (ret) ++ dev_err(regmap_get_device(map), "Error writing reg 0x%4x: %d\n", ++ reg, ret); ++ ++out: ++ if (ret && err) ++ *err = ret; ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(cci_write); ++ ++int cci_update_bits(struct regmap *map, u32 reg, u64 mask, u64 val, int *err) ++{ ++ u64 readval; ++ int ret; ++ ++ ret = cci_read(map, reg, &readval, err); ++ if (ret) ++ return ret; ++ ++ val = (readval & ~mask) | (val & mask); ++ ++ return cci_write(map, reg, val, err); ++} ++EXPORT_SYMBOL_GPL(cci_update_bits); ++ ++int cci_multi_reg_write(struct regmap *map, const struct cci_reg_sequence *regs, ++ unsigned int num_regs, int *err) ++{ ++ unsigned int i; ++ int ret; ++ ++ for (i = 0; i < num_regs; i++) { ++ ret = cci_write(map, regs[i].reg, regs[i].val, err); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(cci_multi_reg_write); ++ ++#if IS_ENABLED(CONFIG_V4L2_CCI_I2C) ++struct regmap *devm_cci_regmap_init_i2c(struct i2c_client *client, ++ int reg_addr_bits) ++{ ++ struct regmap_config config = { ++ .reg_bits = reg_addr_bits, ++ .val_bits = 8, ++ .reg_format_endian = REGMAP_ENDIAN_BIG, ++ .disable_locking = true, ++ }; ++ ++ return devm_regmap_init_i2c(client, &config); ++} ++EXPORT_SYMBOL_GPL(devm_cci_regmap_init_i2c); ++#endif ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Hans de Goede "); ++MODULE_DESCRIPTION("MIPI Camera Control Interface (CCI) support"); +--- /dev/null ++++ b/include/media/v4l2-cci.h +@@ -0,0 +1,125 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * MIPI Camera Control Interface (CCI) register access helpers. ++ * ++ * Copyright (C) 2023 Hans de Goede ++ */ ++#ifndef _V4L2_CCI_H ++#define _V4L2_CCI_H ++ ++#include ++ ++struct i2c_client; ++struct regmap; ++ ++/** ++ * struct cci_reg_sequence - An individual write from a sequence of CCI writes ++ * ++ * @reg: Register address, use CCI_REG#() macros to encode reg width ++ * @val: Register value ++ * ++ * Register/value pairs for sequences of writes. ++ */ ++struct cci_reg_sequence { ++ u32 reg; ++ u64 val; ++}; ++ ++/* ++ * Macros to define register address with the register width encoded ++ * into the higher bits. ++ */ ++#define CCI_REG_ADDR_MASK GENMASK(15, 0) ++#define CCI_REG_WIDTH_SHIFT 16 ++#define CCI_REG_WIDTH_MASK GENMASK(19, 16) ++ ++#define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG32(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG64(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x)) ++ ++/** ++ * cci_read() - Read a value from a single CCI register ++ * ++ * @map: Register map to read from ++ * @reg: Register address to read, use CCI_REG#() macros to encode reg width ++ * @val: Pointer to store read value ++ * @err: Optional pointer to store errors, if a previous error is set ++ * then the read will be skipped ++ * ++ * Return: %0 on success or a negative error code on failure. ++ */ ++int cci_read(struct regmap *map, u32 reg, u64 *val, int *err); ++ ++/** ++ * cci_write() - Write a value to a single CCI register ++ * ++ * @map: Register map to write to ++ * @reg: Register address to write, use CCI_REG#() macros to encode reg width ++ * @val: Value to be written ++ * @err: Optional pointer to store errors, if a previous error is set ++ * then the write will be skipped ++ * ++ * Return: %0 on success or a negative error code on failure. ++ */ ++int cci_write(struct regmap *map, u32 reg, u64 val, int *err); ++ ++/** ++ * cci_update_bits() - Perform a read/modify/write cycle on ++ * a single CCI register ++ * ++ * @map: Register map to update ++ * @reg: Register address to update, use CCI_REG#() macros to encode reg width ++ * @mask: Bitmask to change ++ * @val: New value for bitmask ++ * @err: Optional pointer to store errors, if a previous error is set ++ * then the update will be skipped ++ * ++ * Note this uses read-modify-write to update the bits, atomicity with regards ++ * to other cci_*() register access functions is NOT guaranteed. ++ * ++ * Return: %0 on success or a negative error code on failure. ++ */ ++int cci_update_bits(struct regmap *map, u32 reg, u64 mask, u64 val, int *err); ++ ++/** ++ * cci_multi_reg_write() - Write multiple registers to the device ++ * ++ * @map: Register map to write to ++ * @regs: Array of structures containing register-address, -value pairs to be ++ * written, register-addresses use CCI_REG#() macros to encode reg width ++ * @num_regs: Number of registers to write ++ * @err: Optional pointer to store errors, if a previous error is set ++ * then the write will be skipped ++ * ++ * Write multiple registers to the device where the set of register, value ++ * pairs are supplied in any order, possibly not all in a single range. ++ * ++ * Use of the CCI_REG#() macros to encode reg width is mandatory. ++ * ++ * For raw lists of register-address, -value pairs with only 8 bit ++ * wide writes regmap_multi_reg_write() can be used instead. ++ * ++ * Return: %0 on success or a negative error code on failure. ++ */ ++int cci_multi_reg_write(struct regmap *map, const struct cci_reg_sequence *regs, ++ unsigned int num_regs, int *err); ++ ++#if IS_ENABLED(CONFIG_V4L2_CCI_I2C) ++/** ++ * devm_cci_regmap_init_i2c() - Create regmap to use with cci_*() register ++ * access functions ++ * ++ * @client: i2c_client to create the regmap for ++ * @reg_addr_bits: register address width to use (8 or 16) ++ * ++ * Note the memory for the created regmap is devm() managed, tied to the client. ++ * ++ * Return: %0 on success or a negative error code on failure. ++ */ ++struct regmap *devm_cci_regmap_init_i2c(struct i2c_client *client, ++ int reg_addr_bits); ++#endif ++ ++#endif diff --git a/target/linux/bcm27xx/patches-6.1/950-1193-media-dt-bindings-Add-OmniVision-OV64A40.patch b/target/linux/bcm27xx/patches-6.1/950-1193-media-dt-bindings-Add-OmniVision-OV64A40.patch new file mode 100644 index 0000000000..649e8bc393 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1193-media-dt-bindings-Add-OmniVision-OV64A40.patch @@ -0,0 +1,114 @@ +From 3d108604ca669b83bb4918c4f5f0a02ddef84972 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Sun, 1 Oct 2023 13:20:12 +0200 +Subject: [PATCH] media: dt-bindings: Add OmniVision OV64A40 + +Add bindings for OmniVision OV64A40. + +Signed-off-by: Jacopo Mondi +--- + .../bindings/media/i2c/ovti,ov64a40.yaml | 98 +++++++++++++++++++ + 1 file changed, 98 insertions(+) + create mode 100644 Documentation/devicetree/bindings/media/i2c/ovti,ov64a40.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov64a40.yaml +@@ -0,0 +1,98 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/media/i2c/ovti,ov64a40.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: OmniVision OV64A40 Image Sensor ++ ++maintainers: ++ - Jacopo Mondi ++ ++allOf: ++ - $ref: /schemas/media/video-interface-devices.yaml# ++ ++properties: ++ compatible: ++ const: ovti,ov64a40 ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ maxItems: 1 ++ ++ avdd-supply: ++ description: Analog voltage supply, 2.8 volts ++ ++ dvdd-supply: ++ description: Digital core voltage supply, 1.1 volts ++ ++ dovdd-supply: ++ description: Digital I/O voltage supply, 1.8 volts ++ ++ powerdown-gpios: ++ maxItems: 1 ++ ++ reset-gpios: ++ maxItems: 1 ++ ++ port: ++ $ref: /schemas/graph.yaml#/$defs/port-base ++ additionalProperties: false ++ ++ properties: ++ endpoint: ++ $ref: /schemas/media/video-interfaces.yaml# ++ additionalProperties: false ++ ++ properties: ++ bus-type: ++ enum: ++ - 1 # MIPI CSI-2 C-PHY ++ - 4 # MIPI CSI-2 D-PHY ++ data-lanes: true ++ link-frequencies: true ++ clock-noncontinuous: true ++ remote-endpoint: true ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - port ++ ++unevaluatedProperties: false ++ ++examples: ++ - | ++ #include ++ ++ i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ camera@36 { ++ compatible = "ovti,ov64a40"; ++ reg = <0x36>; ++ clocks = <&camera_clk>; ++ dovdd-supply = <&vgen4_reg>; ++ avdd-supply = <&vgen3_reg>; ++ dvdd-supply = <&vgen2_reg>; ++ powerdown-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; ++ reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; ++ rotation = <180>; ++ orientation = <2>; ++ ++ port { ++ endpoint { ++ remote-endpoint = <&mipi_csi2_in>; ++ bus-type = <4>; ++ data-lanes = <1 2 3 4>; ++ link-frequencies = /bits/ 64 <456000000>; ++ }; ++ }; ++ }; ++ }; ++ ++... diff --git a/target/linux/bcm27xx/patches-6.1/950-1194-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch b/target/linux/bcm27xx/patches-6.1/950-1194-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch new file mode 100644 index 0000000000..82eda14173 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1194-media-dt-bindings-i2c-Add-Rohm-BU64754-bindings.patch @@ -0,0 +1,83 @@ +From 31c2999e543c245f7b96af3e73cd18e1036bfe7b Mon Sep 17 00:00:00 2001 +From: Kieran Bingham +Date: Thu, 14 Sep 2023 17:03:24 +0100 +Subject: [PATCH] media: dt-bindings: i2c: Add Rohm BU64754 bindings + +Add YAML device tree bindings for the ROHM BU64754 VCM Motor Driver for +Camera Autofocus. + +Signed-off-by: Kieran Bingham +Signed-off-by: Jacopo Mondi +--- + .../bindings/media/i2c/rohm,bu64754.yaml | 48 +++++++++++++++++++ + MAINTAINERS | 7 +++ + 2 files changed, 55 insertions(+) + create mode 100644 Documentation/devicetree/bindings/media/i2c/rohm,bu64754.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/media/i2c/rohm,bu64754.yaml +@@ -0,0 +1,48 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++# Copyright (C) 2023 Ideas on Board Oy. ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/media/i2c/rohm,bu64754.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: ROHM BU64754 Actuator Driver for Camera Autofocus ++ ++maintainers: ++ - Kieran Bingham ++ ++description: | ++ The BU64754GWZ is an actuator driver IC which can control the actuator ++ position precisely using an internal Hall Sensor. ++ ++properties: ++ compatible: ++ items: ++ - enum: ++ - rohm,bu64754 ++ ++ reg: ++ maxItems: 1 ++ ++ vdd-supply: ++ description: ++ Definition of the regulator used as VDD power supply to the driver. ++ ++required: ++ - compatible ++ - reg ++ ++additionalProperties: false ++ ++examples: ++ - | ++ i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ lens@76 { ++ compatible = "rohm,bu64754"; ++ reg = <0x76>; ++ vdd-supply = <&cam1_reg>; ++ }; ++ }; ++... +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -17895,6 +17895,13 @@ S: Maintained + F: Documentation/devicetree/bindings/iio/light/bh1750.yaml + F: drivers/iio/light/bh1750.c + ++ROHM BU64754 MOTOR DRIVER FOR CAMERA AUTOFOCUS ++M: Kieran Bingham ++L: linux-media@vger.kernel.org ++S: Maintained ++T: git git://linuxtv.org/media_tree.git ++F: Documentation/devicetree/bindings/media/i2c/rohm,bu64754.yaml ++ + ROHM MULTIFUNCTION BD9571MWV-M PMIC DEVICE DRIVERS + M: Marek Vasut + L: linux-kernel@vger.kernel.org diff --git a/target/linux/bcm27xx/patches-6.1/950-1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch b/target/linux/bcm27xx/patches-6.1/950-1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch new file mode 100644 index 0000000000..2f3ea4b072 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1195-media-i2c-Add-driver-for-OmniVision-OV64A40.patch @@ -0,0 +1,3763 @@ +From 87e3fcaad3017bdc91a7a79d2d1c874422ef87b0 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Thu, 20 Jul 2023 11:44:40 +0200 +Subject: [PATCH] media: i2c: Add driver for OmniVision OV64A40 + +Add a driver for the OmniVision OV64A40 image sensor. + +Signed-off-by: Jacopo Mondi +--- + MAINTAINERS | 8 + + drivers/media/i2c/Kconfig | 14 + + drivers/media/i2c/Makefile | 1 + + drivers/media/i2c/ov64a40.c | 3694 +++++++++++++++++++++++++++++++++++ + 4 files changed, 3717 insertions(+) + create mode 100644 drivers/media/i2c/ov64a40.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -15321,6 +15321,14 @@ S: Maintained + T: git git://linuxtv.org/media_tree.git + F: drivers/media/i2c/ov5695.c + ++OMNIVISION OV64A40 SENSOR DRIVER ++M: Jacopo Mondi ++L: linux-media@vger.kernel.org ++S: Maintained ++T: git git://linuxtv.org/media_tree.git ++F: Documentation/devicetree/bindings/media/i2c/ovti,ov64a40.yaml ++F: drivers/media/i2c/ov64a40.c ++ + OMNIVISION OV7670 SENSOR DRIVER + L: linux-media@vger.kernel.org + S: Orphan +--- a/drivers/media/i2c/Kconfig ++++ b/drivers/media/i2c/Kconfig +@@ -631,6 +631,20 @@ config VIDEO_OV5695 + To compile this driver as a module, choose M here: the + module will be called ov5695. + ++config VIDEO_OV64A40 ++ tristate "OmniVision OV64A40 sensor support" ++ depends on I2C && VIDEO_DEV ++ select MEDIA_CONTROLLER ++ select VIDEO_V4L2_SUBDEV_API ++ select V4L2_FWNODE ++ select V4L2_CCI_I2C ++ help ++ This is a Video4Linux2 sensor driver for the OmniVision ++ OV64A40 camera. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ov64a40. ++ + config VIDEO_OV6650 + tristate "OmniVision OV6650 sensor support" + depends on I2C && VIDEO_DEV +--- a/drivers/media/i2c/Makefile ++++ b/drivers/media/i2c/Makefile +@@ -96,6 +96,7 @@ obj-$(CONFIG_VIDEO_OV5670) += ov5670.o + obj-$(CONFIG_VIDEO_OV5675) += ov5675.o + obj-$(CONFIG_VIDEO_OV5693) += ov5693.o + obj-$(CONFIG_VIDEO_OV5695) += ov5695.o ++obj-$(CONFIG_VIDEO_OV64A40) += ov64a40.o + obj-$(CONFIG_VIDEO_OV6650) += ov6650.o + obj-$(CONFIG_VIDEO_OV7251) += ov7251.o + obj-$(CONFIG_VIDEO_OV7640) += ov7640.o +--- /dev/null ++++ b/drivers/media/i2c/ov64a40.c +@@ -0,0 +1,3694 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * V4L2 sensor driver for OmniVision OV64A40 ++ * ++ * Copyright (C) 2023 Ideas On Board Oy ++ * Copyright (C) 2023 Arducam ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define OV64A40_XCLK_FREQ 24000000 ++ ++#define OV64A40_NATIVE_WIDTH 9286 ++#define OV64A40_NATIVE_HEIGHT 6976 ++#define OV64A40_PIXEL_ARRAY_TOP 0 ++#define OV64A40_PIXEL_ARRAY_LEFT 0 ++#define OV64A40_PIXEL_ARRAY_WIDTH 9248 ++#define OV64A40_PIXEL_ARRAY_HEIGHT 6944 ++ ++#define OV64A40_PIXEL_RATE 300000000 ++ ++#define OV64A40_LINK_FREQ_360M 360000000 ++#define OV64A40_LINK_FREQ_456M 456000000 ++ ++#define OV64A40_PLL1_PRE_DIV0 CCI_REG8(0x0301) ++#define OV64A40_PLL1_PRE_DIV CCI_REG8(0x0303) ++#define OV64A40_PLL1_MULTIPLIER CCI_REG16(0x0304) ++#define OV64A40_PLL1_M_DIV CCI_REG8(0x0307) ++#define OV64A40_PLL2_SEL_BAK_SA1 CCI_REG8(0x0320) ++#define OV64A40_PLL2_PRE_DIV CCI_REG8(0x0323) ++#define OV64A40_PLL2_MULTIPLIER CCI_REG16(0x0324) ++#define OV64A40_PLL2_PRE_DIV0 CCI_REG8(0x0326) ++#define OV64A40_PLL2_DIVDAC CCI_REG8(0x0329) ++#define OV64A40_PLL2_DIVSP CCI_REG8(0x032d) ++#define OV64A40_PLL2_DACPREDIV CCI_REG8(0x032e) ++ ++/* TODO: validate vblank_min, it's not characterized in the datasheet. */ ++#define OV64A40_VBLANK_MIN 128 ++#define OV64A40_VTS_MAX 0xffffff ++ ++#define OV64A40_REG_MEC_LONG_EXPO CCI_REG24(0x3500) ++#define OV64A40_EXPOSURE_MIN 16 ++#define OV64A40_EXPOSURE_MARGIN 32 ++ ++#define OV64A40_REG_MEC_LONG_GAIN CCI_REG16(0x3508) ++#define OV64A40_ANA_GAIN_MIN 0x80 ++#define OV64A40_ANA_GAIN_MAX 0x7ff ++#define OV64A40_ANA_GAIN_DEFAULT 0x80 ++ ++#define OV64A40_REG_TIMING_CTRL0 CCI_REG16(0x3800) ++#define OV64A40_REG_TIMING_CTRL2 CCI_REG16(0x3802) ++#define OV64A40_REG_TIMING_CTRL4 CCI_REG16(0x3804) ++#define OV64A40_REG_TIMING_CTRL6 CCI_REG16(0x3806) ++#define OV64A40_REG_TIMING_CTRL8 CCI_REG16(0x3808) ++#define OV64A40_REG_TIMING_CTRLA CCI_REG16(0x380a) ++#define OV64A40_REG_TIMING_CTRLC CCI_REG16(0x380c) ++#define OV64A40_REG_TIMING_CTRLE CCI_REG16(0x380e) ++#define OV64A40_REG_TIMING_CTRL10 CCI_REG16(0x3810) ++#define OV64A40_REG_TIMING_CTRL12 CCI_REG16(0x3812) ++ ++/* ++ * Careful: a typo in the datasheet calls this register ++ * OV64A40_REG_TIMING_CTRL20. ++ */ ++#define OV64A40_REG_TIMING_CTRL14 CCI_REG8(0x3814) ++#define OV64A40_REG_TIMING_CTRL15 CCI_REG8(0x3815) ++#define OV64A40_ODD_INC_SHIFT 4 ++#define OV64A40_SKIPPING_CONFIG(_odd, _even) \ ++ (((_odd) << OV64A40_ODD_INC_SHIFT) | (_even)) ++ ++#define OV64A40_REG_TIMING_CTRL_20 CCI_REG8(0x3820) ++#define OV64A40_TIMING_CTRL_20_VFLIP BIT(2) ++#define OV64A40_TIMING_CTRL_20_VBIN BIT(1) ++ ++#define OV64A40_REG_TIMING_CTRL_21 CCI_REG8(0x3821) ++#define OV64A40_TIMING_CTRL_21_HBIN BIT(4) ++#define OV64A40_TIMING_CTRL_21_HFLIP BIT(2) ++#define OV64A40_TIMING_CTRL_21_DSPEED BIT(0) ++#define OV64A40_TIMING_CTRL_21_HBIN_CONF \ ++ (OV64A40_TIMING_CTRL_21_HBIN | \ ++ OV64A40_TIMING_CTRL_21_DSPEED) ++ ++#define OV64A40_REG_TIMINGS_VTS_HIGH CCI_REG8(0x3840) ++#define OV64A40_REG_TIMINGS_VTS_MID CCI_REG8(0x380e) ++#define OV64A40_REG_TIMINGS_VTS_LOW CCI_REG8(0x380f) ++ ++/* The test pattern control is weirdly named PRE_ISP_2325_D2V2_TOP_1 in TRM. */ ++#define OV64A40_REG_TEST_PATTERN CCI_REG8(0x50c1) ++#define OV64A40_TEST_PATTERN_DISABLED 0x00 ++#define OV64A40_TEST_PATTERN_TYPE1 BIT(0) ++#define OV64A40_TEST_PATTERN_TYPE2 (BIT(4) | BIT(0)) ++#define OV64A40_TEST_PATTERN_TYPE3 (BIT(5) | BIT(0)) ++#define OV64A40_TEST_PATTERN_TYPE4 (BIT(5) | BIT(4) | BIT(0)) ++ ++#define OV64A40_REG_CHIP_ID CCI_REG24(0x300a) ++#define OV64A40_CHIP_ID 0x566441 ++ ++#define OV64A40_REG_SMIA CCI_REG8(0x0100) ++#define OV64A40_REG_SMIA_STREAMING BIT(0) ++ ++enum ov64a40_link_freq_ids { ++ OV64A40_LINK_FREQ_456M_ID, ++ OV64A40_LINK_FREQ_360M_ID, ++ OV64A40_NUM_LINK_FREQ, ++}; ++ ++static const char * const ov64a40_supply_names[] = { ++ /* Supplies can be enabled in any order */ ++ "avdd", /* Analog (2.8V) supply */ ++ "dovdd", /* Digital Core (1.8V) supply */ ++ "dvdd", /* IF (1.1V) supply */ ++}; ++ ++static const char * const ov64a40_test_pattern_menu[] = { ++ "Disabled", ++ "Type1", ++ "Type2", ++ "Type3", ++ "Type4", ++}; ++ ++static const int ov64a40_test_pattern_val[] = { ++ OV64A40_TEST_PATTERN_DISABLED, ++ OV64A40_TEST_PATTERN_TYPE1, ++ OV64A40_TEST_PATTERN_TYPE2, ++ OV64A40_TEST_PATTERN_TYPE3, ++ OV64A40_TEST_PATTERN_TYPE4, ++}; ++ ++static const unsigned int ov64a40_mbus_codes[] = { ++ MEDIA_BUS_FMT_SBGGR10_1X10, ++ MEDIA_BUS_FMT_SGRBG10_1X10, ++ MEDIA_BUS_FMT_SGBRG10_1X10, ++ MEDIA_BUS_FMT_SRGGB10_1X10, ++}; ++ ++static const struct cci_reg_sequence ov64a40_init[] = { ++ { CCI_REG8(0x0103), 0x01 }, { CCI_REG8(0x0301), 0x88 }, ++ { CCI_REG8(0x0304), 0x00 }, { CCI_REG8(0x0305), 0x96 }, ++ { CCI_REG8(0x0306), 0x03 }, { CCI_REG8(0x0307), 0x00 }, ++ { CCI_REG8(0x0345), 0x2c }, { CCI_REG8(0x034a), 0x02 }, ++ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x0350), 0xc0 }, ++ { CCI_REG8(0x0360), 0x09 }, { CCI_REG8(0x3012), 0x31 }, ++ { CCI_REG8(0x3015), 0xf0 }, { CCI_REG8(0x3017), 0xf0 }, ++ { CCI_REG8(0x301d), 0xf6 }, { CCI_REG8(0x301e), 0xf1 }, ++ { CCI_REG8(0x3022), 0xf0 }, { CCI_REG8(0x3400), 0x08 }, ++ { CCI_REG8(0x3608), 0x41 }, { CCI_REG8(0x3421), 0x02 }, ++ { CCI_REG8(0x3500), 0x00 }, { CCI_REG8(0x3501), 0x00 }, ++ { CCI_REG8(0x3502), 0x18 }, { CCI_REG8(0x3504), 0x0c }, ++ { CCI_REG8(0x3508), 0x01 }, { CCI_REG8(0x3509), 0x00 }, ++ { CCI_REG8(0x350a), 0x01 }, { CCI_REG8(0x350b), 0x00 }, ++ { CCI_REG8(0x350b), 0x00 }, { CCI_REG8(0x3540), 0x00 }, ++ { CCI_REG8(0x3541), 0x00 }, { CCI_REG8(0x3542), 0x08 }, ++ { CCI_REG8(0x3548), 0x01 }, { CCI_REG8(0x3549), 0xa0 }, ++ { CCI_REG8(0x3549), 0x00 }, { CCI_REG8(0x3549), 0x00 }, ++ { CCI_REG8(0x3549), 0x00 }, { CCI_REG8(0x3580), 0x00 }, ++ { CCI_REG8(0x3581), 0x00 }, { CCI_REG8(0x3582), 0x04 }, ++ { CCI_REG8(0x3588), 0x01 }, { CCI_REG8(0x3589), 0xf0 }, ++ { CCI_REG8(0x3589), 0x00 }, { CCI_REG8(0x3589), 0x00 }, ++ { CCI_REG8(0x3589), 0x00 }, { CCI_REG8(0x360d), 0x83 }, ++ { CCI_REG8(0x3616), 0xa0 }, { CCI_REG8(0x3617), 0x31 }, ++ { CCI_REG8(0x3623), 0x10 }, { CCI_REG8(0x3633), 0x03 }, ++ { CCI_REG8(0x3634), 0x03 }, { CCI_REG8(0x3635), 0x77 }, ++ { CCI_REG8(0x3640), 0x19 }, { CCI_REG8(0x3641), 0x80 }, ++ { CCI_REG8(0x364d), 0x0f }, { CCI_REG8(0x3680), 0x80 }, ++ { CCI_REG8(0x3682), 0x00 }, { CCI_REG8(0x3683), 0x00 }, ++ { CCI_REG8(0x3684), 0x07 }, { CCI_REG8(0x3688), 0x01 }, ++ { CCI_REG8(0x3689), 0x08 }, { CCI_REG8(0x368a), 0x26 }, ++ { CCI_REG8(0x368b), 0xc8 }, { CCI_REG8(0x368e), 0x70 }, ++ { CCI_REG8(0x368f), 0x00 }, { CCI_REG8(0x3692), 0x04 }, ++ { CCI_REG8(0x3693), 0x00 }, { CCI_REG8(0x3696), 0xd1 }, ++ { CCI_REG8(0x3697), 0xe0 }, { CCI_REG8(0x3698), 0x80 }, ++ { CCI_REG8(0x3699), 0x2b }, { CCI_REG8(0x369a), 0x00 }, ++ { CCI_REG8(0x369d), 0x00 }, { CCI_REG8(0x369e), 0x14 }, ++ { CCI_REG8(0x369f), 0x20 }, { CCI_REG8(0x36a5), 0x80 }, ++ { CCI_REG8(0x36a6), 0x00 }, { CCI_REG8(0x36a7), 0x00 }, ++ { CCI_REG8(0x36a8), 0x00 }, { CCI_REG8(0x36b5), 0x17 }, ++ { CCI_REG8(0x3701), 0x30 }, { CCI_REG8(0x3706), 0x2b }, ++ { CCI_REG8(0x3709), 0x8d }, { CCI_REG8(0x370b), 0x4f }, ++ { CCI_REG8(0x3711), 0x00 }, { CCI_REG8(0x3712), 0x01 }, ++ { CCI_REG8(0x3713), 0x00 }, { CCI_REG8(0x3720), 0x08 }, ++ { CCI_REG8(0x3727), 0x22 }, { CCI_REG8(0x3728), 0x01 }, ++ { CCI_REG8(0x375e), 0x00 }, { CCI_REG8(0x3760), 0x08 }, ++ { CCI_REG8(0x3761), 0x10 }, { CCI_REG8(0x3762), 0x08 }, ++ { CCI_REG8(0x3765), 0x10 }, { CCI_REG8(0x3766), 0x18 }, ++ { CCI_REG8(0x376a), 0x08 }, { CCI_REG8(0x376b), 0x00 }, ++ { CCI_REG8(0x376d), 0x1b }, { CCI_REG8(0x3791), 0x2b }, ++ { CCI_REG8(0x3793), 0x2b }, { CCI_REG8(0x3795), 0x2b }, ++ { CCI_REG8(0x3797), 0x4f }, { CCI_REG8(0x3799), 0x4f }, ++ { CCI_REG8(0x379b), 0x4f }, { CCI_REG8(0x37a0), 0x22 }, ++ { CCI_REG8(0x37da), 0x04 }, { CCI_REG8(0x37f9), 0x02 }, ++ { CCI_REG8(0x37fa), 0x02 }, { CCI_REG8(0x37fb), 0x02 }, ++ { CCI_REG8(0x3814), 0x11 }, { CCI_REG8(0x3815), 0x11 }, ++ { CCI_REG8(0x3820), 0x40 }, { CCI_REG8(0x3821), 0x04 }, ++ { CCI_REG8(0x3822), 0x00 }, { CCI_REG8(0x3823), 0x04 }, ++ { CCI_REG8(0x3827), 0x08 }, { CCI_REG8(0x3828), 0x00 }, ++ { CCI_REG8(0x382a), 0x81 }, { CCI_REG8(0x382e), 0x70 }, ++ { CCI_REG8(0x3837), 0x10 }, { CCI_REG8(0x3839), 0x00 }, ++ { CCI_REG8(0x383b), 0x00 }, { CCI_REG8(0x383c), 0x00 }, ++ { CCI_REG8(0x383d), 0x10 }, { CCI_REG8(0x383f), 0x00 }, ++ { CCI_REG8(0x384c), 0x02 }, { CCI_REG8(0x384d), 0x8c }, ++ { CCI_REG8(0x3852), 0x00 }, { CCI_REG8(0x3856), 0x10 }, ++ { CCI_REG8(0x3857), 0x10 }, { CCI_REG8(0x3858), 0x20 }, ++ { CCI_REG8(0x3859), 0x20 }, { CCI_REG8(0x3894), 0x00 }, ++ { CCI_REG8(0x3895), 0x00 }, { CCI_REG8(0x3896), 0x00 }, ++ { CCI_REG8(0x3897), 0x00 }, { CCI_REG8(0x3900), 0x40 }, ++ { CCI_REG8(0x3aed), 0x6e }, { CCI_REG8(0x3af1), 0x73 }, ++ { CCI_REG8(0x3d86), 0x12 }, { CCI_REG8(0x3d87), 0x30 }, ++ { CCI_REG8(0x3d8c), 0xab }, { CCI_REG8(0x3d8d), 0xb0 }, ++ { CCI_REG8(0x3f00), 0x12 }, { CCI_REG8(0x3f00), 0x12 }, ++ { CCI_REG8(0x3f00), 0x12 }, { CCI_REG8(0x3f01), 0x03 }, ++ { CCI_REG8(0x4009), 0x01 }, { CCI_REG8(0x400e), 0xc6 }, ++ { CCI_REG8(0x400f), 0x00 }, { CCI_REG8(0x4010), 0x28 }, ++ { CCI_REG8(0x4011), 0x01 }, { CCI_REG8(0x4012), 0x0c }, ++ { CCI_REG8(0x4015), 0x00 }, { CCI_REG8(0x4016), 0x1f }, ++ { CCI_REG8(0x4017), 0x00 }, { CCI_REG8(0x4018), 0x07 }, ++ { CCI_REG8(0x401a), 0x40 }, { CCI_REG8(0x4028), 0x01 }, ++ { CCI_REG8(0x4504), 0x00 }, { CCI_REG8(0x4506), 0x01 }, ++ { CCI_REG8(0x4508), 0x00 }, { CCI_REG8(0x4509), 0x35 }, ++ { CCI_REG8(0x450a), 0x08 }, { CCI_REG8(0x450c), 0x00 }, ++ { CCI_REG8(0x450d), 0x20 }, { CCI_REG8(0x450e), 0x00 }, ++ { CCI_REG8(0x450f), 0x20 }, { CCI_REG8(0x451e), 0x00 }, ++ { CCI_REG8(0x451f), 0x00 }, { CCI_REG8(0x4523), 0x00 }, ++ { CCI_REG8(0x4526), 0x00 }, { CCI_REG8(0x4527), 0x18 }, ++ { CCI_REG8(0x4580), 0x01 }, { CCI_REG8(0x4583), 0x00 }, ++ { CCI_REG8(0x4584), 0x00 }, { CCI_REG8(0x45c0), 0xa1 }, ++ { CCI_REG8(0x4602), 0x08 }, { CCI_REG8(0x4603), 0x05 }, ++ { CCI_REG8(0x4606), 0x12 }, { CCI_REG8(0x4607), 0x30 }, ++ { CCI_REG8(0x460b), 0x00 }, { CCI_REG8(0x460d), 0x00 }, ++ { CCI_REG8(0x4640), 0x00 }, { CCI_REG8(0x4641), 0x24 }, ++ { CCI_REG8(0x4643), 0x08 }, { CCI_REG8(0x4645), 0x14 }, ++ { CCI_REG8(0x4648), 0x0a }, { CCI_REG8(0x4649), 0x06 }, ++ { CCI_REG8(0x464a), 0x00 }, { CCI_REG8(0x464b), 0x30 }, ++ { CCI_REG8(0x4800), 0x04 }, { CCI_REG8(0x4802), 0x02 }, ++ { CCI_REG8(0x480b), 0x10 }, { CCI_REG8(0x480c), 0x80 }, ++ { CCI_REG8(0x480e), 0x04 }, { CCI_REG8(0x480f), 0x32 }, ++ { CCI_REG8(0x481b), 0x12 }, { CCI_REG8(0x4833), 0x30 }, ++ { CCI_REG8(0x4837), 0x08 }, { CCI_REG8(0x484b), 0x27 }, ++ { CCI_REG8(0x4850), 0x42 }, { CCI_REG8(0x4851), 0xaa }, ++ { CCI_REG8(0x4860), 0x01 }, { CCI_REG8(0x4861), 0xec }, ++ { CCI_REG8(0x4862), 0x25 }, { CCI_REG8(0x4888), 0x00 }, ++ { CCI_REG8(0x4889), 0x03 }, { CCI_REG8(0x488c), 0x60 }, ++ { CCI_REG8(0x4910), 0x28 }, { CCI_REG8(0x4911), 0x01 }, ++ { CCI_REG8(0x4912), 0x0c }, { CCI_REG8(0x491a), 0x40 }, ++ { CCI_REG8(0x4915), 0x00 }, { CCI_REG8(0x4916), 0x0f }, ++ { CCI_REG8(0x4917), 0x00 }, { CCI_REG8(0x4918), 0x07 }, ++ { CCI_REG8(0x4a10), 0x28 }, { CCI_REG8(0x4a11), 0x01 }, ++ { CCI_REG8(0x4a12), 0x0c }, { CCI_REG8(0x4a1a), 0x40 }, ++ { CCI_REG8(0x4a15), 0x00 }, { CCI_REG8(0x4a16), 0x0f }, ++ { CCI_REG8(0x4a17), 0x00 }, { CCI_REG8(0x4a18), 0x07 }, ++ { CCI_REG8(0x4d00), 0x04 }, { CCI_REG8(0x4d01), 0x5a }, ++ { CCI_REG8(0x4d02), 0xbb }, { CCI_REG8(0x4d03), 0x84 }, ++ { CCI_REG8(0x4d04), 0xd1 }, { CCI_REG8(0x4d05), 0x68 }, ++ { CCI_REG8(0xc4fa), 0x10 }, { CCI_REG8(0x3b56), 0x0a }, ++ { CCI_REG8(0x3b57), 0x0a }, { CCI_REG8(0x3b58), 0x0c }, ++ { CCI_REG8(0x3b59), 0x10 }, { CCI_REG8(0x3a1d), 0x30 }, ++ { CCI_REG8(0x3a1e), 0x30 }, { CCI_REG8(0x3a21), 0x30 }, ++ { CCI_REG8(0x3a22), 0x30 }, { CCI_REG8(0x3992), 0x02 }, ++ { CCI_REG8(0x399e), 0x02 }, { CCI_REG8(0x39fb), 0x30 }, ++ { CCI_REG8(0x39fc), 0x30 }, { CCI_REG8(0x39fd), 0x30 }, ++ { CCI_REG8(0x39fe), 0x30 }, { CCI_REG8(0x3a6d), 0x83 }, ++ { CCI_REG8(0x3a5e), 0x83 }, { CCI_REG8(0xc500), 0x12 }, ++ { CCI_REG8(0xc501), 0x12 }, { CCI_REG8(0xc502), 0x12 }, ++ { CCI_REG8(0xc503), 0x12 }, { CCI_REG8(0xc505), 0x12 }, ++ { CCI_REG8(0xc506), 0x12 }, { CCI_REG8(0xc507), 0x12 }, ++ { CCI_REG8(0xc508), 0x12 }, { CCI_REG8(0x3a77), 0x12 }, ++ { CCI_REG8(0x3a73), 0x12 }, { CCI_REG8(0x3a7b), 0x12 }, ++ { CCI_REG8(0x3a7f), 0x12 }, { CCI_REG8(0x3b2e), 0x13 }, ++ { CCI_REG8(0x3b29), 0x13 }, { CCI_REG8(0xc439), 0x13 }, ++ { CCI_REG8(0xc469), 0x13 }, { CCI_REG8(0xc41c), 0x89 }, ++ { CCI_REG8(0x3618), 0x80 }, { CCI_REG8(0xc514), 0x51 }, ++ { CCI_REG8(0xc515), 0x2c }, { CCI_REG8(0xc516), 0x16 }, ++ { CCI_REG8(0xc517), 0x0d }, { CCI_REG8(0x3615), 0x7f }, ++ { CCI_REG8(0x3632), 0x99 }, { CCI_REG8(0x3642), 0x00 }, ++ { CCI_REG8(0x3645), 0x80 }, { CCI_REG8(0x3702), 0x2a }, ++ { CCI_REG8(0x3703), 0x2a }, { CCI_REG8(0x3708), 0x2f }, ++ { CCI_REG8(0x3721), 0x15 }, { CCI_REG8(0x3744), 0x28 }, ++ { CCI_REG8(0x3991), 0x0c }, { CCI_REG8(0x371d), 0x24 }, ++ { CCI_REG8(0x371f), 0x0c }, { CCI_REG8(0x374b), 0x03 }, ++ { CCI_REG8(0x37d0), 0x00 }, { CCI_REG8(0x391d), 0x55 }, ++ { CCI_REG8(0x391e), 0x52 }, { CCI_REG8(0x399d), 0x0c }, ++ { CCI_REG8(0x3a2f), 0x01 }, { CCI_REG8(0x3a30), 0x01 }, ++ { CCI_REG8(0x3a31), 0x01 }, { CCI_REG8(0x3a32), 0x01 }, ++ { CCI_REG8(0x3a34), 0x01 }, { CCI_REG8(0x3a35), 0x01 }, ++ { CCI_REG8(0x3a36), 0x01 }, { CCI_REG8(0x3a37), 0x01 }, ++ { CCI_REG8(0x3a43), 0x01 }, { CCI_REG8(0x3a44), 0x01 }, ++ { CCI_REG8(0x3a45), 0x01 }, { CCI_REG8(0x3a46), 0x01 }, ++ { CCI_REG8(0x3a48), 0x01 }, { CCI_REG8(0x3a49), 0x01 }, ++ { CCI_REG8(0x3a4a), 0x01 }, { CCI_REG8(0x3a4b), 0x01 }, ++ { CCI_REG8(0x3a50), 0x14 }, { CCI_REG8(0x3a54), 0x14 }, ++ { CCI_REG8(0x3a60), 0x20 }, { CCI_REG8(0x3a6f), 0x20 }, ++ { CCI_REG8(0x3ac5), 0x01 }, { CCI_REG8(0x3ac6), 0x01 }, ++ { CCI_REG8(0x3ac7), 0x01 }, { CCI_REG8(0x3ac8), 0x01 }, ++ { CCI_REG8(0x3ac9), 0x01 }, { CCI_REG8(0x3aca), 0x01 }, ++ { CCI_REG8(0x3acb), 0x01 }, { CCI_REG8(0x3acc), 0x01 }, ++ { CCI_REG8(0x3acd), 0x01 }, { CCI_REG8(0x3ace), 0x01 }, ++ { CCI_REG8(0x3acf), 0x01 }, { CCI_REG8(0x3ad0), 0x01 }, ++ { CCI_REG8(0x3ad1), 0x01 }, { CCI_REG8(0x3ad2), 0x01 }, ++ { CCI_REG8(0x3ad3), 0x01 }, { CCI_REG8(0x3ad4), 0x01 }, ++ { CCI_REG8(0x3add), 0x1f }, { CCI_REG8(0x3adf), 0x24 }, ++ { CCI_REG8(0x3aef), 0x1f }, { CCI_REG8(0x3af0), 0x24 }, ++ { CCI_REG8(0x3b92), 0x08 }, { CCI_REG8(0x3b93), 0x08 }, ++ { CCI_REG8(0x3b94), 0x08 }, { CCI_REG8(0x3b95), 0x08 }, ++ { CCI_REG8(0x3be7), 0x1e }, { CCI_REG8(0x3be8), 0x26 }, ++ { CCI_REG8(0xc44a), 0x20 }, { CCI_REG8(0xc44c), 0x20 }, ++ { CCI_REG8(0xc483), 0x00 }, { CCI_REG8(0xc484), 0x00 }, ++ { CCI_REG8(0xc485), 0x00 }, { CCI_REG8(0xc486), 0x00 }, ++ { CCI_REG8(0xc487), 0x01 }, { CCI_REG8(0xc488), 0x01 }, ++ { CCI_REG8(0xc489), 0x01 }, { CCI_REG8(0xc48a), 0x01 }, ++ { CCI_REG8(0xc4c1), 0x00 }, { CCI_REG8(0xc4c2), 0x00 }, ++ { CCI_REG8(0xc4c3), 0x00 }, { CCI_REG8(0xc4c4), 0x00 }, ++ { CCI_REG8(0xc4c6), 0x10 }, { CCI_REG8(0xc4c7), 0x10 }, ++ { CCI_REG8(0xc4c8), 0x10 }, { CCI_REG8(0xc4c9), 0x10 }, ++ { CCI_REG8(0xc4ca), 0x10 }, { CCI_REG8(0xc4cb), 0x10 }, ++ { CCI_REG8(0xc4cc), 0x10 }, { CCI_REG8(0xc4cd), 0x10 }, ++ { CCI_REG8(0xc4ea), 0x07 }, { CCI_REG8(0xc4eb), 0x07 }, ++ { CCI_REG8(0xc4ec), 0x07 }, { CCI_REG8(0xc4ed), 0x07 }, ++ { CCI_REG8(0xc4ee), 0x07 }, { CCI_REG8(0xc4f6), 0x10 }, ++ { CCI_REG8(0xc4f7), 0x10 }, { CCI_REG8(0xc4f8), 0x10 }, ++ { CCI_REG8(0xc4f9), 0x10 }, { CCI_REG8(0xc518), 0x0e }, ++ { CCI_REG8(0xc519), 0x0e }, { CCI_REG8(0xc51a), 0x0e }, ++ { CCI_REG8(0xc51b), 0x0e }, { CCI_REG8(0xc51c), 0x0e }, ++ { CCI_REG8(0xc51d), 0x0e }, { CCI_REG8(0xc51e), 0x0e }, ++ { CCI_REG8(0xc51f), 0x0e }, { CCI_REG8(0xc520), 0x0e }, ++ { CCI_REG8(0xc521), 0x0e }, { CCI_REG8(0xc522), 0x0e }, ++ { CCI_REG8(0xc523), 0x0e }, { CCI_REG8(0xc524), 0x0e }, ++ { CCI_REG8(0xc525), 0x0e }, { CCI_REG8(0xc526), 0x0e }, ++ { CCI_REG8(0xc527), 0x0e }, { CCI_REG8(0xc528), 0x0e }, ++ { CCI_REG8(0xc529), 0x0e }, { CCI_REG8(0xc52a), 0x0e }, ++ { CCI_REG8(0xc52b), 0x0e }, { CCI_REG8(0xc52c), 0x0e }, ++ { CCI_REG8(0xc52d), 0x0e }, { CCI_REG8(0xc52e), 0x0e }, ++ { CCI_REG8(0xc52f), 0x0e }, { CCI_REG8(0xc530), 0x0e }, ++ { CCI_REG8(0xc531), 0x0e }, { CCI_REG8(0xc532), 0x0e }, ++ { CCI_REG8(0xc533), 0x0e }, { CCI_REG8(0xc534), 0x0e }, ++ { CCI_REG8(0xc535), 0x0e }, { CCI_REG8(0xc536), 0x0e }, ++ { CCI_REG8(0xc537), 0x0e }, { CCI_REG8(0xc538), 0x0e }, ++ { CCI_REG8(0xc539), 0x0e }, { CCI_REG8(0xc53a), 0x0e }, ++ { CCI_REG8(0xc53b), 0x0e }, { CCI_REG8(0xc53c), 0x0e }, ++ { CCI_REG8(0xc53d), 0x0e }, { CCI_REG8(0xc53e), 0x0e }, ++ { CCI_REG8(0xc53f), 0x0e }, { CCI_REG8(0xc540), 0x0e }, ++ { CCI_REG8(0xc541), 0x0e }, { CCI_REG8(0xc542), 0x0e }, ++ { CCI_REG8(0xc543), 0x0e }, { CCI_REG8(0xc544), 0x0e }, ++ { CCI_REG8(0xc545), 0x0e }, { CCI_REG8(0xc546), 0x0e }, ++ { CCI_REG8(0xc547), 0x0e }, { CCI_REG8(0xc548), 0x0e }, ++ { CCI_REG8(0xc549), 0x0e }, { CCI_REG8(0xc57f), 0x22 }, ++ { CCI_REG8(0xc580), 0x22 }, { CCI_REG8(0xc581), 0x22 }, ++ { CCI_REG8(0xc582), 0x22 }, { CCI_REG8(0xc583), 0x22 }, ++ { CCI_REG8(0xc584), 0x22 }, { CCI_REG8(0xc585), 0x22 }, ++ { CCI_REG8(0xc586), 0x22 }, { CCI_REG8(0xc587), 0x22 }, ++ { CCI_REG8(0xc588), 0x22 }, { CCI_REG8(0xc589), 0x22 }, ++ { CCI_REG8(0xc58a), 0x22 }, { CCI_REG8(0xc58b), 0x22 }, ++ { CCI_REG8(0xc58c), 0x22 }, { CCI_REG8(0xc58d), 0x22 }, ++ { CCI_REG8(0xc58e), 0x22 }, { CCI_REG8(0xc58f), 0x22 }, ++ { CCI_REG8(0xc590), 0x22 }, { CCI_REG8(0xc591), 0x22 }, ++ { CCI_REG8(0xc592), 0x22 }, { CCI_REG8(0xc598), 0x22 }, ++ { CCI_REG8(0xc599), 0x22 }, { CCI_REG8(0xc59a), 0x22 }, ++ { CCI_REG8(0xc59b), 0x22 }, { CCI_REG8(0xc59c), 0x22 }, ++ { CCI_REG8(0xc59d), 0x22 }, { CCI_REG8(0xc59e), 0x22 }, ++ { CCI_REG8(0xc59f), 0x22 }, { CCI_REG8(0xc5a0), 0x22 }, ++ { CCI_REG8(0xc5a1), 0x22 }, { CCI_REG8(0xc5a2), 0x22 }, ++ { CCI_REG8(0xc5a3), 0x22 }, { CCI_REG8(0xc5a4), 0x22 }, ++ { CCI_REG8(0xc5a5), 0x22 }, { CCI_REG8(0xc5a6), 0x22 }, ++ { CCI_REG8(0xc5a7), 0x22 }, { CCI_REG8(0xc5a8), 0x22 }, ++ { CCI_REG8(0xc5a9), 0x22 }, { CCI_REG8(0xc5aa), 0x22 }, ++ { CCI_REG8(0xc5ab), 0x22 }, { CCI_REG8(0xc5b1), 0x2a }, ++ { CCI_REG8(0xc5b2), 0x2a }, { CCI_REG8(0xc5b3), 0x2a }, ++ { CCI_REG8(0xc5b4), 0x2a }, { CCI_REG8(0xc5b5), 0x2a }, ++ { CCI_REG8(0xc5b6), 0x2a }, { CCI_REG8(0xc5b7), 0x2a }, ++ { CCI_REG8(0xc5b8), 0x2a }, { CCI_REG8(0xc5b9), 0x2a }, ++ { CCI_REG8(0xc5ba), 0x2a }, { CCI_REG8(0xc5bb), 0x2a }, ++ { CCI_REG8(0xc5bc), 0x2a }, { CCI_REG8(0xc5bd), 0x2a }, ++ { CCI_REG8(0xc5be), 0x2a }, { CCI_REG8(0xc5bf), 0x2a }, ++ { CCI_REG8(0xc5c0), 0x2a }, { CCI_REG8(0xc5c1), 0x2a }, ++ { CCI_REG8(0xc5c2), 0x2a }, { CCI_REG8(0xc5c3), 0x2a }, ++ { CCI_REG8(0xc5c4), 0x2a }, { CCI_REG8(0xc5ca), 0x2a }, ++ { CCI_REG8(0xc5cb), 0x2a }, { CCI_REG8(0xc5cc), 0x2a }, ++ { CCI_REG8(0xc5cd), 0x2a }, { CCI_REG8(0xc5ce), 0x2a }, ++ { CCI_REG8(0xc5cf), 0x2a }, { CCI_REG8(0xc5d0), 0x2a }, ++ { CCI_REG8(0xc5d1), 0x2a }, { CCI_REG8(0xc5d2), 0x2a }, ++ { CCI_REG8(0xc5d3), 0x2a }, { CCI_REG8(0xc5d4), 0x2a }, ++ { CCI_REG8(0xc5d5), 0x2a }, { CCI_REG8(0xc5d6), 0x2a }, ++ { CCI_REG8(0xc5d7), 0x2a }, { CCI_REG8(0xc5d8), 0x2a }, ++ { CCI_REG8(0xc5d9), 0x2a }, { CCI_REG8(0xc5da), 0x2a }, ++ { CCI_REG8(0xc5db), 0x2a }, { CCI_REG8(0xc5dc), 0x2a }, ++ { CCI_REG8(0xc5dd), 0x2a }, { CCI_REG8(0xc5e8), 0x22 }, ++ { CCI_REG8(0xc5ea), 0x22 }, { CCI_REG8(0x4540), 0x12 }, ++ { CCI_REG8(0x4541), 0x30 }, { CCI_REG8(0x3d86), 0x12 }, ++ { CCI_REG8(0x3d87), 0x30 }, { CCI_REG8(0x4606), 0x12 }, ++ { CCI_REG8(0x4607), 0x30 }, { CCI_REG8(0x4648), 0x0a }, ++ { CCI_REG8(0x4649), 0x06 }, { CCI_REG8(0x3220), 0x12 }, ++ { CCI_REG8(0x3221), 0x30 }, { CCI_REG8(0x40c2), 0x12 }, ++ { CCI_REG8(0x49c2), 0x12 }, { CCI_REG8(0x4ac2), 0x12 }, ++ { CCI_REG8(0x40c3), 0x30 }, { CCI_REG8(0x49c3), 0x30 }, ++ { CCI_REG8(0x4ac3), 0x30 }, { CCI_REG8(0x36b0), 0x12 }, ++ { CCI_REG8(0x36b1), 0x30 }, { CCI_REG8(0x45cb), 0x12 }, ++ { CCI_REG8(0x45cc), 0x30 }, { CCI_REG8(0x4585), 0x12 }, ++ { CCI_REG8(0x4586), 0x30 }, { CCI_REG8(0x36b2), 0x12 }, ++ { CCI_REG8(0x36b3), 0x30 }, { CCI_REG8(0x5a40), 0x75 }, ++ { CCI_REG8(0x5a41), 0x75 }, { CCI_REG8(0x5a42), 0x75 }, ++ { CCI_REG8(0x5a43), 0x75 }, { CCI_REG8(0x5a44), 0x75 }, ++ { CCI_REG8(0x5a45), 0x75 }, { CCI_REG8(0x5a46), 0x75 }, ++ { CCI_REG8(0x5a47), 0x75 }, { CCI_REG8(0x5a48), 0x75 }, ++ { CCI_REG8(0x5a49), 0x75 }, { CCI_REG8(0x5a4a), 0x75 }, ++ { CCI_REG8(0x5a4b), 0x75 }, { CCI_REG8(0x5a4c), 0x75 }, ++ { CCI_REG8(0x5a4d), 0x75 }, { CCI_REG8(0x5a4e), 0x75 }, ++ { CCI_REG8(0x5a4f), 0x75 }, { CCI_REG8(0x5a50), 0x75 }, ++ { CCI_REG8(0x5a51), 0x75 }, { CCI_REG8(0x5a52), 0x75 }, ++ { CCI_REG8(0x5a53), 0x75 }, { CCI_REG8(0x5a54), 0x75 }, ++ { CCI_REG8(0x5a55), 0x75 }, { CCI_REG8(0x5a56), 0x75 }, ++ { CCI_REG8(0x5a57), 0x75 }, { CCI_REG8(0x5a58), 0x75 }, ++ { CCI_REG8(0x5a59), 0x75 }, { CCI_REG8(0x5a5a), 0x75 }, ++ { CCI_REG8(0x5a5b), 0x75 }, { CCI_REG8(0x5a5c), 0x75 }, ++ { CCI_REG8(0x5a5d), 0x75 }, { CCI_REG8(0x5a5e), 0x75 }, ++ { CCI_REG8(0x5a5f), 0x75 }, { CCI_REG8(0x5a60), 0x75 }, ++ { CCI_REG8(0x5a61), 0x75 }, { CCI_REG8(0x5a62), 0x75 }, ++ { CCI_REG8(0x5a63), 0x75 }, { CCI_REG8(0x5a64), 0x75 }, ++ { CCI_REG8(0x5a65), 0x75 }, { CCI_REG8(0x5a66), 0x75 }, ++ { CCI_REG8(0x5a67), 0x75 }, { CCI_REG8(0x5a68), 0x75 }, ++ { CCI_REG8(0x5a69), 0x75 }, { CCI_REG8(0x5a6a), 0x75 }, ++ { CCI_REG8(0x5a6b), 0x75 }, { CCI_REG8(0x5a6c), 0x75 }, ++ { CCI_REG8(0x5a6d), 0x75 }, { CCI_REG8(0x5a6e), 0x75 }, ++ { CCI_REG8(0x5a6f), 0x75 }, { CCI_REG8(0x5a70), 0x75 }, ++ { CCI_REG8(0x5a71), 0x75 }, { CCI_REG8(0x5a72), 0x75 }, ++ { CCI_REG8(0x5a73), 0x75 }, { CCI_REG8(0x5a74), 0x75 }, ++ { CCI_REG8(0x5a75), 0x75 }, { CCI_REG8(0x5a76), 0x75 }, ++ { CCI_REG8(0x5a77), 0x75 }, { CCI_REG8(0x5a78), 0x75 }, ++ { CCI_REG8(0x5a79), 0x75 }, { CCI_REG8(0x5a7a), 0x75 }, ++ { CCI_REG8(0x5a7b), 0x75 }, { CCI_REG8(0x5a7c), 0x75 }, ++ { CCI_REG8(0x5a7d), 0x75 }, { CCI_REG8(0x5a7e), 0x75 }, ++ { CCI_REG8(0x5a7f), 0x75 }, { CCI_REG8(0x5a80), 0x75 }, ++ { CCI_REG8(0x5a81), 0x75 }, { CCI_REG8(0x5a82), 0x75 }, ++ { CCI_REG8(0x5a83), 0x75 }, { CCI_REG8(0x5a84), 0x75 }, ++ { CCI_REG8(0x5a85), 0x75 }, { CCI_REG8(0x5a86), 0x75 }, ++ { CCI_REG8(0x5a87), 0x75 }, { CCI_REG8(0x5a88), 0x75 }, ++ { CCI_REG8(0x5a89), 0x75 }, { CCI_REG8(0x5a8a), 0x75 }, ++ { CCI_REG8(0x5a8b), 0x75 }, { CCI_REG8(0x5a8c), 0x75 }, ++ { CCI_REG8(0x5a8d), 0x75 }, { CCI_REG8(0x5a8e), 0x75 }, ++ { CCI_REG8(0x5a8f), 0x75 }, { CCI_REG8(0x5a90), 0x75 }, ++ { CCI_REG8(0x5a91), 0x75 }, { CCI_REG8(0x5a92), 0x75 }, ++ { CCI_REG8(0x5a93), 0x75 }, { CCI_REG8(0x5a94), 0x75 }, ++ { CCI_REG8(0x5a95), 0x75 }, { CCI_REG8(0x5a96), 0x75 }, ++ { CCI_REG8(0x5a97), 0x75 }, { CCI_REG8(0x5a98), 0x75 }, ++ { CCI_REG8(0x5a99), 0x75 }, { CCI_REG8(0x5a9a), 0x75 }, ++ { CCI_REG8(0x5a9b), 0x75 }, { CCI_REG8(0x5a9c), 0x75 }, ++ { CCI_REG8(0x5a9d), 0x75 }, { CCI_REG8(0x5a9e), 0x75 }, ++ { CCI_REG8(0x5a9f), 0x75 }, { CCI_REG8(0x5aa0), 0x75 }, ++ { CCI_REG8(0x5aa1), 0x75 }, { CCI_REG8(0x5aa2), 0x75 }, ++ { CCI_REG8(0x5aa3), 0x75 }, { CCI_REG8(0x5aa4), 0x75 }, ++ { CCI_REG8(0x5aa5), 0x75 }, { CCI_REG8(0x5aa6), 0x75 }, ++ { CCI_REG8(0x5aa7), 0x75 }, { CCI_REG8(0x5aa8), 0x75 }, ++ { CCI_REG8(0x5aa9), 0x75 }, { CCI_REG8(0x5aaa), 0x75 }, ++ { CCI_REG8(0x5aab), 0x75 }, { CCI_REG8(0x5aac), 0x75 }, ++ { CCI_REG8(0x5aad), 0x75 }, { CCI_REG8(0x5aae), 0x75 }, ++ { CCI_REG8(0x5aaf), 0x75 }, { CCI_REG8(0x5ab0), 0x75 }, ++ { CCI_REG8(0x5ab1), 0x75 }, { CCI_REG8(0x5ab2), 0x75 }, ++ { CCI_REG8(0x5ab3), 0x75 }, { CCI_REG8(0x5ab4), 0x75 }, ++ { CCI_REG8(0x5ab5), 0x75 }, { CCI_REG8(0x5ab6), 0x75 }, ++ { CCI_REG8(0x5ab7), 0x75 }, { CCI_REG8(0x5ab8), 0x75 }, ++ { CCI_REG8(0x5ab9), 0x75 }, { CCI_REG8(0x5aba), 0x75 }, ++ { CCI_REG8(0x5abb), 0x75 }, { CCI_REG8(0x5abc), 0x75 }, ++ { CCI_REG8(0x5abd), 0x75 }, { CCI_REG8(0x5abe), 0x75 }, ++ { CCI_REG8(0x5abf), 0x75 }, { CCI_REG8(0x5ac0), 0x75 }, ++ { CCI_REG8(0x5ac1), 0x75 }, { CCI_REG8(0x5ac2), 0x75 }, ++ { CCI_REG8(0x5ac3), 0x75 }, { CCI_REG8(0x5ac4), 0x75 }, ++ { CCI_REG8(0x5ac5), 0x75 }, { CCI_REG8(0x5ac6), 0x75 }, ++ { CCI_REG8(0x5ac7), 0x75 }, { CCI_REG8(0x5ac8), 0x75 }, ++ { CCI_REG8(0x5ac9), 0x75 }, { CCI_REG8(0x5aca), 0x75 }, ++ { CCI_REG8(0x5acb), 0x75 }, { CCI_REG8(0x5acc), 0x75 }, ++ { CCI_REG8(0x5acd), 0x75 }, { CCI_REG8(0x5ace), 0x75 }, ++ { CCI_REG8(0x5acf), 0x75 }, { CCI_REG8(0x5ad0), 0x75 }, ++ { CCI_REG8(0x5ad1), 0x75 }, { CCI_REG8(0x5ad2), 0x75 }, ++ { CCI_REG8(0x5ad3), 0x75 }, { CCI_REG8(0x5ad4), 0x75 }, ++ { CCI_REG8(0x5ad5), 0x75 }, { CCI_REG8(0x5ad6), 0x75 }, ++ { CCI_REG8(0x5ad7), 0x75 }, { CCI_REG8(0x5ad8), 0x75 }, ++ { CCI_REG8(0x5ad9), 0x75 }, { CCI_REG8(0x5ada), 0x75 }, ++ { CCI_REG8(0x5adb), 0x75 }, { CCI_REG8(0x5adc), 0x75 }, ++ { CCI_REG8(0x5add), 0x75 }, { CCI_REG8(0x5ade), 0x75 }, ++ { CCI_REG8(0x5adf), 0x75 }, { CCI_REG8(0x5ae0), 0x75 }, ++ { CCI_REG8(0x5ae1), 0x75 }, { CCI_REG8(0x5ae2), 0x75 }, ++ { CCI_REG8(0x5ae3), 0x75 }, { CCI_REG8(0x5ae4), 0x75 }, ++ { CCI_REG8(0x5ae5), 0x75 }, { CCI_REG8(0x5ae6), 0x75 }, ++ { CCI_REG8(0x5ae7), 0x75 }, { CCI_REG8(0x5ae8), 0x75 }, ++ { CCI_REG8(0x5ae9), 0x75 }, { CCI_REG8(0x5aea), 0x75 }, ++ { CCI_REG8(0x5aeb), 0x75 }, { CCI_REG8(0x5aec), 0x75 }, ++ { CCI_REG8(0x5aed), 0x75 }, { CCI_REG8(0x5aee), 0x75 }, ++ { CCI_REG8(0x5aef), 0x75 }, { CCI_REG8(0x5af0), 0x75 }, ++ { CCI_REG8(0x5af1), 0x75 }, { CCI_REG8(0x5af2), 0x75 }, ++ { CCI_REG8(0x5af3), 0x75 }, { CCI_REG8(0x5af4), 0x75 }, ++ { CCI_REG8(0x5af5), 0x75 }, { CCI_REG8(0x5af6), 0x75 }, ++ { CCI_REG8(0x5af7), 0x75 }, { CCI_REG8(0x5af8), 0x75 }, ++ { CCI_REG8(0x5af9), 0x75 }, { CCI_REG8(0x5afa), 0x75 }, ++ { CCI_REG8(0x5afb), 0x75 }, { CCI_REG8(0x5afc), 0x75 }, ++ { CCI_REG8(0x5afd), 0x75 }, { CCI_REG8(0x5afe), 0x75 }, ++ { CCI_REG8(0x5aff), 0x75 }, { CCI_REG8(0x5b00), 0x75 }, ++ { CCI_REG8(0x5b01), 0x75 }, { CCI_REG8(0x5b02), 0x75 }, ++ { CCI_REG8(0x5b03), 0x75 }, { CCI_REG8(0x5b04), 0x75 }, ++ { CCI_REG8(0x5b05), 0x75 }, { CCI_REG8(0x5b06), 0x75 }, ++ { CCI_REG8(0x5b07), 0x75 }, { CCI_REG8(0x5b08), 0x75 }, ++ { CCI_REG8(0x5b09), 0x75 }, { CCI_REG8(0x5b0a), 0x75 }, ++ { CCI_REG8(0x5b0b), 0x75 }, { CCI_REG8(0x5b0c), 0x75 }, ++ { CCI_REG8(0x5b0d), 0x75 }, { CCI_REG8(0x5b0e), 0x75 }, ++ { CCI_REG8(0x5b0f), 0x75 }, { CCI_REG8(0x5b10), 0x75 }, ++ { CCI_REG8(0x5b11), 0x75 }, { CCI_REG8(0x5b12), 0x75 }, ++ { CCI_REG8(0x5b13), 0x75 }, { CCI_REG8(0x5b14), 0x75 }, ++ { CCI_REG8(0x5b15), 0x75 }, { CCI_REG8(0x5b16), 0x75 }, ++ { CCI_REG8(0x5b17), 0x75 }, { CCI_REG8(0x5b18), 0x75 }, ++ { CCI_REG8(0x5b19), 0x75 }, { CCI_REG8(0x5b1a), 0x75 }, ++ { CCI_REG8(0x5b1b), 0x75 }, { CCI_REG8(0x5b1c), 0x75 }, ++ { CCI_REG8(0x5b1d), 0x75 }, { CCI_REG8(0x5b1e), 0x75 }, ++ { CCI_REG8(0x5b1f), 0x75 }, { CCI_REG8(0x5b20), 0x75 }, ++ { CCI_REG8(0x5b21), 0x75 }, { CCI_REG8(0x5b22), 0x75 }, ++ { CCI_REG8(0x5b23), 0x75 }, { CCI_REG8(0x5b24), 0x75 }, ++ { CCI_REG8(0x5b25), 0x75 }, { CCI_REG8(0x5b26), 0x75 }, ++ { CCI_REG8(0x5b27), 0x75 }, { CCI_REG8(0x5b28), 0x75 }, ++ { CCI_REG8(0x5b29), 0x75 }, { CCI_REG8(0x5b2a), 0x75 }, ++ { CCI_REG8(0x5b2b), 0x75 }, { CCI_REG8(0x5b2c), 0x75 }, ++ { CCI_REG8(0x5b2d), 0x75 }, { CCI_REG8(0x5b2e), 0x75 }, ++ { CCI_REG8(0x5b2f), 0x75 }, { CCI_REG8(0x5b30), 0x75 }, ++ { CCI_REG8(0x5b31), 0x75 }, { CCI_REG8(0x5b32), 0x75 }, ++ { CCI_REG8(0x5b33), 0x75 }, { CCI_REG8(0x5b34), 0x75 }, ++ { CCI_REG8(0x5b35), 0x75 }, { CCI_REG8(0x5b36), 0x75 }, ++ { CCI_REG8(0x5b37), 0x75 }, { CCI_REG8(0x5b38), 0x75 }, ++ { CCI_REG8(0x5b39), 0x75 }, { CCI_REG8(0x5b3a), 0x75 }, ++ { CCI_REG8(0x5b3b), 0x75 }, { CCI_REG8(0x5b3c), 0x75 }, ++ { CCI_REG8(0x5b3d), 0x75 }, { CCI_REG8(0x5b3e), 0x75 }, ++ { CCI_REG8(0x5b3f), 0x75 }, { CCI_REG8(0x5b40), 0x75 }, ++ { CCI_REG8(0x5b41), 0x75 }, { CCI_REG8(0x5b42), 0x75 }, ++ { CCI_REG8(0x5b43), 0x75 }, { CCI_REG8(0x5b44), 0x75 }, ++ { CCI_REG8(0x5b45), 0x75 }, { CCI_REG8(0x5b46), 0x75 }, ++ { CCI_REG8(0x5b47), 0x75 }, { CCI_REG8(0x5b48), 0x75 }, ++ { CCI_REG8(0x5b49), 0x75 }, { CCI_REG8(0x5b4a), 0x75 }, ++ { CCI_REG8(0x5b4b), 0x75 }, { CCI_REG8(0x5b4c), 0x75 }, ++ { CCI_REG8(0x5b4d), 0x75 }, { CCI_REG8(0x5b4e), 0x75 }, ++ { CCI_REG8(0x5b4f), 0x75 }, { CCI_REG8(0x5b50), 0x75 }, ++ { CCI_REG8(0x5b51), 0x75 }, { CCI_REG8(0x5b52), 0x75 }, ++ { CCI_REG8(0x5b53), 0x75 }, { CCI_REG8(0x5b54), 0x75 }, ++ { CCI_REG8(0x5b55), 0x75 }, { CCI_REG8(0x5b56), 0x75 }, ++ { CCI_REG8(0x5b57), 0x75 }, { CCI_REG8(0x5b58), 0x75 }, ++ { CCI_REG8(0x5b59), 0x75 }, { CCI_REG8(0x5b5a), 0x75 }, ++ { CCI_REG8(0x5b5b), 0x75 }, { CCI_REG8(0x5b5c), 0x75 }, ++ { CCI_REG8(0x5b5d), 0x75 }, { CCI_REG8(0x5b5e), 0x75 }, ++ { CCI_REG8(0x5b5f), 0x75 }, { CCI_REG8(0x5b80), 0x75 }, ++ { CCI_REG8(0x5b81), 0x75 }, { CCI_REG8(0x5b82), 0x75 }, ++ { CCI_REG8(0x5b83), 0x75 }, { CCI_REG8(0x5b84), 0x75 }, ++ { CCI_REG8(0x5b85), 0x75 }, { CCI_REG8(0x5b86), 0x75 }, ++ { CCI_REG8(0x5b87), 0x75 }, { CCI_REG8(0x5b88), 0x75 }, ++ { CCI_REG8(0x5b89), 0x75 }, { CCI_REG8(0x5b8a), 0x75 }, ++ { CCI_REG8(0x5b8b), 0x75 }, { CCI_REG8(0x5b8c), 0x75 }, ++ { CCI_REG8(0x5b8d), 0x75 }, { CCI_REG8(0x5b8e), 0x75 }, ++ { CCI_REG8(0x5b8f), 0x75 }, { CCI_REG8(0x5b90), 0x75 }, ++ { CCI_REG8(0x5b91), 0x75 }, { CCI_REG8(0x5b92), 0x75 }, ++ { CCI_REG8(0x5b93), 0x75 }, { CCI_REG8(0x5b94), 0x75 }, ++ { CCI_REG8(0x5b95), 0x75 }, { CCI_REG8(0x5b96), 0x75 }, ++ { CCI_REG8(0x5b97), 0x75 }, { CCI_REG8(0x5b98), 0x75 }, ++ { CCI_REG8(0x5b99), 0x75 }, { CCI_REG8(0x5b9a), 0x75 }, ++ { CCI_REG8(0x5b9b), 0x75 }, { CCI_REG8(0x5b9c), 0x75 }, ++ { CCI_REG8(0x5b9d), 0x75 }, { CCI_REG8(0x5b9e), 0x75 }, ++ { CCI_REG8(0x5b9f), 0x75 }, { CCI_REG8(0x5ba0), 0x75 }, ++ { CCI_REG8(0x5ba1), 0x75 }, { CCI_REG8(0x5ba2), 0x75 }, ++ { CCI_REG8(0x5ba3), 0x75 }, { CCI_REG8(0x5ba4), 0x75 }, ++ { CCI_REG8(0x5ba5), 0x75 }, { CCI_REG8(0x5ba6), 0x75 }, ++ { CCI_REG8(0x5ba7), 0x75 }, { CCI_REG8(0x5ba8), 0x75 }, ++ { CCI_REG8(0x5ba9), 0x75 }, { CCI_REG8(0x5baa), 0x75 }, ++ { CCI_REG8(0x5bab), 0x75 }, { CCI_REG8(0x5bac), 0x75 }, ++ { CCI_REG8(0x5bad), 0x75 }, { CCI_REG8(0x5bae), 0x75 }, ++ { CCI_REG8(0x5baf), 0x75 }, { CCI_REG8(0x5bb0), 0x75 }, ++ { CCI_REG8(0x5bb1), 0x75 }, { CCI_REG8(0x5bb2), 0x75 }, ++ { CCI_REG8(0x5bb3), 0x75 }, { CCI_REG8(0x5bb4), 0x75 }, ++ { CCI_REG8(0x5bb5), 0x75 }, { CCI_REG8(0x5bb6), 0x75 }, ++ { CCI_REG8(0x5bb7), 0x75 }, { CCI_REG8(0x5bb8), 0x75 }, ++ { CCI_REG8(0x5bb9), 0x75 }, { CCI_REG8(0x5bba), 0x75 }, ++ { CCI_REG8(0x5bbb), 0x75 }, { CCI_REG8(0x5bbc), 0x75 }, ++ { CCI_REG8(0x5bbd), 0x75 }, { CCI_REG8(0x5bbe), 0x75 }, ++ { CCI_REG8(0x5bbf), 0x75 }, { CCI_REG8(0x5bc0), 0x75 }, ++ { CCI_REG8(0x5bc1), 0x75 }, { CCI_REG8(0x5bc2), 0x75 }, ++ { CCI_REG8(0x5bc3), 0x75 }, { CCI_REG8(0x5bc4), 0x75 }, ++ { CCI_REG8(0x5bc5), 0x75 }, { CCI_REG8(0x5bc6), 0x75 }, ++ { CCI_REG8(0x5bc7), 0x75 }, { CCI_REG8(0x5bc8), 0x75 }, ++ { CCI_REG8(0x5bc9), 0x75 }, { CCI_REG8(0x5bca), 0x75 }, ++ { CCI_REG8(0x5bcb), 0x75 }, { CCI_REG8(0x5bcc), 0x75 }, ++ { CCI_REG8(0x5bcd), 0x75 }, { CCI_REG8(0x5bce), 0x75 }, ++ { CCI_REG8(0x5bcf), 0x75 }, { CCI_REG8(0x5bd0), 0x75 }, ++ { CCI_REG8(0x5bd1), 0x75 }, { CCI_REG8(0x5bd2), 0x75 }, ++ { CCI_REG8(0x5bd3), 0x75 }, { CCI_REG8(0x5bd4), 0x75 }, ++ { CCI_REG8(0x5bd5), 0x75 }, { CCI_REG8(0x5bd6), 0x75 }, ++ { CCI_REG8(0x5bd7), 0x75 }, { CCI_REG8(0x5bd8), 0x75 }, ++ { CCI_REG8(0x5bd9), 0x75 }, { CCI_REG8(0x5bda), 0x75 }, ++ { CCI_REG8(0x5bdb), 0x75 }, { CCI_REG8(0x5bdc), 0x75 }, ++ { CCI_REG8(0x5bdd), 0x75 }, { CCI_REG8(0x5bde), 0x75 }, ++ { CCI_REG8(0x5bdf), 0x75 }, { CCI_REG8(0x5be0), 0x75 }, ++ { CCI_REG8(0x5be1), 0x75 }, { CCI_REG8(0x5be2), 0x75 }, ++ { CCI_REG8(0x5be3), 0x75 }, { CCI_REG8(0x5be4), 0x75 }, ++ { CCI_REG8(0x5be5), 0x75 }, { CCI_REG8(0x5be6), 0x75 }, ++ { CCI_REG8(0x5be7), 0x75 }, { CCI_REG8(0x5be8), 0x75 }, ++ { CCI_REG8(0x5be9), 0x75 }, { CCI_REG8(0x5bea), 0x75 }, ++ { CCI_REG8(0x5beb), 0x75 }, { CCI_REG8(0x5bec), 0x75 }, ++ { CCI_REG8(0x5bed), 0x75 }, { CCI_REG8(0x5bee), 0x75 }, ++ { CCI_REG8(0x5bef), 0x75 }, { CCI_REG8(0x5bf0), 0x75 }, ++ { CCI_REG8(0x5bf1), 0x75 }, { CCI_REG8(0x5bf2), 0x75 }, ++ { CCI_REG8(0x5bf3), 0x75 }, { CCI_REG8(0x5bf4), 0x75 }, ++ { CCI_REG8(0x5bf5), 0x75 }, { CCI_REG8(0x5bf6), 0x75 }, ++ { CCI_REG8(0x5bf7), 0x75 }, { CCI_REG8(0x5bf8), 0x75 }, ++ { CCI_REG8(0x5bf9), 0x75 }, { CCI_REG8(0x5bfa), 0x75 }, ++ { CCI_REG8(0x5bfb), 0x75 }, { CCI_REG8(0x5bfc), 0x75 }, ++ { CCI_REG8(0x5bfd), 0x75 }, { CCI_REG8(0x5bfe), 0x75 }, ++ { CCI_REG8(0x5bff), 0x75 }, { CCI_REG8(0x5c00), 0x75 }, ++ { CCI_REG8(0x5c01), 0x75 }, { CCI_REG8(0x5c02), 0x75 }, ++ { CCI_REG8(0x5c03), 0x75 }, { CCI_REG8(0x5c04), 0x75 }, ++ { CCI_REG8(0x5c05), 0x75 }, { CCI_REG8(0x5c06), 0x75 }, ++ { CCI_REG8(0x5c07), 0x75 }, { CCI_REG8(0x5c08), 0x75 }, ++ { CCI_REG8(0x5c09), 0x75 }, { CCI_REG8(0x5c0a), 0x75 }, ++ { CCI_REG8(0x5c0b), 0x75 }, { CCI_REG8(0x5c0c), 0x75 }, ++ { CCI_REG8(0x5c0d), 0x75 }, { CCI_REG8(0x5c0e), 0x75 }, ++ { CCI_REG8(0x5c0f), 0x75 }, { CCI_REG8(0x5c10), 0x75 }, ++ { CCI_REG8(0x5c11), 0x75 }, { CCI_REG8(0x5c12), 0x75 }, ++ { CCI_REG8(0x5c13), 0x75 }, { CCI_REG8(0x5c14), 0x75 }, ++ { CCI_REG8(0x5c15), 0x75 }, { CCI_REG8(0x5c16), 0x75 }, ++ { CCI_REG8(0x5c17), 0x75 }, { CCI_REG8(0x5c18), 0x75 }, ++ { CCI_REG8(0x5c19), 0x75 }, { CCI_REG8(0x5c1a), 0x75 }, ++ { CCI_REG8(0x5c1b), 0x75 }, { CCI_REG8(0x5c1c), 0x75 }, ++ { CCI_REG8(0x5c1d), 0x75 }, { CCI_REG8(0x5c1e), 0x75 }, ++ { CCI_REG8(0x5c1f), 0x75 }, { CCI_REG8(0x5c20), 0x75 }, ++ { CCI_REG8(0x5c21), 0x75 }, { CCI_REG8(0x5c22), 0x75 }, ++ { CCI_REG8(0x5c23), 0x75 }, { CCI_REG8(0x5c24), 0x75 }, ++ { CCI_REG8(0x5c25), 0x75 }, { CCI_REG8(0x5c26), 0x75 }, ++ { CCI_REG8(0x5c27), 0x75 }, { CCI_REG8(0x5c28), 0x75 }, ++ { CCI_REG8(0x5c29), 0x75 }, { CCI_REG8(0x5c2a), 0x75 }, ++ { CCI_REG8(0x5c2b), 0x75 }, { CCI_REG8(0x5c2c), 0x75 }, ++ { CCI_REG8(0x5c2d), 0x75 }, { CCI_REG8(0x5c2e), 0x75 }, ++ { CCI_REG8(0x5c2f), 0x75 }, { CCI_REG8(0x5c30), 0x75 }, ++ { CCI_REG8(0x5c31), 0x75 }, { CCI_REG8(0x5c32), 0x75 }, ++ { CCI_REG8(0x5c33), 0x75 }, { CCI_REG8(0x5c34), 0x75 }, ++ { CCI_REG8(0x5c35), 0x75 }, { CCI_REG8(0x5c36), 0x75 }, ++ { CCI_REG8(0x5c37), 0x75 }, { CCI_REG8(0x5c38), 0x75 }, ++ { CCI_REG8(0x5c39), 0x75 }, { CCI_REG8(0x5c3a), 0x75 }, ++ { CCI_REG8(0x5c3b), 0x75 }, { CCI_REG8(0x5c3c), 0x75 }, ++ { CCI_REG8(0x5c3d), 0x75 }, { CCI_REG8(0x5c3e), 0x75 }, ++ { CCI_REG8(0x5c3f), 0x75 }, { CCI_REG8(0x5c40), 0x75 }, ++ { CCI_REG8(0x5c41), 0x75 }, { CCI_REG8(0x5c42), 0x75 }, ++ { CCI_REG8(0x5c43), 0x75 }, { CCI_REG8(0x5c44), 0x75 }, ++ { CCI_REG8(0x5c45), 0x75 }, { CCI_REG8(0x5c46), 0x75 }, ++ { CCI_REG8(0x5c47), 0x75 }, { CCI_REG8(0x5c48), 0x75 }, ++ { CCI_REG8(0x5c49), 0x75 }, { CCI_REG8(0x5c4a), 0x75 }, ++ { CCI_REG8(0x5c4b), 0x75 }, { CCI_REG8(0x5c4c), 0x75 }, ++ { CCI_REG8(0x5c4d), 0x75 }, { CCI_REG8(0x5c4e), 0x75 }, ++ { CCI_REG8(0x5c4f), 0x75 }, { CCI_REG8(0x5c50), 0x75 }, ++ { CCI_REG8(0x5c51), 0x75 }, { CCI_REG8(0x5c52), 0x75 }, ++ { CCI_REG8(0x5c53), 0x75 }, { CCI_REG8(0x5c54), 0x75 }, ++ { CCI_REG8(0x5c55), 0x75 }, { CCI_REG8(0x5c56), 0x75 }, ++ { CCI_REG8(0x5c57), 0x75 }, { CCI_REG8(0x5c58), 0x75 }, ++ { CCI_REG8(0x5c59), 0x75 }, { CCI_REG8(0x5c5a), 0x75 }, ++ { CCI_REG8(0x5c5b), 0x75 }, { CCI_REG8(0x5c5c), 0x75 }, ++ { CCI_REG8(0x5c5d), 0x75 }, { CCI_REG8(0x5c5e), 0x75 }, ++ { CCI_REG8(0x5c5f), 0x75 }, { CCI_REG8(0x5c60), 0x75 }, ++ { CCI_REG8(0x5c61), 0x75 }, { CCI_REG8(0x5c62), 0x75 }, ++ { CCI_REG8(0x5c63), 0x75 }, { CCI_REG8(0x5c64), 0x75 }, ++ { CCI_REG8(0x5c65), 0x75 }, { CCI_REG8(0x5c66), 0x75 }, ++ { CCI_REG8(0x5c67), 0x75 }, { CCI_REG8(0x5c68), 0x75 }, ++ { CCI_REG8(0x5c69), 0x75 }, { CCI_REG8(0x5c6a), 0x75 }, ++ { CCI_REG8(0x5c6b), 0x75 }, { CCI_REG8(0x5c6c), 0x75 }, ++ { CCI_REG8(0x5c6d), 0x75 }, { CCI_REG8(0x5c6e), 0x75 }, ++ { CCI_REG8(0x5c6f), 0x75 }, { CCI_REG8(0x5c70), 0x75 }, ++ { CCI_REG8(0x5c71), 0x75 }, { CCI_REG8(0x5c72), 0x75 }, ++ { CCI_REG8(0x5c73), 0x75 }, { CCI_REG8(0x5c74), 0x75 }, ++ { CCI_REG8(0x5c75), 0x75 }, { CCI_REG8(0x5c76), 0x75 }, ++ { CCI_REG8(0x5c77), 0x75 }, { CCI_REG8(0x5c78), 0x75 }, ++ { CCI_REG8(0x5c79), 0x75 }, { CCI_REG8(0x5c7a), 0x75 }, ++ { CCI_REG8(0x5c7b), 0x75 }, { CCI_REG8(0x5c7c), 0x75 }, ++ { CCI_REG8(0x5c7d), 0x75 }, { CCI_REG8(0x5c7e), 0x75 }, ++ { CCI_REG8(0x5c7f), 0x75 }, { CCI_REG8(0x5c80), 0x75 }, ++ { CCI_REG8(0x5c81), 0x75 }, { CCI_REG8(0x5c82), 0x75 }, ++ { CCI_REG8(0x5c83), 0x75 }, { CCI_REG8(0x5c84), 0x75 }, ++ { CCI_REG8(0x5c85), 0x75 }, { CCI_REG8(0x5c86), 0x75 }, ++ { CCI_REG8(0x5c87), 0x75 }, { CCI_REG8(0x5c88), 0x75 }, ++ { CCI_REG8(0x5c89), 0x75 }, { CCI_REG8(0x5c8a), 0x75 }, ++ { CCI_REG8(0x5c8b), 0x75 }, { CCI_REG8(0x5c8c), 0x75 }, ++ { CCI_REG8(0x5c8d), 0x75 }, { CCI_REG8(0x5c8e), 0x75 }, ++ { CCI_REG8(0x5c8f), 0x75 }, { CCI_REG8(0x5c90), 0x75 }, ++ { CCI_REG8(0x5c91), 0x75 }, { CCI_REG8(0x5c92), 0x75 }, ++ { CCI_REG8(0x5c93), 0x75 }, { CCI_REG8(0x5c94), 0x75 }, ++ { CCI_REG8(0x5c95), 0x75 }, { CCI_REG8(0x5c96), 0x75 }, ++ { CCI_REG8(0x5c97), 0x75 }, { CCI_REG8(0x5c98), 0x75 }, ++ { CCI_REG8(0x5c99), 0x75 }, { CCI_REG8(0x5c9a), 0x75 }, ++ { CCI_REG8(0x5c9b), 0x75 }, { CCI_REG8(0x5c9c), 0x75 }, ++ { CCI_REG8(0x5c9d), 0x75 }, { CCI_REG8(0x5c9e), 0x75 }, ++ { CCI_REG8(0x5c9f), 0x75 }, { CCI_REG8(0x5ca0), 0x75 }, ++ { CCI_REG8(0x5ca1), 0x75 }, { CCI_REG8(0x5ca2), 0x75 }, ++ { CCI_REG8(0x5ca3), 0x75 }, { CCI_REG8(0x5ca4), 0x75 }, ++ { CCI_REG8(0x5ca5), 0x75 }, { CCI_REG8(0x5ca6), 0x75 }, ++ { CCI_REG8(0x5ca7), 0x75 }, { CCI_REG8(0x5ca8), 0x75 }, ++ { CCI_REG8(0x5ca9), 0x75 }, { CCI_REG8(0x5caa), 0x75 }, ++ { CCI_REG8(0x5cab), 0x75 }, { CCI_REG8(0x5cac), 0x75 }, ++ { CCI_REG8(0x5cad), 0x75 }, { CCI_REG8(0x5cae), 0x75 }, ++ { CCI_REG8(0x5caf), 0x75 }, { CCI_REG8(0x5cb0), 0x75 }, ++ { CCI_REG8(0x5cb1), 0x75 }, { CCI_REG8(0x5cb2), 0x75 }, ++ { CCI_REG8(0x5cb3), 0x75 }, { CCI_REG8(0x5cb4), 0x75 }, ++ { CCI_REG8(0x5cb5), 0x75 }, { CCI_REG8(0x5cb6), 0x75 }, ++ { CCI_REG8(0x5cb7), 0x75 }, { CCI_REG8(0x5cb8), 0x75 }, ++ { CCI_REG8(0x5cb9), 0x75 }, { CCI_REG8(0x5cba), 0x75 }, ++ { CCI_REG8(0x5cbb), 0x75 }, { CCI_REG8(0x5cbc), 0x75 }, ++ { CCI_REG8(0x5cbd), 0x75 }, { CCI_REG8(0x5cbe), 0x75 }, ++ { CCI_REG8(0x5cbf), 0x75 }, { CCI_REG8(0x5cc0), 0x75 }, ++ { CCI_REG8(0x5cc1), 0x75 }, { CCI_REG8(0x5cc2), 0x75 }, ++ { CCI_REG8(0x5cc3), 0x75 }, { CCI_REG8(0x5cc4), 0x75 }, ++ { CCI_REG8(0x5cc5), 0x75 }, { CCI_REG8(0x5cc6), 0x75 }, ++ { CCI_REG8(0x5cc7), 0x75 }, { CCI_REG8(0x5cc8), 0x75 }, ++ { CCI_REG8(0x5cc9), 0x75 }, { CCI_REG8(0x5cca), 0x75 }, ++ { CCI_REG8(0x5ccb), 0x75 }, { CCI_REG8(0x5ccc), 0x75 }, ++ { CCI_REG8(0x5ccd), 0x75 }, { CCI_REG8(0x5cce), 0x75 }, ++ { CCI_REG8(0x5ccf), 0x75 }, { CCI_REG8(0x5cd0), 0x75 }, ++ { CCI_REG8(0x5cd1), 0x75 }, { CCI_REG8(0x5cd2), 0x75 }, ++ { CCI_REG8(0x5cd3), 0x75 }, { CCI_REG8(0x5cd4), 0x75 }, ++ { CCI_REG8(0x5cd5), 0x75 }, { CCI_REG8(0x5cd6), 0x75 }, ++ { CCI_REG8(0x5cd7), 0x75 }, { CCI_REG8(0x5cd8), 0x75 }, ++ { CCI_REG8(0x5cd9), 0x75 }, { CCI_REG8(0x5cda), 0x75 }, ++ { CCI_REG8(0x5cdb), 0x75 }, { CCI_REG8(0x5cdc), 0x75 }, ++ { CCI_REG8(0x5cdd), 0x75 }, { CCI_REG8(0x5cde), 0x75 }, ++ { CCI_REG8(0x5cdf), 0x75 }, { CCI_REG8(0x5ce0), 0x75 }, ++ { CCI_REG8(0x5ce1), 0x75 }, { CCI_REG8(0x5ce2), 0x75 }, ++ { CCI_REG8(0x5ce3), 0x75 }, { CCI_REG8(0x5ce4), 0x75 }, ++ { CCI_REG8(0x5ce5), 0x75 }, { CCI_REG8(0x5ce6), 0x75 }, ++ { CCI_REG8(0x5ce7), 0x75 }, { CCI_REG8(0x5ce8), 0x75 }, ++ { CCI_REG8(0x5ce9), 0x75 }, { CCI_REG8(0x5cea), 0x75 }, ++ { CCI_REG8(0x5ceb), 0x75 }, { CCI_REG8(0x5cec), 0x75 }, ++ { CCI_REG8(0x5ced), 0x75 }, { CCI_REG8(0x5cee), 0x75 }, ++ { CCI_REG8(0x5cef), 0x75 }, { CCI_REG8(0x5cf0), 0x75 }, ++ { CCI_REG8(0x5cf1), 0x75 }, { CCI_REG8(0x5cf2), 0x75 }, ++ { CCI_REG8(0x5cf3), 0x75 }, { CCI_REG8(0x5cf4), 0x75 }, ++ { CCI_REG8(0x5cf5), 0x75 }, { CCI_REG8(0x5cf6), 0x75 }, ++ { CCI_REG8(0x5cf7), 0x75 }, { CCI_REG8(0x5cf8), 0x75 }, ++ { CCI_REG8(0x5cf9), 0x75 }, { CCI_REG8(0x5cfa), 0x75 }, ++ { CCI_REG8(0x5cfb), 0x75 }, { CCI_REG8(0x5cfc), 0x75 }, ++ { CCI_REG8(0x5cfd), 0x75 }, { CCI_REG8(0x5cfe), 0x75 }, ++ { CCI_REG8(0x5cff), 0x75 }, { CCI_REG8(0x5d00), 0x75 }, ++ { CCI_REG8(0x5d01), 0x75 }, { CCI_REG8(0x5d02), 0x75 }, ++ { CCI_REG8(0x5d03), 0x75 }, { CCI_REG8(0x5d04), 0x75 }, ++ { CCI_REG8(0x5d05), 0x75 }, { CCI_REG8(0x5d06), 0x75 }, ++ { CCI_REG8(0x5d07), 0x75 }, { CCI_REG8(0x5d08), 0x75 }, ++ { CCI_REG8(0x5d09), 0x75 }, { CCI_REG8(0x5d0a), 0x75 }, ++ { CCI_REG8(0x5d0b), 0x75 }, { CCI_REG8(0x5d0c), 0x75 }, ++ { CCI_REG8(0x5d0d), 0x75 }, { CCI_REG8(0x5d0e), 0x75 }, ++ { CCI_REG8(0x5d0f), 0x75 }, { CCI_REG8(0x5d10), 0x75 }, ++ { CCI_REG8(0x5d11), 0x75 }, { CCI_REG8(0x5d12), 0x75 }, ++ { CCI_REG8(0x5d13), 0x75 }, { CCI_REG8(0x5d14), 0x75 }, ++ { CCI_REG8(0x5d15), 0x75 }, { CCI_REG8(0x5d16), 0x75 }, ++ { CCI_REG8(0x5d17), 0x75 }, { CCI_REG8(0x5d18), 0x75 }, ++ { CCI_REG8(0x5d19), 0x75 }, { CCI_REG8(0x5d1a), 0x75 }, ++ { CCI_REG8(0x5d1b), 0x75 }, { CCI_REG8(0x5d1c), 0x75 }, ++ { CCI_REG8(0x5d1d), 0x75 }, { CCI_REG8(0x5d1e), 0x75 }, ++ { CCI_REG8(0x5d1f), 0x75 }, { CCI_REG8(0x5d20), 0x75 }, ++ { CCI_REG8(0x5d21), 0x75 }, { CCI_REG8(0x5d22), 0x75 }, ++ { CCI_REG8(0x5d23), 0x75 }, { CCI_REG8(0x5d24), 0x75 }, ++ { CCI_REG8(0x5d25), 0x75 }, { CCI_REG8(0x5d26), 0x75 }, ++ { CCI_REG8(0x5d27), 0x75 }, { CCI_REG8(0x5d28), 0x75 }, ++ { CCI_REG8(0x5d29), 0x75 }, { CCI_REG8(0x5d2a), 0x75 }, ++ { CCI_REG8(0x5d2b), 0x75 }, { CCI_REG8(0x5d2c), 0x75 }, ++ { CCI_REG8(0x5d2d), 0x75 }, { CCI_REG8(0x5d2e), 0x75 }, ++ { CCI_REG8(0x5d2f), 0x75 }, { CCI_REG8(0x5d30), 0x75 }, ++ { CCI_REG8(0x5d31), 0x75 }, { CCI_REG8(0x5d32), 0x75 }, ++ { CCI_REG8(0x5d33), 0x75 }, { CCI_REG8(0x5d34), 0x75 }, ++ { CCI_REG8(0x5d35), 0x75 }, { CCI_REG8(0x5d36), 0x75 }, ++ { CCI_REG8(0x5d37), 0x75 }, { CCI_REG8(0x5d38), 0x75 }, ++ { CCI_REG8(0x5d39), 0x75 }, { CCI_REG8(0x5d3a), 0x75 }, ++ { CCI_REG8(0x5d3b), 0x75 }, { CCI_REG8(0x5d3c), 0x75 }, ++ { CCI_REG8(0x5d3d), 0x75 }, { CCI_REG8(0x5d3e), 0x75 }, ++ { CCI_REG8(0x5d3f), 0x75 }, { CCI_REG8(0x5d40), 0x75 }, ++ { CCI_REG8(0x5d41), 0x75 }, { CCI_REG8(0x5d42), 0x75 }, ++ { CCI_REG8(0x5d43), 0x75 }, { CCI_REG8(0x5d44), 0x75 }, ++ { CCI_REG8(0x5d45), 0x75 }, { CCI_REG8(0x5d46), 0x75 }, ++ { CCI_REG8(0x5d47), 0x75 }, { CCI_REG8(0x5d48), 0x75 }, ++ { CCI_REG8(0x5d49), 0x75 }, { CCI_REG8(0x5d4a), 0x75 }, ++ { CCI_REG8(0x5d4b), 0x75 }, { CCI_REG8(0x5d4c), 0x75 }, ++ { CCI_REG8(0x5d4d), 0x75 }, { CCI_REG8(0x5d4e), 0x75 }, ++ { CCI_REG8(0x5d4f), 0x75 }, { CCI_REG8(0x5d50), 0x75 }, ++ { CCI_REG8(0x5d51), 0x75 }, { CCI_REG8(0x5d52), 0x75 }, ++ { CCI_REG8(0x5d53), 0x75 }, { CCI_REG8(0x5d54), 0x75 }, ++ { CCI_REG8(0x5d55), 0x75 }, { CCI_REG8(0x5d56), 0x75 }, ++ { CCI_REG8(0x5d57), 0x75 }, { CCI_REG8(0x5d58), 0x75 }, ++ { CCI_REG8(0x5d59), 0x75 }, { CCI_REG8(0x5d5a), 0x75 }, ++ { CCI_REG8(0x5d5b), 0x75 }, { CCI_REG8(0x5d5c), 0x75 }, ++ { CCI_REG8(0x5d5d), 0x75 }, { CCI_REG8(0x5d5e), 0x75 }, ++ { CCI_REG8(0x5d5f), 0x75 }, { CCI_REG8(0x5d60), 0x75 }, ++ { CCI_REG8(0x5d61), 0x75 }, { CCI_REG8(0x5d62), 0x75 }, ++ { CCI_REG8(0x5d63), 0x75 }, { CCI_REG8(0x5d64), 0x75 }, ++ { CCI_REG8(0x5d65), 0x75 }, { CCI_REG8(0x5d66), 0x75 }, ++ { CCI_REG8(0x5d67), 0x75 }, { CCI_REG8(0x5d68), 0x75 }, ++ { CCI_REG8(0x5d69), 0x75 }, { CCI_REG8(0x5d6a), 0x75 }, ++ { CCI_REG8(0x5d6b), 0x75 }, { CCI_REG8(0x5d6c), 0x75 }, ++ { CCI_REG8(0x5d6d), 0x75 }, { CCI_REG8(0x5d6e), 0x75 }, ++ { CCI_REG8(0x5d6f), 0x75 }, { CCI_REG8(0x5d70), 0x75 }, ++ { CCI_REG8(0x5d71), 0x75 }, { CCI_REG8(0x5d72), 0x75 }, ++ { CCI_REG8(0x5d73), 0x75 }, { CCI_REG8(0x5d74), 0x75 }, ++ { CCI_REG8(0x5d75), 0x75 }, { CCI_REG8(0x5d76), 0x75 }, ++ { CCI_REG8(0x5d77), 0x75 }, { CCI_REG8(0x5d78), 0x75 }, ++ { CCI_REG8(0x5d79), 0x75 }, { CCI_REG8(0x5d7a), 0x75 }, ++ { CCI_REG8(0x5d7b), 0x75 }, { CCI_REG8(0x5d7c), 0x75 }, ++ { CCI_REG8(0x5d7d), 0x75 }, { CCI_REG8(0x5d7e), 0x75 }, ++ { CCI_REG8(0x5d7f), 0x75 }, { CCI_REG8(0x5d80), 0x75 }, ++ { CCI_REG8(0x5d81), 0x75 }, { CCI_REG8(0x5d82), 0x75 }, ++ { CCI_REG8(0x5d83), 0x75 }, { CCI_REG8(0x5d84), 0x75 }, ++ { CCI_REG8(0x5d85), 0x75 }, { CCI_REG8(0x5d86), 0x75 }, ++ { CCI_REG8(0x5d87), 0x75 }, { CCI_REG8(0x5d88), 0x75 }, ++ { CCI_REG8(0x5d89), 0x75 }, { CCI_REG8(0x5d8a), 0x75 }, ++ { CCI_REG8(0x5d8b), 0x75 }, { CCI_REG8(0x5d8c), 0x75 }, ++ { CCI_REG8(0x5d8d), 0x75 }, { CCI_REG8(0x5d8e), 0x75 }, ++ { CCI_REG8(0x5d8f), 0x75 }, { CCI_REG8(0x5d90), 0x75 }, ++ { CCI_REG8(0x5d91), 0x75 }, { CCI_REG8(0x5d92), 0x75 }, ++ { CCI_REG8(0x5d93), 0x75 }, { CCI_REG8(0x5d94), 0x75 }, ++ { CCI_REG8(0x5d95), 0x75 }, { CCI_REG8(0x5d96), 0x75 }, ++ { CCI_REG8(0x5d97), 0x75 }, { CCI_REG8(0x5d98), 0x75 }, ++ { CCI_REG8(0x5d99), 0x75 }, { CCI_REG8(0x5d9a), 0x75 }, ++ { CCI_REG8(0x5d9b), 0x75 }, { CCI_REG8(0x5d9c), 0x75 }, ++ { CCI_REG8(0x5d9d), 0x75 }, { CCI_REG8(0x5d9e), 0x75 }, ++ { CCI_REG8(0x5d9f), 0x75 }, { CCI_REG8(0x5da0), 0x75 }, ++ { CCI_REG8(0x5da1), 0x75 }, { CCI_REG8(0x5da2), 0x75 }, ++ { CCI_REG8(0x5da3), 0x75 }, { CCI_REG8(0x5da4), 0x75 }, ++ { CCI_REG8(0x5da5), 0x75 }, { CCI_REG8(0x5da6), 0x75 }, ++ { CCI_REG8(0x5da7), 0x75 }, { CCI_REG8(0x5da8), 0x75 }, ++ { CCI_REG8(0x5da9), 0x75 }, { CCI_REG8(0x5daa), 0x75 }, ++ { CCI_REG8(0x5dab), 0x75 }, { CCI_REG8(0x5dac), 0x75 }, ++ { CCI_REG8(0x5dad), 0x75 }, { CCI_REG8(0x5dae), 0x75 }, ++ { CCI_REG8(0x5daf), 0x75 }, { CCI_REG8(0x5db0), 0x75 }, ++ { CCI_REG8(0x5db1), 0x75 }, { CCI_REG8(0x5db2), 0x75 }, ++ { CCI_REG8(0x5db3), 0x75 }, { CCI_REG8(0x5db4), 0x75 }, ++ { CCI_REG8(0x5db5), 0x75 }, { CCI_REG8(0x5db6), 0x75 }, ++ { CCI_REG8(0x5db7), 0x75 }, { CCI_REG8(0x5db8), 0x75 }, ++ { CCI_REG8(0x5db9), 0x75 }, { CCI_REG8(0x5dba), 0x75 }, ++ { CCI_REG8(0x5dbb), 0x75 }, { CCI_REG8(0x5dbc), 0x75 }, ++ { CCI_REG8(0x5dbd), 0x75 }, { CCI_REG8(0x5dbe), 0x75 }, ++ { CCI_REG8(0x5dbf), 0x75 }, { CCI_REG8(0x5dc0), 0x75 }, ++ { CCI_REG8(0x5dc1), 0x75 }, { CCI_REG8(0x5dc2), 0x75 }, ++ { CCI_REG8(0x5dc3), 0x75 }, { CCI_REG8(0x5dc4), 0x75 }, ++ { CCI_REG8(0x5dc5), 0x75 }, { CCI_REG8(0x5dc6), 0x75 }, ++ { CCI_REG8(0x5dc7), 0x75 }, { CCI_REG8(0x5dc8), 0x75 }, ++ { CCI_REG8(0x5dc9), 0x75 }, { CCI_REG8(0x5dca), 0x75 }, ++ { CCI_REG8(0x5dcb), 0x75 }, { CCI_REG8(0x5dcc), 0x75 }, ++ { CCI_REG8(0x5dcd), 0x75 }, { CCI_REG8(0x5dce), 0x75 }, ++ { CCI_REG8(0x5dcf), 0x75 }, { CCI_REG8(0x5dd0), 0x75 }, ++ { CCI_REG8(0x5dd1), 0x75 }, { CCI_REG8(0x5dd2), 0x75 }, ++ { CCI_REG8(0x5dd3), 0x75 }, { CCI_REG8(0x5dd4), 0x75 }, ++ { CCI_REG8(0x5dd5), 0x75 }, { CCI_REG8(0x5dd6), 0x75 }, ++ { CCI_REG8(0x5dd7), 0x75 }, { CCI_REG8(0x5dd8), 0x75 }, ++ { CCI_REG8(0x5dd9), 0x75 }, { CCI_REG8(0x5dda), 0x75 }, ++ { CCI_REG8(0x5ddb), 0x75 }, { CCI_REG8(0x5ddc), 0x75 }, ++ { CCI_REG8(0x5ddd), 0x75 }, { CCI_REG8(0x5dde), 0x75 }, ++ { CCI_REG8(0x5ddf), 0x75 }, { CCI_REG8(0x5de0), 0x75 }, ++ { CCI_REG8(0x5de1), 0x75 }, { CCI_REG8(0x5de2), 0x75 }, ++ { CCI_REG8(0x5de3), 0x75 }, { CCI_REG8(0x5de4), 0x75 }, ++ { CCI_REG8(0x5de5), 0x75 }, { CCI_REG8(0x5de6), 0x75 }, ++ { CCI_REG8(0x5de7), 0x75 }, { CCI_REG8(0x5de8), 0x75 }, ++ { CCI_REG8(0x5de9), 0x75 }, { CCI_REG8(0x5dea), 0x75 }, ++ { CCI_REG8(0x5deb), 0x75 }, { CCI_REG8(0x5dec), 0x75 }, ++ { CCI_REG8(0x5ded), 0x75 }, { CCI_REG8(0x5dee), 0x75 }, ++ { CCI_REG8(0x5def), 0x75 }, { CCI_REG8(0x5df0), 0x75 }, ++ { CCI_REG8(0x5df1), 0x75 }, { CCI_REG8(0x5df2), 0x75 }, ++ { CCI_REG8(0x5df3), 0x75 }, { CCI_REG8(0x5df4), 0x75 }, ++ { CCI_REG8(0x5df5), 0x75 }, { CCI_REG8(0x5df6), 0x75 }, ++ { CCI_REG8(0x5df7), 0x75 }, { CCI_REG8(0x5df8), 0x75 }, ++ { CCI_REG8(0x5df9), 0x75 }, { CCI_REG8(0x5dfa), 0x75 }, ++ { CCI_REG8(0x5dfb), 0x75 }, { CCI_REG8(0x5dfc), 0x75 }, ++ { CCI_REG8(0x5dfd), 0x75 }, { CCI_REG8(0x5dfe), 0x75 }, ++ { CCI_REG8(0x5dff), 0x75 }, { CCI_REG8(0x5e00), 0x75 }, ++ { CCI_REG8(0x5e01), 0x75 }, { CCI_REG8(0x5e02), 0x75 }, ++ { CCI_REG8(0x5e03), 0x75 }, { CCI_REG8(0x5e04), 0x75 }, ++ { CCI_REG8(0x5e05), 0x75 }, { CCI_REG8(0x5e06), 0x75 }, ++ { CCI_REG8(0x5e07), 0x75 }, { CCI_REG8(0x5e08), 0x75 }, ++ { CCI_REG8(0x5e09), 0x75 }, { CCI_REG8(0x5e0a), 0x75 }, ++ { CCI_REG8(0x5e0b), 0x75 }, { CCI_REG8(0x5e0c), 0x75 }, ++ { CCI_REG8(0x5e0d), 0x75 }, { CCI_REG8(0x5e0e), 0x75 }, ++ { CCI_REG8(0x5e0f), 0x75 }, { CCI_REG8(0x5e10), 0x75 }, ++ { CCI_REG8(0x5e11), 0x75 }, { CCI_REG8(0x5e12), 0x75 }, ++ { CCI_REG8(0x5e13), 0x75 }, { CCI_REG8(0x5e14), 0x75 }, ++ { CCI_REG8(0x5e15), 0x75 }, { CCI_REG8(0x5e16), 0x75 }, ++ { CCI_REG8(0x5e17), 0x75 }, { CCI_REG8(0x5e18), 0x75 }, ++ { CCI_REG8(0x5e19), 0x75 }, { CCI_REG8(0x5e1a), 0x75 }, ++ { CCI_REG8(0x5e1b), 0x75 }, { CCI_REG8(0x5e1c), 0x75 }, ++ { CCI_REG8(0x5e1d), 0x75 }, { CCI_REG8(0x5e1e), 0x75 }, ++ { CCI_REG8(0x5e1f), 0x75 }, { CCI_REG8(0x5e20), 0x75 }, ++ { CCI_REG8(0x5e21), 0x75 }, { CCI_REG8(0x5e22), 0x75 }, ++ { CCI_REG8(0x5e23), 0x75 }, { CCI_REG8(0x5e24), 0x75 }, ++ { CCI_REG8(0x5e25), 0x75 }, { CCI_REG8(0x5e26), 0x75 }, ++ { CCI_REG8(0x5e27), 0x75 }, { CCI_REG8(0x5e28), 0x75 }, ++ { CCI_REG8(0x5e29), 0x75 }, { CCI_REG8(0x5e2a), 0x75 }, ++ { CCI_REG8(0x5e2b), 0x75 }, { CCI_REG8(0x5e2c), 0x75 }, ++ { CCI_REG8(0x5e2d), 0x75 }, { CCI_REG8(0x5e2e), 0x75 }, ++ { CCI_REG8(0x5e2f), 0x75 }, { CCI_REG8(0x5e30), 0x75 }, ++ { CCI_REG8(0x5e31), 0x75 }, { CCI_REG8(0x5e32), 0x75 }, ++ { CCI_REG8(0x5e33), 0x75 }, { CCI_REG8(0x5e34), 0x75 }, ++ { CCI_REG8(0x5e35), 0x75 }, { CCI_REG8(0x5e36), 0x75 }, ++ { CCI_REG8(0x5e37), 0x75 }, { CCI_REG8(0x5e38), 0x75 }, ++ { CCI_REG8(0x5e39), 0x75 }, { CCI_REG8(0x5e3a), 0x75 }, ++ { CCI_REG8(0x5e3b), 0x75 }, { CCI_REG8(0x5e3c), 0x75 }, ++ { CCI_REG8(0x5e3d), 0x75 }, { CCI_REG8(0x5e3e), 0x75 }, ++ { CCI_REG8(0x5e3f), 0x75 }, { CCI_REG8(0x5e40), 0x75 }, ++ { CCI_REG8(0x5e41), 0x75 }, { CCI_REG8(0x5e42), 0x75 }, ++ { CCI_REG8(0x5e43), 0x75 }, { CCI_REG8(0x5e44), 0x75 }, ++ { CCI_REG8(0x5e45), 0x75 }, { CCI_REG8(0x5e46), 0x75 }, ++ { CCI_REG8(0x5e47), 0x75 }, { CCI_REG8(0x5e48), 0x75 }, ++ { CCI_REG8(0x5e49), 0x75 }, { CCI_REG8(0x5e4a), 0x75 }, ++ { CCI_REG8(0x5e4b), 0x75 }, { CCI_REG8(0x5e4c), 0x75 }, ++ { CCI_REG8(0x5e4d), 0x75 }, { CCI_REG8(0x5e4e), 0x75 }, ++ { CCI_REG8(0x5e4f), 0x75 }, { CCI_REG8(0x5e50), 0x75 }, ++ { CCI_REG8(0x5e51), 0x75 }, { CCI_REG8(0x5e52), 0x75 }, ++ { CCI_REG8(0x5e53), 0x75 }, { CCI_REG8(0x5e54), 0x75 }, ++ { CCI_REG8(0x5e55), 0x75 }, { CCI_REG8(0x5e56), 0x75 }, ++ { CCI_REG8(0x5e57), 0x75 }, { CCI_REG8(0x5e58), 0x75 }, ++ { CCI_REG8(0x5e59), 0x75 }, { CCI_REG8(0x5e5a), 0x75 }, ++ { CCI_REG8(0x5e5b), 0x75 }, { CCI_REG8(0x5e5c), 0x75 }, ++ { CCI_REG8(0x5e5d), 0x75 }, { CCI_REG8(0x5e5e), 0x75 }, ++ { CCI_REG8(0x5e5f), 0x75 }, { CCI_REG8(0x5e60), 0x75 }, ++ { CCI_REG8(0x5e61), 0x75 }, { CCI_REG8(0x5e62), 0x75 }, ++ { CCI_REG8(0x5e63), 0x75 }, { CCI_REG8(0x5e64), 0x75 }, ++ { CCI_REG8(0x5e65), 0x75 }, { CCI_REG8(0x5e66), 0x75 }, ++ { CCI_REG8(0x5e67), 0x75 }, { CCI_REG8(0x5e68), 0x75 }, ++ { CCI_REG8(0x5e69), 0x75 }, { CCI_REG8(0x5e6a), 0x75 }, ++ { CCI_REG8(0x5e6b), 0x75 }, { CCI_REG8(0x5e6c), 0x75 }, ++ { CCI_REG8(0x5e6d), 0x75 }, { CCI_REG8(0x5e6e), 0x75 }, ++ { CCI_REG8(0x5e6f), 0x75 }, { CCI_REG8(0x5e70), 0x75 }, ++ { CCI_REG8(0x5e71), 0x75 }, { CCI_REG8(0x5e72), 0x75 }, ++ { CCI_REG8(0x5e73), 0x75 }, { CCI_REG8(0x5e74), 0x75 }, ++ { CCI_REG8(0x5e75), 0x75 }, { CCI_REG8(0x5e76), 0x75 }, ++ { CCI_REG8(0x5e77), 0x75 }, { CCI_REG8(0x5e78), 0x75 }, ++ { CCI_REG8(0x5e79), 0x75 }, { CCI_REG8(0x5e7a), 0x75 }, ++ { CCI_REG8(0x5e7b), 0x75 }, { CCI_REG8(0x5e7c), 0x75 }, ++ { CCI_REG8(0x5e7d), 0x75 }, { CCI_REG8(0x5e7e), 0x75 }, ++ { CCI_REG8(0x5e7f), 0x75 }, { CCI_REG8(0x5e80), 0x75 }, ++ { CCI_REG8(0x5e81), 0x75 }, { CCI_REG8(0x5e82), 0x75 }, ++ { CCI_REG8(0x5e83), 0x75 }, { CCI_REG8(0x5e84), 0x75 }, ++ { CCI_REG8(0x5e85), 0x75 }, { CCI_REG8(0x5e86), 0x75 }, ++ { CCI_REG8(0x5e87), 0x75 }, { CCI_REG8(0x5e88), 0x75 }, ++ { CCI_REG8(0x5e89), 0x75 }, { CCI_REG8(0x5e8a), 0x75 }, ++ { CCI_REG8(0x5e8b), 0x75 }, { CCI_REG8(0x5e8c), 0x75 }, ++ { CCI_REG8(0x5e8d), 0x75 }, { CCI_REG8(0x5e8e), 0x75 }, ++ { CCI_REG8(0x5e8f), 0x75 }, { CCI_REG8(0x5e90), 0x75 }, ++ { CCI_REG8(0x5e91), 0x75 }, { CCI_REG8(0x5e92), 0x75 }, ++ { CCI_REG8(0x5e93), 0x75 }, { CCI_REG8(0x5e94), 0x75 }, ++ { CCI_REG8(0x5e95), 0x75 }, { CCI_REG8(0x5e96), 0x75 }, ++ { CCI_REG8(0x5e97), 0x75 }, { CCI_REG8(0x5e98), 0x75 }, ++ { CCI_REG8(0x5e99), 0x75 }, { CCI_REG8(0x5e9a), 0x75 }, ++ { CCI_REG8(0x5e9b), 0x75 }, { CCI_REG8(0x5e9c), 0x75 }, ++ { CCI_REG8(0x5e9d), 0x75 }, { CCI_REG8(0x5e9e), 0x75 }, ++ { CCI_REG8(0x5e9f), 0x75 }, { CCI_REG8(0x5ea0), 0x75 }, ++ { CCI_REG8(0x5ea1), 0x75 }, { CCI_REG8(0x5ea2), 0x75 }, ++ { CCI_REG8(0x5ea3), 0x75 }, { CCI_REG8(0x5ea4), 0x75 }, ++ { CCI_REG8(0x5ea5), 0x75 }, { CCI_REG8(0x5ea6), 0x75 }, ++ { CCI_REG8(0x5ea7), 0x75 }, { CCI_REG8(0x5ea8), 0x75 }, ++ { CCI_REG8(0x5ea9), 0x75 }, { CCI_REG8(0x5eaa), 0x75 }, ++ { CCI_REG8(0x5eab), 0x75 }, { CCI_REG8(0x5eac), 0x75 }, ++ { CCI_REG8(0x5ead), 0x75 }, { CCI_REG8(0x5eae), 0x75 }, ++ { CCI_REG8(0x5eaf), 0x75 }, { CCI_REG8(0x5eb0), 0x75 }, ++ { CCI_REG8(0x5eb1), 0x75 }, { CCI_REG8(0x5eb2), 0x75 }, ++ { CCI_REG8(0x5eb3), 0x75 }, { CCI_REG8(0x5eb4), 0x75 }, ++ { CCI_REG8(0x5eb5), 0x75 }, { CCI_REG8(0x5eb6), 0x75 }, ++ { CCI_REG8(0x5eb7), 0x75 }, { CCI_REG8(0x5eb8), 0x75 }, ++ { CCI_REG8(0x5eb9), 0x75 }, { CCI_REG8(0x5eba), 0x75 }, ++ { CCI_REG8(0x5ebb), 0x75 }, { CCI_REG8(0x5ebc), 0x75 }, ++ { CCI_REG8(0x5ebd), 0x75 }, { CCI_REG8(0x5ebe), 0x75 }, ++ { CCI_REG8(0x5ebf), 0x75 }, { CCI_REG8(0x5ec0), 0x75 }, ++ { CCI_REG8(0x5ec1), 0x75 }, { CCI_REG8(0x5ec2), 0x75 }, ++ { CCI_REG8(0x5ec3), 0x75 }, { CCI_REG8(0x5ec4), 0x75 }, ++ { CCI_REG8(0x5ec5), 0x75 }, { CCI_REG8(0x5ec6), 0x75 }, ++ { CCI_REG8(0x5ec7), 0x75 }, { CCI_REG8(0x5ec8), 0x75 }, ++ { CCI_REG8(0x5ec9), 0x75 }, { CCI_REG8(0x5eca), 0x75 }, ++ { CCI_REG8(0x5ecb), 0x75 }, { CCI_REG8(0x5ecc), 0x75 }, ++ { CCI_REG8(0x5ecd), 0x75 }, { CCI_REG8(0x5ece), 0x75 }, ++ { CCI_REG8(0x5ecf), 0x75 }, { CCI_REG8(0x5ed0), 0x75 }, ++ { CCI_REG8(0x5ed1), 0x75 }, { CCI_REG8(0x5ed2), 0x75 }, ++ { CCI_REG8(0x5ed3), 0x75 }, { CCI_REG8(0x5ed4), 0x75 }, ++ { CCI_REG8(0x5ed5), 0x75 }, { CCI_REG8(0x5ed6), 0x75 }, ++ { CCI_REG8(0x5ed7), 0x75 }, { CCI_REG8(0x5ed8), 0x75 }, ++ { CCI_REG8(0x5ed9), 0x75 }, { CCI_REG8(0x5eda), 0x75 }, ++ { CCI_REG8(0x5edb), 0x75 }, { CCI_REG8(0x5edc), 0x75 }, ++ { CCI_REG8(0x5edd), 0x75 }, { CCI_REG8(0x5ede), 0x75 }, ++ { CCI_REG8(0x5edf), 0x75 }, { CCI_REG8(0xfff9), 0x08 }, ++ { CCI_REG8(0x1570), 0x00 }, { CCI_REG8(0x15d0), 0x00 }, ++ { CCI_REG8(0x15a0), 0x02 }, { CCI_REG8(0x15a1), 0x00 }, ++ { CCI_REG8(0x15a2), 0x02 }, { CCI_REG8(0x15a3), 0x76 }, ++ { CCI_REG8(0x15a4), 0x03 }, { CCI_REG8(0x15a5), 0x08 }, ++ { CCI_REG8(0x15a6), 0x00 }, { CCI_REG8(0x15a7), 0x60 }, ++ { CCI_REG8(0x15a8), 0x01 }, { CCI_REG8(0x15a9), 0x00 }, ++ { CCI_REG8(0x15aa), 0x02 }, { CCI_REG8(0x15ab), 0x00 }, ++ { CCI_REG8(0x1600), 0x02 }, { CCI_REG8(0x1601), 0x00 }, ++ { CCI_REG8(0x1602), 0x02 }, { CCI_REG8(0x1603), 0x76 }, ++ { CCI_REG8(0x1604), 0x03 }, { CCI_REG8(0x1605), 0x08 }, ++ { CCI_REG8(0x1606), 0x00 }, { CCI_REG8(0x1607), 0x60 }, ++ { CCI_REG8(0x1608), 0x01 }, { CCI_REG8(0x1609), 0x00 }, ++ { CCI_REG8(0x160a), 0x02 }, { CCI_REG8(0x160b), 0x00 }, ++ { CCI_REG8(0x1633), 0x03 }, { CCI_REG8(0x1634), 0x01 }, ++ { CCI_REG8(0x163c), 0x3a }, { CCI_REG8(0x163d), 0x01 }, ++ { CCI_REG8(0x1648), 0x32 }, { CCI_REG8(0x1658), 0x01 }, ++ { CCI_REG8(0x1659), 0x01 }, { CCI_REG8(0x165f), 0x01 }, ++ { CCI_REG8(0x1677), 0x01 }, { CCI_REG8(0x1690), 0x08 }, ++ { CCI_REG8(0x1691), 0x00 }, { CCI_REG8(0x1692), 0x20 }, ++ { CCI_REG8(0x1693), 0x00 }, { CCI_REG8(0x1694), 0x10 }, ++ { CCI_REG8(0x1695), 0x14 }, { CCI_REG8(0x1696), 0x10 }, ++ { CCI_REG8(0x1697), 0x0e }, { CCI_REG8(0x1730), 0x01 }, ++ { CCI_REG8(0x1732), 0x00 }, { CCI_REG8(0x1733), 0x10 }, ++ { CCI_REG8(0x1734), 0x01 }, { CCI_REG8(0x1735), 0x00 }, ++ { CCI_REG8(0x1748), 0x01 }, { CCI_REG8(0xfff9), 0x06 }, ++ { CCI_REG8(0x5000), 0xff }, { CCI_REG8(0x5001), 0x3d }, ++ { CCI_REG8(0x5002), 0xf5 }, { CCI_REG8(0x5004), 0x80 }, ++ { CCI_REG8(0x5006), 0x04 }, { CCI_REG8(0x5061), 0x20 }, ++ { CCI_REG8(0x5063), 0x20 }, { CCI_REG8(0x5064), 0x24 }, ++ { CCI_REG8(0x5065), 0x00 }, { CCI_REG8(0x5066), 0x1b }, ++ { CCI_REG8(0x5067), 0x00 }, { CCI_REG8(0x5068), 0x03 }, ++ { CCI_REG8(0x5069), 0x10 }, { CCI_REG8(0x506a), 0x20 }, ++ { CCI_REG8(0x506b), 0x04 }, { CCI_REG8(0x506c), 0x04 }, ++ { CCI_REG8(0x506d), 0x0c }, { CCI_REG8(0x506e), 0x0c }, ++ { CCI_REG8(0x506f), 0x04 }, { CCI_REG8(0x5070), 0x0c }, ++ { CCI_REG8(0x5071), 0x14 }, { CCI_REG8(0x5072), 0x1c }, ++ { CCI_REG8(0x5073), 0x01 }, { CCI_REG8(0x5074), 0x01 }, ++ { CCI_REG8(0x5075), 0xbe }, { CCI_REG8(0x5083), 0x00 }, ++ { CCI_REG8(0x5114), 0x03 }, { CCI_REG8(0x51b0), 0x00 }, ++ { CCI_REG8(0x51b3), 0x0e }, { CCI_REG8(0x51b5), 0x02 }, ++ { CCI_REG8(0x51b6), 0x00 }, { CCI_REG8(0x51b7), 0x00 }, ++ { CCI_REG8(0x51b8), 0x00 }, { CCI_REG8(0x51b9), 0x70 }, ++ { CCI_REG8(0x51ba), 0x00 }, { CCI_REG8(0x51bb), 0x10 }, ++ { CCI_REG8(0x51bc), 0x00 }, { CCI_REG8(0x51bd), 0x00 }, ++ { CCI_REG8(0x51d2), 0xff }, { CCI_REG8(0x51d3), 0x1c }, ++ { CCI_REG8(0x5250), 0x34 }, { CCI_REG8(0x5251), 0x00 }, ++ { CCI_REG8(0x525b), 0x00 }, { CCI_REG8(0x525d), 0x00 }, ++ { CCI_REG8(0x527a), 0x00 }, { CCI_REG8(0x527b), 0x38 }, ++ { CCI_REG8(0x527c), 0x00 }, { CCI_REG8(0x527d), 0x4b }, ++ { CCI_REG8(0x5286), 0x1b }, { CCI_REG8(0x5287), 0x40 }, ++ { CCI_REG8(0x5290), 0x00 }, { CCI_REG8(0x5291), 0x50 }, ++ { CCI_REG8(0x5292), 0x00 }, { CCI_REG8(0x5293), 0x50 }, ++ { CCI_REG8(0x5294), 0x00 }, { CCI_REG8(0x5295), 0x50 }, ++ { CCI_REG8(0x5296), 0x00 }, { CCI_REG8(0x5297), 0x50 }, ++ { CCI_REG8(0x5298), 0x00 }, { CCI_REG8(0x5299), 0x50 }, ++ { CCI_REG8(0x529a), 0x01 }, { CCI_REG8(0x529b), 0x00 }, ++ { CCI_REG8(0x529c), 0x01 }, { CCI_REG8(0x529d), 0x00 }, ++ { CCI_REG8(0x529e), 0x00 }, { CCI_REG8(0x529f), 0x50 }, ++ { CCI_REG8(0x52a0), 0x00 }, { CCI_REG8(0x52a1), 0x50 }, ++ { CCI_REG8(0x52a2), 0x01 }, { CCI_REG8(0x52a3), 0x00 }, ++ { CCI_REG8(0x52a4), 0x01 }, { CCI_REG8(0x52a5), 0x00 }, ++ { CCI_REG8(0x52a6), 0x00 }, { CCI_REG8(0x52a7), 0x50 }, ++ { CCI_REG8(0x52a8), 0x00 }, { CCI_REG8(0x52a9), 0x50 }, ++ { CCI_REG8(0x52aa), 0x00 }, { CCI_REG8(0x52ab), 0x50 }, ++ { CCI_REG8(0x52ac), 0x00 }, { CCI_REG8(0x52ad), 0x50 }, ++ { CCI_REG8(0x52ae), 0x00 }, { CCI_REG8(0x52af), 0x50 }, ++ { CCI_REG8(0x52b0), 0x00 }, { CCI_REG8(0x52b1), 0x50 }, ++ { CCI_REG8(0x52b2), 0x00 }, { CCI_REG8(0x52b3), 0x50 }, ++ { CCI_REG8(0x52b4), 0x00 }, { CCI_REG8(0x52b5), 0x50 }, ++ { CCI_REG8(0x52b6), 0x00 }, { CCI_REG8(0x52b7), 0x50 }, ++ { CCI_REG8(0x52b8), 0x00 }, { CCI_REG8(0x52b9), 0x50 }, ++ { CCI_REG8(0x52ba), 0x01 }, { CCI_REG8(0x52bb), 0x00 }, ++ { CCI_REG8(0x52bc), 0x01 }, { CCI_REG8(0x52bd), 0x00 }, ++ { CCI_REG8(0x52be), 0x00 }, { CCI_REG8(0x52bf), 0x50 }, ++ { CCI_REG8(0x52c0), 0x00 }, { CCI_REG8(0x52c1), 0x50 }, ++ { CCI_REG8(0x52c2), 0x01 }, { CCI_REG8(0x52c3), 0x00 }, ++ { CCI_REG8(0x52c4), 0x01 }, { CCI_REG8(0x52c5), 0x00 }, ++ { CCI_REG8(0x52c6), 0x00 }, { CCI_REG8(0x52c7), 0x50 }, ++ { CCI_REG8(0x52c8), 0x00 }, { CCI_REG8(0x52c9), 0x50 }, ++ { CCI_REG8(0x52ca), 0x00 }, { CCI_REG8(0x52cb), 0x50 }, ++ { CCI_REG8(0x52cc), 0x00 }, { CCI_REG8(0x52cd), 0x50 }, ++ { CCI_REG8(0x52ce), 0x00 }, { CCI_REG8(0x52cf), 0x50 }, ++ { CCI_REG8(0x52f0), 0x04 }, { CCI_REG8(0x52f1), 0x03 }, ++ { CCI_REG8(0x52f2), 0x02 }, { CCI_REG8(0x52f3), 0x01 }, ++ { CCI_REG8(0x52f4), 0x08 }, { CCI_REG8(0x52f5), 0x07 }, ++ { CCI_REG8(0x52f6), 0x06 }, { CCI_REG8(0x52f7), 0x05 }, ++ { CCI_REG8(0x52f8), 0x0c }, { CCI_REG8(0x52f9), 0x0b }, ++ { CCI_REG8(0x52fa), 0x0a }, { CCI_REG8(0x52fb), 0x09 }, ++ { CCI_REG8(0x52fc), 0x10 }, { CCI_REG8(0x52fd), 0x0f }, ++ { CCI_REG8(0x52fe), 0x0e }, { CCI_REG8(0x52ff), 0x0d }, ++ { CCI_REG8(0x5300), 0x14 }, { CCI_REG8(0x5301), 0x13 }, ++ { CCI_REG8(0x5302), 0x12 }, { CCI_REG8(0x5303), 0x11 }, ++ { CCI_REG8(0x5304), 0x18 }, { CCI_REG8(0x5305), 0x17 }, ++ { CCI_REG8(0x5306), 0x16 }, { CCI_REG8(0x5307), 0x15 }, ++ { CCI_REG8(0x5308), 0x1c }, { CCI_REG8(0x5309), 0x1b }, ++ { CCI_REG8(0x530a), 0x1a }, { CCI_REG8(0x530b), 0x19 }, ++ { CCI_REG8(0x530c), 0x20 }, { CCI_REG8(0x530d), 0x1f }, ++ { CCI_REG8(0x530e), 0x1e }, { CCI_REG8(0x530f), 0x1d }, ++ { CCI_REG8(0x5310), 0x03 }, { CCI_REG8(0x5311), 0xe8 }, ++ { CCI_REG8(0x5331), 0x0a }, { CCI_REG8(0x5332), 0x43 }, ++ { CCI_REG8(0x5333), 0x45 }, { CCI_REG8(0x5353), 0x09 }, ++ { CCI_REG8(0x5354), 0x00 }, { CCI_REG8(0x5414), 0x03 }, ++ { CCI_REG8(0x54b0), 0x10 }, { CCI_REG8(0x54b3), 0x0e }, ++ { CCI_REG8(0x54b5), 0x02 }, { CCI_REG8(0x54b6), 0x00 }, ++ { CCI_REG8(0x54b7), 0x00 }, { CCI_REG8(0x54b8), 0x00 }, ++ { CCI_REG8(0x54b9), 0x70 }, { CCI_REG8(0x54ba), 0x00 }, ++ { CCI_REG8(0x54bb), 0x10 }, { CCI_REG8(0x54bc), 0x00 }, ++ { CCI_REG8(0x54bd), 0x00 }, { CCI_REG8(0x54d2), 0xff }, ++ { CCI_REG8(0x54d3), 0x1c }, { CCI_REG8(0x5510), 0x03 }, ++ { CCI_REG8(0x5511), 0xe8 }, { CCI_REG8(0x5550), 0x6c }, ++ { CCI_REG8(0x5551), 0x00 }, { CCI_REG8(0x557a), 0x00 }, ++ { CCI_REG8(0x557b), 0x38 }, { CCI_REG8(0x557c), 0x00 }, ++ { CCI_REG8(0x557d), 0x4b }, { CCI_REG8(0x5590), 0x00 }, ++ { CCI_REG8(0x5591), 0x50 }, { CCI_REG8(0x5592), 0x00 }, ++ { CCI_REG8(0x5593), 0x50 }, { CCI_REG8(0x5594), 0x00 }, ++ { CCI_REG8(0x5595), 0x50 }, { CCI_REG8(0x5596), 0x00 }, ++ { CCI_REG8(0x5597), 0x50 }, { CCI_REG8(0x5598), 0x00 }, ++ { CCI_REG8(0x5599), 0x50 }, { CCI_REG8(0x559a), 0x01 }, ++ { CCI_REG8(0x559b), 0x00 }, { CCI_REG8(0x559c), 0x01 }, ++ { CCI_REG8(0x559d), 0x00 }, { CCI_REG8(0x559e), 0x00 }, ++ { CCI_REG8(0x559f), 0x50 }, { CCI_REG8(0x55a0), 0x00 }, ++ { CCI_REG8(0x55a1), 0x50 }, { CCI_REG8(0x55a2), 0x01 }, ++ { CCI_REG8(0x55a3), 0x00 }, { CCI_REG8(0x55a4), 0x01 }, ++ { CCI_REG8(0x55a5), 0x00 }, { CCI_REG8(0x55a6), 0x00 }, ++ { CCI_REG8(0x55a7), 0x50 }, { CCI_REG8(0x55a8), 0x00 }, ++ { CCI_REG8(0x55a9), 0x50 }, { CCI_REG8(0x55aa), 0x00 }, ++ { CCI_REG8(0x55ab), 0x50 }, { CCI_REG8(0x55ac), 0x00 }, ++ { CCI_REG8(0x55ad), 0x50 }, { CCI_REG8(0x55ae), 0x00 }, ++ { CCI_REG8(0x55af), 0x50 }, { CCI_REG8(0x55b0), 0x00 }, ++ { CCI_REG8(0x55b1), 0x50 }, { CCI_REG8(0x55b2), 0x00 }, ++ { CCI_REG8(0x55b3), 0x50 }, { CCI_REG8(0x55b4), 0x00 }, ++ { CCI_REG8(0x55b5), 0x50 }, { CCI_REG8(0x55b6), 0x00 }, ++ { CCI_REG8(0x55b7), 0x50 }, { CCI_REG8(0x55b8), 0x00 }, ++ { CCI_REG8(0x55b9), 0x50 }, { CCI_REG8(0x55ba), 0x01 }, ++ { CCI_REG8(0x55bb), 0x00 }, { CCI_REG8(0x55bc), 0x01 }, ++ { CCI_REG8(0x55bd), 0x00 }, { CCI_REG8(0x55be), 0x00 }, ++ { CCI_REG8(0x55bf), 0x50 }, { CCI_REG8(0x55c0), 0x00 }, ++ { CCI_REG8(0x55c1), 0x50 }, { CCI_REG8(0x55c2), 0x01 }, ++ { CCI_REG8(0x55c3), 0x00 }, { CCI_REG8(0x55c4), 0x01 }, ++ { CCI_REG8(0x55c5), 0x00 }, { CCI_REG8(0x55c6), 0x00 }, ++ { CCI_REG8(0x55c7), 0x50 }, { CCI_REG8(0x55c8), 0x00 }, ++ { CCI_REG8(0x55c9), 0x50 }, { CCI_REG8(0x55ca), 0x00 }, ++ { CCI_REG8(0x55cb), 0x50 }, { CCI_REG8(0x55cc), 0x00 }, ++ { CCI_REG8(0x55cd), 0x50 }, { CCI_REG8(0x55ce), 0x00 }, ++ { CCI_REG8(0x55cf), 0x50 }, { CCI_REG8(0x55f0), 0x04 }, ++ { CCI_REG8(0x55f1), 0x03 }, { CCI_REG8(0x55f2), 0x02 }, ++ { CCI_REG8(0x55f3), 0x01 }, { CCI_REG8(0x55f4), 0x08 }, ++ { CCI_REG8(0x55f5), 0x07 }, { CCI_REG8(0x55f6), 0x06 }, ++ { CCI_REG8(0x55f7), 0x05 }, { CCI_REG8(0x55f8), 0x0c }, ++ { CCI_REG8(0x55f9), 0x0b }, { CCI_REG8(0x55fa), 0x0a }, ++ { CCI_REG8(0x55fb), 0x09 }, { CCI_REG8(0x55fc), 0x10 }, ++ { CCI_REG8(0x55fd), 0x0f }, { CCI_REG8(0x55fe), 0x0e }, ++ { CCI_REG8(0x55ff), 0x0d }, { CCI_REG8(0x5600), 0x14 }, ++ { CCI_REG8(0x5601), 0x13 }, { CCI_REG8(0x5602), 0x12 }, ++ { CCI_REG8(0x5603), 0x11 }, { CCI_REG8(0x5604), 0x18 }, ++ { CCI_REG8(0x5605), 0x17 }, { CCI_REG8(0x5606), 0x16 }, ++ { CCI_REG8(0x5607), 0x15 }, { CCI_REG8(0x5608), 0x1c }, ++ { CCI_REG8(0x5609), 0x1b }, { CCI_REG8(0x560a), 0x1a }, ++ { CCI_REG8(0x560b), 0x19 }, { CCI_REG8(0x560c), 0x20 }, ++ { CCI_REG8(0x560d), 0x1f }, { CCI_REG8(0x560e), 0x1e }, ++ { CCI_REG8(0x560f), 0x1d }, { CCI_REG8(0x5631), 0x02 }, ++ { CCI_REG8(0x5632), 0x42 }, { CCI_REG8(0x5633), 0x24 }, ++ { CCI_REG8(0x5653), 0x09 }, { CCI_REG8(0x5654), 0x00 }, ++ { CCI_REG8(0x5714), 0x03 }, { CCI_REG8(0x57b0), 0x10 }, ++ { CCI_REG8(0x57b3), 0x0e }, { CCI_REG8(0x57b5), 0x02 }, ++ { CCI_REG8(0x57b6), 0x00 }, { CCI_REG8(0x57b7), 0x00 }, ++ { CCI_REG8(0x57b8), 0x00 }, { CCI_REG8(0x57b9), 0x70 }, ++ { CCI_REG8(0x57ba), 0x00 }, { CCI_REG8(0x57bb), 0x10 }, ++ { CCI_REG8(0x57bc), 0x00 }, { CCI_REG8(0x57bd), 0x00 }, ++ { CCI_REG8(0x57d2), 0xff }, { CCI_REG8(0x57d3), 0x1c }, ++ { CCI_REG8(0x5810), 0x03 }, { CCI_REG8(0x5811), 0xe8 }, ++ { CCI_REG8(0x5850), 0x6c }, { CCI_REG8(0x5851), 0x00 }, ++ { CCI_REG8(0x587a), 0x00 }, { CCI_REG8(0x587b), 0x38 }, ++ { CCI_REG8(0x587c), 0x00 }, { CCI_REG8(0x587d), 0x4b }, ++ { CCI_REG8(0x5890), 0x00 }, { CCI_REG8(0x5891), 0x50 }, ++ { CCI_REG8(0x5892), 0x00 }, { CCI_REG8(0x5893), 0x50 }, ++ { CCI_REG8(0x5894), 0x00 }, { CCI_REG8(0x5895), 0x50 }, ++ { CCI_REG8(0x5896), 0x00 }, { CCI_REG8(0x5897), 0x50 }, ++ { CCI_REG8(0x5898), 0x00 }, { CCI_REG8(0x5899), 0x50 }, ++ { CCI_REG8(0x589a), 0x01 }, { CCI_REG8(0x589b), 0x00 }, ++ { CCI_REG8(0x589c), 0x01 }, { CCI_REG8(0x589d), 0x00 }, ++ { CCI_REG8(0x589e), 0x00 }, { CCI_REG8(0x589f), 0x50 }, ++ { CCI_REG8(0x58a0), 0x00 }, { CCI_REG8(0x58a1), 0x50 }, ++ { CCI_REG8(0x58a2), 0x01 }, { CCI_REG8(0x58a3), 0x00 }, ++ { CCI_REG8(0x58a4), 0x01 }, { CCI_REG8(0x58a5), 0x00 }, ++ { CCI_REG8(0x58a6), 0x00 }, { CCI_REG8(0x58a7), 0x50 }, ++ { CCI_REG8(0x58a8), 0x00 }, { CCI_REG8(0x58a9), 0x50 }, ++ { CCI_REG8(0x58aa), 0x00 }, { CCI_REG8(0x58ab), 0x50 }, ++ { CCI_REG8(0x58ac), 0x00 }, { CCI_REG8(0x58ad), 0x50 }, ++ { CCI_REG8(0x58ae), 0x00 }, { CCI_REG8(0x58af), 0x50 }, ++ { CCI_REG8(0x58b0), 0x00 }, { CCI_REG8(0x58b1), 0x50 }, ++ { CCI_REG8(0x58b2), 0x00 }, { CCI_REG8(0x58b3), 0x50 }, ++ { CCI_REG8(0x58b4), 0x00 }, { CCI_REG8(0x58b5), 0x50 }, ++ { CCI_REG8(0x58b6), 0x00 }, { CCI_REG8(0x58b7), 0x50 }, ++ { CCI_REG8(0x58b8), 0x00 }, { CCI_REG8(0x58b9), 0x50 }, ++ { CCI_REG8(0x58ba), 0x01 }, { CCI_REG8(0x58bb), 0x00 }, ++ { CCI_REG8(0x58bc), 0x01 }, { CCI_REG8(0x58bd), 0x00 }, ++ { CCI_REG8(0x58be), 0x00 }, { CCI_REG8(0x58bf), 0x50 }, ++ { CCI_REG8(0x58c0), 0x00 }, { CCI_REG8(0x58c1), 0x50 }, ++ { CCI_REG8(0x58c2), 0x01 }, { CCI_REG8(0x58c3), 0x00 }, ++ { CCI_REG8(0x58c4), 0x01 }, { CCI_REG8(0x58c5), 0x00 }, ++ { CCI_REG8(0x58c6), 0x00 }, { CCI_REG8(0x58c7), 0x50 }, ++ { CCI_REG8(0x58c8), 0x00 }, { CCI_REG8(0x58c9), 0x50 }, ++ { CCI_REG8(0x58ca), 0x00 }, { CCI_REG8(0x58cb), 0x50 }, ++ { CCI_REG8(0x58cc), 0x00 }, { CCI_REG8(0x58cd), 0x50 }, ++ { CCI_REG8(0x58ce), 0x00 }, { CCI_REG8(0x58cf), 0x50 }, ++ { CCI_REG8(0x58f0), 0x04 }, { CCI_REG8(0x58f1), 0x03 }, ++ { CCI_REG8(0x58f2), 0x02 }, { CCI_REG8(0x58f3), 0x01 }, ++ { CCI_REG8(0x58f4), 0x08 }, { CCI_REG8(0x58f5), 0x07 }, ++ { CCI_REG8(0x58f6), 0x06 }, { CCI_REG8(0x58f7), 0x05 }, ++ { CCI_REG8(0x58f8), 0x0c }, { CCI_REG8(0x58f9), 0x0b }, ++ { CCI_REG8(0x58fa), 0x0a }, { CCI_REG8(0x58fb), 0x09 }, ++ { CCI_REG8(0x58fc), 0x10 }, { CCI_REG8(0x58fd), 0x0f }, ++ { CCI_REG8(0x58fe), 0x0e }, { CCI_REG8(0x58ff), 0x0d }, ++ { CCI_REG8(0x5900), 0x14 }, { CCI_REG8(0x5901), 0x13 }, ++ { CCI_REG8(0x5902), 0x12 }, { CCI_REG8(0x5903), 0x11 }, ++ { CCI_REG8(0x5904), 0x18 }, { CCI_REG8(0x5905), 0x17 }, ++ { CCI_REG8(0x5906), 0x16 }, { CCI_REG8(0x5907), 0x15 }, ++ { CCI_REG8(0x5908), 0x1c }, { CCI_REG8(0x5909), 0x1b }, ++ { CCI_REG8(0x590a), 0x1a }, { CCI_REG8(0x590b), 0x19 }, ++ { CCI_REG8(0x590c), 0x20 }, { CCI_REG8(0x590d), 0x1f }, ++ { CCI_REG8(0x590e), 0x1e }, { CCI_REG8(0x590f), 0x1d }, ++ { CCI_REG8(0x5931), 0x02 }, { CCI_REG8(0x5932), 0x42 }, ++ { CCI_REG8(0x5933), 0x24 }, { CCI_REG8(0x5953), 0x09 }, ++ { CCI_REG8(0x5954), 0x00 }, { CCI_REG8(0x5989), 0x84 }, ++ { CCI_REG8(0x59c3), 0x04 }, { CCI_REG8(0x59c4), 0x24 }, ++ { CCI_REG8(0x59c5), 0x40 }, { CCI_REG8(0x59c6), 0x1b }, ++ { CCI_REG8(0x59c7), 0x40 }, { CCI_REG8(0x5a02), 0x0f }, ++ { CCI_REG8(0x5f00), 0x29 }, { CCI_REG8(0x5f2d), 0x28 }, ++ { CCI_REG8(0x5f2e), 0x28 }, { CCI_REG8(0x6801), 0x11 }, ++ { CCI_REG8(0x6802), 0x3f }, { CCI_REG8(0x6803), 0xe7 }, ++ { CCI_REG8(0x6825), 0x0f }, { CCI_REG8(0x6826), 0x20 }, ++ { CCI_REG8(0x6827), 0x00 }, { CCI_REG8(0x6829), 0x16 }, ++ { CCI_REG8(0x682b), 0xb3 }, { CCI_REG8(0x682c), 0x01 }, ++ { CCI_REG8(0x6832), 0xff }, { CCI_REG8(0x6833), 0xff }, ++ { CCI_REG8(0x6898), 0x80 }, { CCI_REG8(0x6899), 0x80 }, ++ { CCI_REG8(0x689b), 0x40 }, { CCI_REG8(0x689c), 0x20 }, ++ { CCI_REG8(0x689d), 0x20 }, { CCI_REG8(0x689e), 0x80 }, ++ { CCI_REG8(0x689f), 0x60 }, { CCI_REG8(0x68a0), 0x40 }, ++ { CCI_REG8(0x68a4), 0x40 }, { CCI_REG8(0x68a5), 0x20 }, ++ { CCI_REG8(0x68a6), 0x00 }, { CCI_REG8(0x68b6), 0x80 }, ++ { CCI_REG8(0x68b7), 0x80 }, { CCI_REG8(0x68b8), 0x80 }, ++ { CCI_REG8(0x68bc), 0x80 }, { CCI_REG8(0x68bd), 0x80 }, ++ { CCI_REG8(0x68be), 0x80 }, { CCI_REG8(0x68bf), 0x40 }, ++ { CCI_REG8(0x68c2), 0x80 }, { CCI_REG8(0x68c3), 0x80 }, ++ { CCI_REG8(0x68c4), 0x60 }, { CCI_REG8(0x68c5), 0x30 }, ++ { CCI_REG8(0x6918), 0x80 }, { CCI_REG8(0x6919), 0x80 }, ++ { CCI_REG8(0x691b), 0x40 }, { CCI_REG8(0x691c), 0x20 }, ++ { CCI_REG8(0x691d), 0x20 }, { CCI_REG8(0x691e), 0x80 }, ++ { CCI_REG8(0x691f), 0x60 }, { CCI_REG8(0x6920), 0x40 }, ++ { CCI_REG8(0x6924), 0x40 }, { CCI_REG8(0x6925), 0x20 }, ++ { CCI_REG8(0x6926), 0x00 }, { CCI_REG8(0x6936), 0x40 }, ++ { CCI_REG8(0x6937), 0x40 }, { CCI_REG8(0x6938), 0x20 }, ++ { CCI_REG8(0x6939), 0x20 }, { CCI_REG8(0x693a), 0x10 }, ++ { CCI_REG8(0x693b), 0x10 }, { CCI_REG8(0x693c), 0x20 }, ++ { CCI_REG8(0x693d), 0x20 }, { CCI_REG8(0x693e), 0x10 }, ++ { CCI_REG8(0x693f), 0x10 }, { CCI_REG8(0x6940), 0x00 }, ++ { CCI_REG8(0x6941), 0x00 }, { CCI_REG8(0x6942), 0x08 }, ++ { CCI_REG8(0x6943), 0x08 }, { CCI_REG8(0x6944), 0x00 }, ++ { CCI_REG8(0x69c2), 0x07 }, { CCI_REG8(0x6a20), 0x01 }, ++ { CCI_REG8(0x6a23), 0x10 }, { CCI_REG8(0x6a26), 0x3d }, ++ { CCI_REG8(0x6a27), 0x3e }, { CCI_REG8(0x6a38), 0x02 }, ++ { CCI_REG8(0x6a39), 0x20 }, { CCI_REG8(0x6a3a), 0x02 }, ++ { CCI_REG8(0x6a3b), 0x84 }, { CCI_REG8(0x6a3e), 0x02 }, ++ { CCI_REG8(0x6a3f), 0x20 }, { CCI_REG8(0x6a47), 0x3b }, ++ { CCI_REG8(0x6a63), 0x04 }, { CCI_REG8(0x6a65), 0x00 }, ++ { CCI_REG8(0x6a67), 0x0f }, { CCI_REG8(0x6b22), 0x07 }, ++ { CCI_REG8(0x6b23), 0xc2 }, { CCI_REG8(0x6b2f), 0x00 }, ++ { CCI_REG8(0x6b60), 0x1f }, { CCI_REG8(0x6bd2), 0x5a }, ++ { CCI_REG8(0x6c20), 0x50 }, { CCI_REG8(0x6c60), 0x50 }, ++ { CCI_REG8(0x6c61), 0x06 }, { CCI_REG8(0x7318), 0x04 }, ++ { CCI_REG8(0x7319), 0x01 }, { CCI_REG8(0x731a), 0x04 }, ++ { CCI_REG8(0x731b), 0x01 }, { CCI_REG8(0x731c), 0x00 }, ++ { CCI_REG8(0x731d), 0x00 }, { CCI_REG8(0x731e), 0x04 }, ++ { CCI_REG8(0x731f), 0x01 }, { CCI_REG8(0x7320), 0x04 }, ++ { CCI_REG8(0x7321), 0x00 }, { CCI_REG8(0x7322), 0x04 }, ++ { CCI_REG8(0x7323), 0x00 }, { CCI_REG8(0x7324), 0x04 }, ++ { CCI_REG8(0x7325), 0x00 }, { CCI_REG8(0x7326), 0x04 }, ++ { CCI_REG8(0x7327), 0x00 }, { CCI_REG8(0x7600), 0x00 }, ++ { CCI_REG8(0x7601), 0x00 }, { CCI_REG8(0x7602), 0x10 }, ++ { CCI_REG8(0x7603), 0x00 }, { CCI_REG8(0x7604), 0x00 }, ++ { CCI_REG8(0x7605), 0x00 }, { CCI_REG8(0x7606), 0x10 }, ++ { CCI_REG8(0x7607), 0x00 }, { CCI_REG8(0x7608), 0x00 }, ++ { CCI_REG8(0x7609), 0x00 }, { CCI_REG8(0x760a), 0x10 }, ++ { CCI_REG8(0x760b), 0x00 }, { CCI_REG8(0x760c), 0x00 }, ++ { CCI_REG8(0x760d), 0x00 }, { CCI_REG8(0x760e), 0x10 }, ++ { CCI_REG8(0x760f), 0x00 }, { CCI_REG8(0x7610), 0x00 }, ++ { CCI_REG8(0x7611), 0x00 }, { CCI_REG8(0x7612), 0x10 }, ++ { CCI_REG8(0x7613), 0x00 }, { CCI_REG8(0x7614), 0x00 }, ++ { CCI_REG8(0x7615), 0x00 }, { CCI_REG8(0x7616), 0x10 }, ++ { CCI_REG8(0x7617), 0x00 }, { CCI_REG8(0x7618), 0x00 }, ++ { CCI_REG8(0x7619), 0x00 }, { CCI_REG8(0x761a), 0x10 }, ++ { CCI_REG8(0x761b), 0x00 }, { CCI_REG8(0x761c), 0x00 }, ++ { CCI_REG8(0x761d), 0x00 }, { CCI_REG8(0x761e), 0x10 }, ++ { CCI_REG8(0x761f), 0x00 }, { CCI_REG8(0x7620), 0x00 }, ++ { CCI_REG8(0x7621), 0x00 }, { CCI_REG8(0x7622), 0x10 }, ++ { CCI_REG8(0x7623), 0x00 }, { CCI_REG8(0x7624), 0x00 }, ++ { CCI_REG8(0x7625), 0x00 }, { CCI_REG8(0x7626), 0x10 }, ++ { CCI_REG8(0x7627), 0x00 }, { CCI_REG8(0x7628), 0x00 }, ++ { CCI_REG8(0x7629), 0x00 }, { CCI_REG8(0x762a), 0x10 }, ++ { CCI_REG8(0x762b), 0x00 }, { CCI_REG8(0x762c), 0x00 }, ++ { CCI_REG8(0x762d), 0x00 }, { CCI_REG8(0x762e), 0x10 }, ++ { CCI_REG8(0x762f), 0x00 }, { CCI_REG8(0x7630), 0x00 }, ++ { CCI_REG8(0x7631), 0x00 }, { CCI_REG8(0x7632), 0x10 }, ++ { CCI_REG8(0x7633), 0x00 }, { CCI_REG8(0x7634), 0x00 }, ++ { CCI_REG8(0x7635), 0x00 }, { CCI_REG8(0x7636), 0x10 }, ++ { CCI_REG8(0x7637), 0x00 }, { CCI_REG8(0x7638), 0x00 }, ++ { CCI_REG8(0x7639), 0x00 }, { CCI_REG8(0x763a), 0x10 }, ++ { CCI_REG8(0x763b), 0x00 }, { CCI_REG8(0x763c), 0x00 }, ++ { CCI_REG8(0x763d), 0x00 }, { CCI_REG8(0x763e), 0x10 }, ++ { CCI_REG8(0x763f), 0x00 }, { CCI_REG8(0x7640), 0x00 }, ++ { CCI_REG8(0x7641), 0x00 }, { CCI_REG8(0x7642), 0x10 }, ++ { CCI_REG8(0x7643), 0x00 }, { CCI_REG8(0x7644), 0x00 }, ++ { CCI_REG8(0x7645), 0x00 }, { CCI_REG8(0x7646), 0x10 }, ++ { CCI_REG8(0x7647), 0x00 }, { CCI_REG8(0x7648), 0x00 }, ++ { CCI_REG8(0x7649), 0x00 }, { CCI_REG8(0x764a), 0x10 }, ++ { CCI_REG8(0x764b), 0x00 }, { CCI_REG8(0x764c), 0x00 }, ++ { CCI_REG8(0x764d), 0x00 }, { CCI_REG8(0x764e), 0x10 }, ++ { CCI_REG8(0x764f), 0x00 }, { CCI_REG8(0x7650), 0x00 }, ++ { CCI_REG8(0x7651), 0x00 }, { CCI_REG8(0x7652), 0x10 }, ++ { CCI_REG8(0x7653), 0x00 }, { CCI_REG8(0x7654), 0x00 }, ++ { CCI_REG8(0x7655), 0x00 }, { CCI_REG8(0x7656), 0x10 }, ++ { CCI_REG8(0x7657), 0x00 }, { CCI_REG8(0x7658), 0x00 }, ++ { CCI_REG8(0x7659), 0x00 }, { CCI_REG8(0x765a), 0x10 }, ++ { CCI_REG8(0x765b), 0x00 }, { CCI_REG8(0x765c), 0x00 }, ++ { CCI_REG8(0x765d), 0x00 }, { CCI_REG8(0x765e), 0x10 }, ++ { CCI_REG8(0x765f), 0x00 }, { CCI_REG8(0x7660), 0x00 }, ++ { CCI_REG8(0x7661), 0x00 }, { CCI_REG8(0x7662), 0x10 }, ++ { CCI_REG8(0x7663), 0x00 }, { CCI_REG8(0x7664), 0x00 }, ++ { CCI_REG8(0x7665), 0x00 }, { CCI_REG8(0x7666), 0x10 }, ++ { CCI_REG8(0x7667), 0x00 }, { CCI_REG8(0x7668), 0x00 }, ++ { CCI_REG8(0x7669), 0x00 }, { CCI_REG8(0x766a), 0x10 }, ++ { CCI_REG8(0x766b), 0x00 }, { CCI_REG8(0x766c), 0x00 }, ++ { CCI_REG8(0x766d), 0x00 }, { CCI_REG8(0x766e), 0x10 }, ++ { CCI_REG8(0x766f), 0x00 }, { CCI_REG8(0x7670), 0x00 }, ++ { CCI_REG8(0x7671), 0x00 }, { CCI_REG8(0x7672), 0x10 }, ++ { CCI_REG8(0x7673), 0x00 }, { CCI_REG8(0x7674), 0x00 }, ++ { CCI_REG8(0x7675), 0x00 }, { CCI_REG8(0x7676), 0x10 }, ++ { CCI_REG8(0x7677), 0x00 }, { CCI_REG8(0x7678), 0x00 }, ++ { CCI_REG8(0x7679), 0x00 }, { CCI_REG8(0x767a), 0x10 }, ++ { CCI_REG8(0x767b), 0x00 }, { CCI_REG8(0x767c), 0x00 }, ++ { CCI_REG8(0x767d), 0x00 }, { CCI_REG8(0x767e), 0x10 }, ++ { CCI_REG8(0x767f), 0x00 }, { CCI_REG8(0x7680), 0x00 }, ++ { CCI_REG8(0x7681), 0x00 }, { CCI_REG8(0x7682), 0x10 }, ++ { CCI_REG8(0x7683), 0x00 }, { CCI_REG8(0x7684), 0x00 }, ++ { CCI_REG8(0x7685), 0x00 }, { CCI_REG8(0x7686), 0x10 }, ++ { CCI_REG8(0x7687), 0x00 }, { CCI_REG8(0x7688), 0x00 }, ++ { CCI_REG8(0x7689), 0x00 }, { CCI_REG8(0x768a), 0x10 }, ++ { CCI_REG8(0x768b), 0x00 }, { CCI_REG8(0x768c), 0x00 }, ++ { CCI_REG8(0x768d), 0x00 }, { CCI_REG8(0x768e), 0x10 }, ++ { CCI_REG8(0x768f), 0x00 }, { CCI_REG8(0x7690), 0x00 }, ++ { CCI_REG8(0x7691), 0x00 }, { CCI_REG8(0x7692), 0x10 }, ++ { CCI_REG8(0x7693), 0x00 }, { CCI_REG8(0x7694), 0x00 }, ++ { CCI_REG8(0x7695), 0x00 }, { CCI_REG8(0x7696), 0x10 }, ++ { CCI_REG8(0x7697), 0x00 }, { CCI_REG8(0x7698), 0x00 }, ++ { CCI_REG8(0x7699), 0x00 }, { CCI_REG8(0x769a), 0x10 }, ++ { CCI_REG8(0x769b), 0x00 }, { CCI_REG8(0x769c), 0x00 }, ++ { CCI_REG8(0x769d), 0x00 }, { CCI_REG8(0x769e), 0x10 }, ++ { CCI_REG8(0x769f), 0x00 }, { CCI_REG8(0x76a0), 0x00 }, ++ { CCI_REG8(0x76a1), 0x00 }, { CCI_REG8(0x76a2), 0x10 }, ++ { CCI_REG8(0x76a3), 0x00 }, { CCI_REG8(0x76a4), 0x00 }, ++ { CCI_REG8(0x76a5), 0x00 }, { CCI_REG8(0x76a6), 0x10 }, ++ { CCI_REG8(0x76a7), 0x00 }, { CCI_REG8(0x76a8), 0x00 }, ++ { CCI_REG8(0x76a9), 0x00 }, { CCI_REG8(0x76aa), 0x10 }, ++ { CCI_REG8(0x76ab), 0x00 }, { CCI_REG8(0x76ac), 0x00 }, ++ { CCI_REG8(0x76ad), 0x00 }, { CCI_REG8(0x76ae), 0x10 }, ++ { CCI_REG8(0x76af), 0x00 }, { CCI_REG8(0x76b0), 0x00 }, ++ { CCI_REG8(0x76b1), 0x00 }, { CCI_REG8(0x76b2), 0x10 }, ++ { CCI_REG8(0x76b3), 0x00 }, { CCI_REG8(0x76b4), 0x00 }, ++ { CCI_REG8(0x76b5), 0x00 }, { CCI_REG8(0x76b6), 0x10 }, ++ { CCI_REG8(0x76b7), 0x00 }, { CCI_REG8(0x76b8), 0x00 }, ++ { CCI_REG8(0x76b9), 0x00 }, { CCI_REG8(0x76ba), 0x10 }, ++ { CCI_REG8(0x76bb), 0x00 }, { CCI_REG8(0x76bc), 0x00 }, ++ { CCI_REG8(0x76bd), 0x00 }, { CCI_REG8(0x76be), 0x10 }, ++ { CCI_REG8(0x76bf), 0x00 }, { CCI_REG8(0x76c0), 0x00 }, ++ { CCI_REG8(0x76c1), 0x00 }, { CCI_REG8(0x76c2), 0x10 }, ++ { CCI_REG8(0x76c3), 0x00 }, { CCI_REG8(0x76c4), 0x00 }, ++ { CCI_REG8(0x76c5), 0x00 }, { CCI_REG8(0x76c6), 0x10 }, ++ { CCI_REG8(0x76c7), 0x00 }, { CCI_REG8(0x76c8), 0x00 }, ++ { CCI_REG8(0x76c9), 0x00 }, { CCI_REG8(0x76ca), 0x10 }, ++ { CCI_REG8(0x76cb), 0x00 }, { CCI_REG8(0x76cc), 0x00 }, ++ { CCI_REG8(0x76cd), 0x00 }, { CCI_REG8(0x76ce), 0x10 }, ++ { CCI_REG8(0x76cf), 0x00 }, { CCI_REG8(0x76d0), 0x00 }, ++ { CCI_REG8(0x76d1), 0x00 }, { CCI_REG8(0x76d2), 0x10 }, ++ { CCI_REG8(0x76d3), 0x00 }, { CCI_REG8(0x76d4), 0x00 }, ++ { CCI_REG8(0x76d5), 0x00 }, { CCI_REG8(0x76d6), 0x10 }, ++ { CCI_REG8(0x76d7), 0x00 }, { CCI_REG8(0x76d8), 0x00 }, ++ { CCI_REG8(0x76d9), 0x00 }, { CCI_REG8(0x76da), 0x10 }, ++ { CCI_REG8(0x76db), 0x00 }, { CCI_REG8(0x76dc), 0x00 }, ++ { CCI_REG8(0x76dd), 0x00 }, { CCI_REG8(0x76de), 0x10 }, ++ { CCI_REG8(0x76df), 0x00 }, { CCI_REG8(0x76e0), 0x00 }, ++ { CCI_REG8(0x76e1), 0x00 }, { CCI_REG8(0x76e2), 0x10 }, ++ { CCI_REG8(0x76e3), 0x00 }, { CCI_REG8(0x76e4), 0x00 }, ++ { CCI_REG8(0x76e5), 0x00 }, { CCI_REG8(0x76e6), 0x10 }, ++ { CCI_REG8(0x76e7), 0x00 }, { CCI_REG8(0x76e8), 0x00 }, ++ { CCI_REG8(0x76e9), 0x00 }, { CCI_REG8(0x76ea), 0x10 }, ++ { CCI_REG8(0x76eb), 0x00 }, { CCI_REG8(0x76ec), 0x00 }, ++ { CCI_REG8(0x76ed), 0x00 }, { CCI_REG8(0x76ee), 0x10 }, ++ { CCI_REG8(0x76ef), 0x00 }, { CCI_REG8(0x76f0), 0x00 }, ++ { CCI_REG8(0x76f1), 0x00 }, { CCI_REG8(0x76f2), 0x10 }, ++ { CCI_REG8(0x76f3), 0x00 }, { CCI_REG8(0x76f4), 0x00 }, ++ { CCI_REG8(0x76f5), 0x00 }, { CCI_REG8(0x76f6), 0x10 }, ++ { CCI_REG8(0x76f7), 0x00 }, { CCI_REG8(0x76f8), 0x00 }, ++ { CCI_REG8(0x76f9), 0x00 }, { CCI_REG8(0x76fa), 0x10 }, ++ { CCI_REG8(0x76fb), 0x00 }, { CCI_REG8(0x76fc), 0x00 }, ++ { CCI_REG8(0x76fd), 0x00 }, { CCI_REG8(0x76fe), 0x10 }, ++ { CCI_REG8(0x76ff), 0x00 }, { CCI_REG8(0x7700), 0x00 }, ++ { CCI_REG8(0x7701), 0x00 }, { CCI_REG8(0x7702), 0x10 }, ++ { CCI_REG8(0x7703), 0x00 }, { CCI_REG8(0x7704), 0x00 }, ++ { CCI_REG8(0x7705), 0x00 }, { CCI_REG8(0x7706), 0x10 }, ++ { CCI_REG8(0x7707), 0x00 }, { CCI_REG8(0x7708), 0x00 }, ++ { CCI_REG8(0x7709), 0x00 }, { CCI_REG8(0x770a), 0x10 }, ++ { CCI_REG8(0x770b), 0x00 }, { CCI_REG8(0x770c), 0x00 }, ++ { CCI_REG8(0x770d), 0x00 }, { CCI_REG8(0x770e), 0x10 }, ++ { CCI_REG8(0x770f), 0x00 }, { CCI_REG8(0x7710), 0x00 }, ++ { CCI_REG8(0x7711), 0x00 }, { CCI_REG8(0x7712), 0x10 }, ++ { CCI_REG8(0x7713), 0x00 }, { CCI_REG8(0x7714), 0x00 }, ++ { CCI_REG8(0x7715), 0x00 }, { CCI_REG8(0x7716), 0x10 }, ++ { CCI_REG8(0x7717), 0x00 }, { CCI_REG8(0x7718), 0x00 }, ++ { CCI_REG8(0x7719), 0x00 }, { CCI_REG8(0x771a), 0x10 }, ++ { CCI_REG8(0x771b), 0x00 }, { CCI_REG8(0x771c), 0x00 }, ++ { CCI_REG8(0x771d), 0x00 }, { CCI_REG8(0x771e), 0x10 }, ++ { CCI_REG8(0x771f), 0x00 }, { CCI_REG8(0x7720), 0x00 }, ++ { CCI_REG8(0x7721), 0x00 }, { CCI_REG8(0x7722), 0x10 }, ++ { CCI_REG8(0x7723), 0x00 }, { CCI_REG8(0x7724), 0x00 }, ++ { CCI_REG8(0x7725), 0x00 }, { CCI_REG8(0x7726), 0x10 }, ++ { CCI_REG8(0x7727), 0x00 }, { CCI_REG8(0x7728), 0x00 }, ++ { CCI_REG8(0x7729), 0x00 }, { CCI_REG8(0x772a), 0x10 }, ++ { CCI_REG8(0x772b), 0x00 }, { CCI_REG8(0x772c), 0x00 }, ++ { CCI_REG8(0x772d), 0x00 }, { CCI_REG8(0x772e), 0x10 }, ++ { CCI_REG8(0x772f), 0x00 }, { CCI_REG8(0x7730), 0x00 }, ++ { CCI_REG8(0x7731), 0x00 }, { CCI_REG8(0x7732), 0x10 }, ++ { CCI_REG8(0x7733), 0x00 }, { CCI_REG8(0x7734), 0x00 }, ++ { CCI_REG8(0x7735), 0x00 }, { CCI_REG8(0x7736), 0x10 }, ++ { CCI_REG8(0x7737), 0x00 }, { CCI_REG8(0x7738), 0x00 }, ++ { CCI_REG8(0x7739), 0x00 }, { CCI_REG8(0x773a), 0x10 }, ++ { CCI_REG8(0x773b), 0x00 }, { CCI_REG8(0x773c), 0x00 }, ++ { CCI_REG8(0x773d), 0x00 }, { CCI_REG8(0x773e), 0x10 }, ++ { CCI_REG8(0x773f), 0x00 }, { CCI_REG8(0x7740), 0x00 }, ++ { CCI_REG8(0x7741), 0x00 }, { CCI_REG8(0x7742), 0x10 }, ++ { CCI_REG8(0x7743), 0x00 }, { CCI_REG8(0x3421), 0x02 }, ++ { CCI_REG8(0x37d0), 0x00 }, { CCI_REG8(0x3632), 0x99 }, ++ { CCI_REG8(0xc518), 0x1f }, { CCI_REG8(0xc519), 0x1f }, ++ { CCI_REG8(0xc51a), 0x1f }, { CCI_REG8(0xc51b), 0x1f }, ++ { CCI_REG8(0xc51c), 0x1f }, { CCI_REG8(0xc51d), 0x1f }, ++ { CCI_REG8(0xc51e), 0x1f }, { CCI_REG8(0xc51f), 0x1f }, ++ { CCI_REG8(0xc520), 0x1f }, { CCI_REG8(0xc521), 0x1f }, ++ { CCI_REG8(0x3616), 0xa0 }, { CCI_REG8(0x3615), 0xc5 }, ++ { CCI_REG8(0xc4c1), 0x02 }, { CCI_REG8(0xc4c2), 0x02 }, ++ { CCI_REG8(0xc4c3), 0x03 }, { CCI_REG8(0xc4c4), 0x03 }, ++ { CCI_REG8(0xc4f6), 0x0a }, { CCI_REG8(0xc4f7), 0x0a }, ++ { CCI_REG8(0xc4f8), 0x0a }, { CCI_REG8(0xc4f9), 0x0a }, ++ { CCI_REG8(0xc4fa), 0x0a }, { CCI_REG8(0xc4c6), 0x0a }, ++ { CCI_REG8(0xc4c7), 0x0a }, { CCI_REG8(0xc4c8), 0x0a }, ++ { CCI_REG8(0xc4c9), 0x0a }, { CCI_REG8(0xc4ca), 0x14 }, ++ { CCI_REG8(0xc4cb), 0x14 }, { CCI_REG8(0xc4cc), 0x14 }, ++ { CCI_REG8(0xc4cd), 0x14 }, { CCI_REG8(0x3b92), 0x05 }, ++ { CCI_REG8(0x3b93), 0x05 }, { CCI_REG8(0x3b94), 0x05 }, ++ { CCI_REG8(0x3b95), 0x05 }, { CCI_REG8(0x3623), 0x10 }, ++ { CCI_REG8(0xc522), 0x18 }, { CCI_REG8(0xc523), 0x12 }, ++ { CCI_REG8(0xc524), 0x0e }, { CCI_REG8(0xc525), 0x0b }, ++ { CCI_REG8(0xc526), 0x18 }, { CCI_REG8(0xc527), 0x12 }, ++ { CCI_REG8(0xc528), 0x0c }, { CCI_REG8(0xc529), 0x08 }, ++ { CCI_REG8(0xc52a), 0x18 }, { CCI_REG8(0xc52b), 0x12 }, ++ { CCI_REG8(0xc52c), 0x0e }, { CCI_REG8(0xc52d), 0x0b }, ++ { CCI_REG8(0xc52e), 0x18 }, { CCI_REG8(0xc52f), 0x12 }, ++ { CCI_REG8(0xc530), 0x0e }, { CCI_REG8(0xc531), 0x0b }, ++ { CCI_REG8(0xc532), 0x18 }, { CCI_REG8(0xc533), 0x12 }, ++ { CCI_REG8(0xc534), 0x0e }, { CCI_REG8(0xc535), 0x0b }, ++ { CCI_REG8(0xc536), 0x18 }, { CCI_REG8(0xc537), 0x12 }, ++ { CCI_REG8(0xc538), 0x0e }, { CCI_REG8(0xc539), 0x0b }, ++ { CCI_REG8(0xc53a), 0x18 }, { CCI_REG8(0xc53b), 0x12 }, ++ { CCI_REG8(0xc53c), 0x0c }, { CCI_REG8(0xc53d), 0x08 }, ++ { CCI_REG8(0xc53e), 0x18 }, { CCI_REG8(0xc53f), 0x12 }, ++ { CCI_REG8(0xc540), 0x0e }, { CCI_REG8(0xc541), 0x0b }, ++ { CCI_REG8(0xc542), 0x18 }, { CCI_REG8(0xc543), 0x12 }, ++ { CCI_REG8(0xc544), 0x0e }, { CCI_REG8(0xc545), 0x0b }, ++ { CCI_REG8(0xc546), 0x18 }, { CCI_REG8(0xc547), 0x12 }, ++ { CCI_REG8(0xc548), 0x0e }, { CCI_REG8(0xc549), 0x0b }, ++ { CCI_REG8(0x3701), 0x18 }, { CCI_REG8(0x3702), 0x38 }, ++ { CCI_REG8(0x3703), 0x72 }, { CCI_REG8(0x3708), 0x26 }, ++ { CCI_REG8(0x3709), 0xe6 }, { CCI_REG8(0x3a1d), 0x18 }, ++ { CCI_REG8(0x3a1e), 0x18 }, { CCI_REG8(0x3a21), 0x18 }, ++ { CCI_REG8(0x3a22), 0x18 }, { CCI_REG8(0x39fb), 0x18 }, ++ { CCI_REG8(0x39fc), 0x18 }, { CCI_REG8(0x39fd), 0x18 }, ++ { CCI_REG8(0x39fe), 0x18 }, { CCI_REG8(0xc44a), 0x08 }, ++ { CCI_REG8(0xc44c), 0x08 }, { CCI_REG8(0xc5e8), 0x0a }, ++ { CCI_REG8(0xc5ea), 0x0a }, { CCI_REG8(0x391d), 0x54 }, ++ { CCI_REG8(0x391e), 0xca }, { CCI_REG8(0x3991), 0x0c }, ++ { CCI_REG8(0x399d), 0x0c }, { CCI_REG8(0x3744), 0x24 }, ++ { CCI_REG8(0x374b), 0x0c }, { CCI_REG8(0x3be7), 0x1e }, ++ { CCI_REG8(0x3be8), 0x26 }, { CCI_REG8(0x3a50), 0x14 }, ++ { CCI_REG8(0x3a54), 0x14 }, { CCI_REG8(0x3add), 0x1f }, ++ { CCI_REG8(0x3adf), 0x24 }, { CCI_REG8(0x3aef), 0x1f }, ++ { CCI_REG8(0x3af0), 0x24 }, { CCI_REG8(0xc57f), 0x30 }, ++ { CCI_REG8(0xc580), 0x30 }, { CCI_REG8(0xc581), 0x30 }, ++ { CCI_REG8(0xc582), 0x30 }, { CCI_REG8(0xc583), 0x30 }, ++ { CCI_REG8(0xc584), 0x30 }, { CCI_REG8(0xc585), 0x30 }, ++ { CCI_REG8(0xc586), 0x30 }, { CCI_REG8(0xc587), 0x30 }, ++ { CCI_REG8(0xc588), 0x30 }, { CCI_REG8(0xc589), 0x30 }, ++ { CCI_REG8(0xc58a), 0x30 }, { CCI_REG8(0xc58b), 0x30 }, ++ { CCI_REG8(0xc58c), 0x30 }, { CCI_REG8(0xc58d), 0x30 }, ++ { CCI_REG8(0xc58e), 0x30 }, { CCI_REG8(0xc58f), 0x30 }, ++ { CCI_REG8(0xc590), 0x30 }, { CCI_REG8(0xc591), 0x30 }, ++ { CCI_REG8(0xc592), 0x30 }, { CCI_REG8(0xc598), 0x30 }, ++ { CCI_REG8(0xc599), 0x30 }, { CCI_REG8(0xc59a), 0x30 }, ++ { CCI_REG8(0xc59b), 0x30 }, { CCI_REG8(0xc59c), 0x30 }, ++ { CCI_REG8(0xc59d), 0x30 }, { CCI_REG8(0xc59e), 0x30 }, ++ { CCI_REG8(0xc59f), 0x30 }, { CCI_REG8(0xc5a0), 0x30 }, ++ { CCI_REG8(0xc5a1), 0x30 }, { CCI_REG8(0xc5a2), 0x30 }, ++ { CCI_REG8(0xc5a3), 0x30 }, { CCI_REG8(0xc5a4), 0x30 }, ++ { CCI_REG8(0xc5a5), 0x30 }, { CCI_REG8(0xc5a6), 0x30 }, ++ { CCI_REG8(0xc5a7), 0x30 }, { CCI_REG8(0xc5a8), 0x30 }, ++ { CCI_REG8(0xc5a9), 0x30 }, { CCI_REG8(0xc5aa), 0x30 }, ++ { CCI_REG8(0xc5ab), 0x30 }, { CCI_REG8(0xc5b1), 0x38 }, ++ { CCI_REG8(0xc5b2), 0x38 }, { CCI_REG8(0xc5b3), 0x38 }, ++ { CCI_REG8(0xc5b4), 0x38 }, { CCI_REG8(0xc5b5), 0x38 }, ++ { CCI_REG8(0xc5b6), 0x38 }, { CCI_REG8(0xc5b7), 0x38 }, ++ { CCI_REG8(0xc5b8), 0x38 }, { CCI_REG8(0xc5b9), 0x38 }, ++ { CCI_REG8(0xc5ba), 0x38 }, { CCI_REG8(0xc5bb), 0x38 }, ++ { CCI_REG8(0xc5bc), 0x38 }, { CCI_REG8(0xc5bd), 0x38 }, ++ { CCI_REG8(0xc5be), 0x38 }, { CCI_REG8(0xc5bf), 0x38 }, ++ { CCI_REG8(0xc5c0), 0x38 }, { CCI_REG8(0xc5c1), 0x38 }, ++ { CCI_REG8(0xc5c2), 0x38 }, { CCI_REG8(0xc5c3), 0x38 }, ++ { CCI_REG8(0xc5c4), 0x38 }, { CCI_REG8(0xc5ca), 0x38 }, ++ { CCI_REG8(0xc5cb), 0x38 }, { CCI_REG8(0xc5cc), 0x38 }, ++ { CCI_REG8(0xc5cd), 0x38 }, { CCI_REG8(0xc5ce), 0x38 }, ++ { CCI_REG8(0xc5cf), 0x38 }, { CCI_REG8(0xc5d0), 0x38 }, ++ { CCI_REG8(0xc5d1), 0x38 }, { CCI_REG8(0xc5d2), 0x38 }, ++ { CCI_REG8(0xc5d3), 0x38 }, { CCI_REG8(0xc5d4), 0x38 }, ++ { CCI_REG8(0xc5d5), 0x38 }, { CCI_REG8(0xc5d6), 0x38 }, ++ { CCI_REG8(0xc5d7), 0x38 }, { CCI_REG8(0xc5d8), 0x38 }, ++ { CCI_REG8(0xc5d9), 0x38 }, { CCI_REG8(0xc5da), 0x38 }, ++ { CCI_REG8(0xc5db), 0x38 }, { CCI_REG8(0xc5dc), 0x38 }, ++ { CCI_REG8(0xc5dd), 0x38 }, { CCI_REG8(0x3a60), 0x68 }, ++ { CCI_REG8(0x3a6f), 0x68 }, { CCI_REG8(0x3a5e), 0xdc }, ++ { CCI_REG8(0x3a6d), 0xdc }, { CCI_REG8(0x3aed), 0x6e }, ++ { CCI_REG8(0x3af1), 0x73 }, { CCI_REG8(0x3992), 0x02 }, ++ { CCI_REG8(0x399e), 0x02 }, { CCI_REG8(0x371d), 0x17 }, ++ { CCI_REG8(0x371f), 0x08 }, { CCI_REG8(0x3721), 0xc9 }, ++ { CCI_REG8(0x401e), 0x00 }, { CCI_REG8(0x401f), 0xf8 }, ++ { CCI_REG8(0x3642), 0x00 }, { CCI_REG8(0x3641), 0x7f }, ++ { CCI_REG8(0x3ac5), 0x0c }, { CCI_REG8(0x3ac6), 0x09 }, ++ { CCI_REG8(0x3ac7), 0x06 }, { CCI_REG8(0x3ac8), 0x02 }, ++ { CCI_REG8(0x3ac9), 0x0c }, { CCI_REG8(0x3aca), 0x09 }, ++ { CCI_REG8(0x3acb), 0x06 }, { CCI_REG8(0x3acc), 0x02 }, ++ { CCI_REG8(0x3acd), 0x0c }, { CCI_REG8(0x3ace), 0x09 }, ++ { CCI_REG8(0x3acf), 0x07 }, { CCI_REG8(0x3ad0), 0x04 }, ++ { CCI_REG8(0x3ad1), 0x0c }, { CCI_REG8(0x3ad2), 0x09 }, ++ { CCI_REG8(0x3ad3), 0x07 }, { CCI_REG8(0x3ad4), 0x04 }, ++ { CCI_REG8(0xc483), 0x0c }, { CCI_REG8(0xc484), 0x0c }, ++ { CCI_REG8(0xc485), 0x0c }, { CCI_REG8(0xc486), 0x0c }, ++ { CCI_REG8(0x3a2f), 0x0c }, { CCI_REG8(0x3a30), 0x09 }, ++ { CCI_REG8(0x3a31), 0x06 }, { CCI_REG8(0x3a32), 0x02 }, ++ { CCI_REG8(0x3a34), 0x0c }, { CCI_REG8(0x3a35), 0x09 }, ++ { CCI_REG8(0x3a36), 0x07 }, { CCI_REG8(0x3a37), 0x04 }, ++ { CCI_REG8(0x3a43), 0x0c }, { CCI_REG8(0x3a44), 0x09 }, ++ { CCI_REG8(0x3a45), 0x06 }, { CCI_REG8(0x3a46), 0x02 }, ++ { CCI_REG8(0x3a48), 0x0c }, { CCI_REG8(0x3a49), 0x09 }, ++ { CCI_REG8(0x3a4a), 0x07 }, { CCI_REG8(0x3a4b), 0x04 }, ++ { CCI_REG8(0xc487), 0x0c }, { CCI_REG8(0xc488), 0x0c }, ++ { CCI_REG8(0xc489), 0x0c }, { CCI_REG8(0xc48a), 0x0c }, ++ { CCI_REG8(0x3645), 0xbd }, { CCI_REG8(0x373f), 0x00 }, ++ { CCI_REG8(0x374f), 0x10 }, { CCI_REG8(0x3743), 0xc6 }, ++ { CCI_REG8(0x3717), 0x82 }, { CCI_REG8(0x3732), 0x07 }, ++ { CCI_REG8(0x3731), 0x16 }, { CCI_REG8(0x3730), 0x16 }, ++ { CCI_REG8(0x3828), 0x07 }, { CCI_REG8(0x3714), 0x68 }, ++ { CCI_REG8(0x371d), 0x02 }, { CCI_REG8(0x371f), 0x02 }, ++ { CCI_REG8(0x37e0), 0x00 }, { CCI_REG8(0x37e1), 0x03 }, ++ { CCI_REG8(0x37e2), 0x07 }, { CCI_REG8(0x3734), 0x3e }, ++ { CCI_REG8(0x3736), 0x02 }, { CCI_REG8(0x37e4), 0x36 }, ++ { CCI_REG8(0x37e9), 0x1c }, { CCI_REG8(0x37ea), 0x01 }, ++ { CCI_REG8(0x37eb), 0x0a }, { CCI_REG8(0x37ec), 0x1c }, ++ { CCI_REG8(0x37ed), 0x01 }, { CCI_REG8(0x37ee), 0x36 }, ++ { CCI_REG8(0x373b), 0x1c }, { CCI_REG8(0x373c), 0x02 }, ++ { CCI_REG8(0x37bb), 0x1c }, { CCI_REG8(0x37bc), 0x02 }, ++ { CCI_REG8(0x37b8), 0x0c }, { CCI_REG8(0x371c), 0x01 }, ++ { CCI_REG8(0x371e), 0x11 }, { CCI_REG8(0x371d), 0x01 }, ++ { CCI_REG8(0x371f), 0x01 }, { CCI_REG8(0x3721), 0x01 }, ++ { CCI_REG8(0x3725), 0x12 }, { CCI_REG8(0x37e3), 0x06 }, ++ { CCI_REG8(0x37dd), 0x86 }, { CCI_REG8(0x37db), 0x0a }, ++ { CCI_REG8(0x37dc), 0x14 }, { CCI_REG8(0x3727), 0x20 }, ++ { CCI_REG8(0x37b2), 0x80 }, { CCI_REG8(0x37da), 0x04 }, ++ { CCI_REG8(0x37df), 0x01 }, { CCI_REG8(0x3731), 0x11 }, ++ { CCI_REG8(0x37dd), 0x86 }, { CCI_REG8(0x37df), 0x01 }, ++ { CCI_REG8(0x37da), 0x03 }, { CCI_REG8(0x37b2), 0x80 }, ++ { CCI_REG8(0x3727), 0x20 }, { CCI_REG8(0x4883), 0x26 }, ++ { CCI_REG8(0x488b), 0x88 }, { CCI_REG8(0x3d85), 0x1f }, ++ { CCI_REG8(0x3d81), 0x01 }, { CCI_REG8(0x3d84), 0x40 }, ++ { CCI_REG8(0x3d88), 0x00 }, { CCI_REG8(0x3d89), 0x00 }, ++ { CCI_REG8(0x3d8a), 0x0b }, { CCI_REG8(0x3d8b), 0xff }, ++ { CCI_REG8(0x4d00), 0x05 }, { CCI_REG8(0x4d01), 0xc4 }, ++ { CCI_REG8(0x4d02), 0xa3 }, { CCI_REG8(0x4d03), 0x8c }, ++ { CCI_REG8(0x4d04), 0xfb }, { CCI_REG8(0x4d05), 0xed }, ++ { CCI_REG8(0x4010), 0x28 }, { CCI_REG8(0x4030), 0x00 }, ++ { CCI_REG8(0x4031), 0x00 }, { CCI_REG8(0x4032), 0x00 }, ++ { CCI_REG8(0x4033), 0x00 }, { CCI_REG8(0x4034), 0x00 }, ++ { CCI_REG8(0x4035), 0x00 }, { CCI_REG8(0x4036), 0x00 }, ++ { CCI_REG8(0x4037), 0x00 }, { CCI_REG8(0x4040), 0x00 }, ++ { CCI_REG8(0x4041), 0x00 }, { CCI_REG8(0x4042), 0x00 }, ++ { CCI_REG8(0x4043), 0x00 }, { CCI_REG8(0x4044), 0x00 }, ++ { CCI_REG8(0x4045), 0x00 }, { CCI_REG8(0x4046), 0x00 }, ++ { CCI_REG8(0x4047), 0x00 }, { CCI_REG8(0x3400), 0x00 }, ++ { CCI_REG8(0x3421), 0x23 }, { CCI_REG8(0x3422), 0xfc }, ++ { CCI_REG8(0x3423), 0x07 }, { CCI_REG8(0x3424), 0x01 }, ++ { CCI_REG8(0x3425), 0x04 }, { CCI_REG8(0x3426), 0x50 }, ++ { CCI_REG8(0x3427), 0x55 }, { CCI_REG8(0x3428), 0x15 }, ++ { CCI_REG8(0x3429), 0x00 }, { CCI_REG8(0x3025), 0x03 }, ++ { CCI_REG8(0x3053), 0x00 }, { CCI_REG8(0x3054), 0x00 }, ++ { CCI_REG8(0x3055), 0x00 }, { CCI_REG8(0x3056), 0x00 }, ++ { CCI_REG8(0x3057), 0x00 }, { CCI_REG8(0x3058), 0x00 }, ++ { CCI_REG8(0x305c), 0x00 }, { CCI_REG8(0x340c), 0x1f }, ++ { CCI_REG8(0x340d), 0x00 }, { CCI_REG8(0x3501), 0x01 }, ++ { CCI_REG8(0x3542), 0x48 }, { CCI_REG8(0x3582), 0x24 }, ++ { CCI_REG8(0x3015), 0xf1 }, { CCI_REG8(0x3018), 0xf2 }, ++ { CCI_REG8(0x301c), 0xf2 }, { CCI_REG8(0x301d), 0xf6 }, ++ { CCI_REG8(0x301e), 0xf1 }, { CCI_REG8(0x0100), 0x01 }, ++ { CCI_REG8(0xfff9), 0x08 }, { CCI_REG8(0x3900), 0xcd }, ++ { CCI_REG8(0x3901), 0xcd }, { CCI_REG8(0x3902), 0xcd }, ++ { CCI_REG8(0x3903), 0xcd }, { CCI_REG8(0x3904), 0xcd }, ++ { CCI_REG8(0x3905), 0xcd }, { CCI_REG8(0x3906), 0xcd }, ++ { CCI_REG8(0x3907), 0xcd }, { CCI_REG8(0x3908), 0xcd }, ++ { CCI_REG8(0x3909), 0xcd }, { CCI_REG8(0x390a), 0xcd }, ++ { CCI_REG8(0x390b), 0xcd }, { CCI_REG8(0x390c), 0xcd }, ++ { CCI_REG8(0x390d), 0xcd }, { CCI_REG8(0x390e), 0xcd }, ++ { CCI_REG8(0x390f), 0xcd }, { CCI_REG8(0x3910), 0xcd }, ++ { CCI_REG8(0x3911), 0xcd }, { CCI_REG8(0x3912), 0xcd }, ++ { CCI_REG8(0x3913), 0xcd }, { CCI_REG8(0x3914), 0xcd }, ++ { CCI_REG8(0x3915), 0xcd }, { CCI_REG8(0x3916), 0xcd }, ++ { CCI_REG8(0x3917), 0xcd }, { CCI_REG8(0x3918), 0xcd }, ++ { CCI_REG8(0x3919), 0xcd }, { CCI_REG8(0x391a), 0xcd }, ++ { CCI_REG8(0x391b), 0xcd }, { CCI_REG8(0x391c), 0xcd }, ++ { CCI_REG8(0x391d), 0xcd }, { CCI_REG8(0x391e), 0xcd }, ++ { CCI_REG8(0x391f), 0xcd }, { CCI_REG8(0x3920), 0xcd }, ++ { CCI_REG8(0x3921), 0xcd }, { CCI_REG8(0x3922), 0xcd }, ++ { CCI_REG8(0x3923), 0xcd }, { CCI_REG8(0x3924), 0xcd }, ++ { CCI_REG8(0x3925), 0xcd }, { CCI_REG8(0x3926), 0xcd }, ++ { CCI_REG8(0x3927), 0xcd }, { CCI_REG8(0x3928), 0xcd }, ++ { CCI_REG8(0x3929), 0xcd }, { CCI_REG8(0x392a), 0xcd }, ++ { CCI_REG8(0x392b), 0xcd }, { CCI_REG8(0x392c), 0xcd }, ++ { CCI_REG8(0x392d), 0xcd }, { CCI_REG8(0x392e), 0xcd }, ++ { CCI_REG8(0x392f), 0xcd }, { CCI_REG8(0x3930), 0xcd }, ++ { CCI_REG8(0x3931), 0xcd }, { CCI_REG8(0x3932), 0xcd }, ++ { CCI_REG8(0x3933), 0xcd }, { CCI_REG8(0x3934), 0xcd }, ++ { CCI_REG8(0x3935), 0xcd }, { CCI_REG8(0x3936), 0xcd }, ++ { CCI_REG8(0x3937), 0xcd }, { CCI_REG8(0x3938), 0xcd }, ++ { CCI_REG8(0x3939), 0xcd }, { CCI_REG8(0x393a), 0xcd }, ++ { CCI_REG8(0x393b), 0xcd }, { CCI_REG8(0x393c), 0xcd }, ++ { CCI_REG8(0x393d), 0xcd }, { CCI_REG8(0x393e), 0xcd }, ++ { CCI_REG8(0x393f), 0xcd }, { CCI_REG8(0x3940), 0xcd }, ++ { CCI_REG8(0x3941), 0xcd }, { CCI_REG8(0x3942), 0xcd }, ++ { CCI_REG8(0x3943), 0xcd }, { CCI_REG8(0x3944), 0xcd }, ++ { CCI_REG8(0x3945), 0xcd }, { CCI_REG8(0x3946), 0xcd }, ++ { CCI_REG8(0x3947), 0xcd }, { CCI_REG8(0x3948), 0xcd }, ++ { CCI_REG8(0x3949), 0xcd }, { CCI_REG8(0x394a), 0xcd }, ++ { CCI_REG8(0x394b), 0xcd }, { CCI_REG8(0x394c), 0xcd }, ++ { CCI_REG8(0x394d), 0xcd }, { CCI_REG8(0x394e), 0xcd }, ++ { CCI_REG8(0x394f), 0xcd }, { CCI_REG8(0x3950), 0xcd }, ++ { CCI_REG8(0x3951), 0xcd }, { CCI_REG8(0x3952), 0xcd }, ++ { CCI_REG8(0x3953), 0xcd }, { CCI_REG8(0x3954), 0xcd }, ++ { CCI_REG8(0x3955), 0xcd }, { CCI_REG8(0x3956), 0xcd }, ++ { CCI_REG8(0x3957), 0xcd }, { CCI_REG8(0x3958), 0xcd }, ++ { CCI_REG8(0x3959), 0xcd }, { CCI_REG8(0x395a), 0xcd }, ++ { CCI_REG8(0x395b), 0xcd }, { CCI_REG8(0x395c), 0xcd }, ++ { CCI_REG8(0x395d), 0xcd }, { CCI_REG8(0x395e), 0xcd }, ++ { CCI_REG8(0x395f), 0xcd }, { CCI_REG8(0x3960), 0xcd }, ++ { CCI_REG8(0x3961), 0xcd }, { CCI_REG8(0x3962), 0xcd }, ++ { CCI_REG8(0x3963), 0xcd }, { CCI_REG8(0x3964), 0xcd }, ++ { CCI_REG8(0x3965), 0xcd }, { CCI_REG8(0x3966), 0xcd }, ++ { CCI_REG8(0x3967), 0xcd }, { CCI_REG8(0x3968), 0xcd }, ++ { CCI_REG8(0x3969), 0xcd }, { CCI_REG8(0x396a), 0xcd }, ++ { CCI_REG8(0x396b), 0xcd }, { CCI_REG8(0x396c), 0xcd }, ++ { CCI_REG8(0x396d), 0xcd }, { CCI_REG8(0x396e), 0xcd }, ++ { CCI_REG8(0x396f), 0xcd }, { CCI_REG8(0x3970), 0xcd }, ++ { CCI_REG8(0x3971), 0xcd }, { CCI_REG8(0x3972), 0xcd }, ++ { CCI_REG8(0x3973), 0xcd }, { CCI_REG8(0x3974), 0xcd }, ++ { CCI_REG8(0x3975), 0xcd }, { CCI_REG8(0x3976), 0xcd }, ++ { CCI_REG8(0x3977), 0xcd }, { CCI_REG8(0x3978), 0xcd }, ++ { CCI_REG8(0x3979), 0xcd }, { CCI_REG8(0x397a), 0xcd }, ++ { CCI_REG8(0x397b), 0xcd }, { CCI_REG8(0x397c), 0xcd }, ++ { CCI_REG8(0x397d), 0xcd }, { CCI_REG8(0x397e), 0xcd }, ++ { CCI_REG8(0x397f), 0xcd }, { CCI_REG8(0x3980), 0xcd }, ++ { CCI_REG8(0x3981), 0xcd }, { CCI_REG8(0x3982), 0xcd }, ++ { CCI_REG8(0x3983), 0xcd }, { CCI_REG8(0x3984), 0xcd }, ++ { CCI_REG8(0x3985), 0xcd }, { CCI_REG8(0x3986), 0xcd }, ++ { CCI_REG8(0x3987), 0xcd }, { CCI_REG8(0x3988), 0xcd }, ++ { CCI_REG8(0x3989), 0xcd }, { CCI_REG8(0x398a), 0xcd }, ++ { CCI_REG8(0x398b), 0xcd }, { CCI_REG8(0x398c), 0xcd }, ++ { CCI_REG8(0x398d), 0xcd }, { CCI_REG8(0x398e), 0xcd }, ++ { CCI_REG8(0x398f), 0xcd }, { CCI_REG8(0x3990), 0xcd }, ++ { CCI_REG8(0x3991), 0xcd }, { CCI_REG8(0x3992), 0xcd }, ++ { CCI_REG8(0x3993), 0xcd }, { CCI_REG8(0x3994), 0xcd }, ++ { CCI_REG8(0x3995), 0xcd }, { CCI_REG8(0x3996), 0xcd }, ++ { CCI_REG8(0x3997), 0xcd }, { CCI_REG8(0x3998), 0xcd }, ++ { CCI_REG8(0x3999), 0xcd }, { CCI_REG8(0x399a), 0xcd }, ++ { CCI_REG8(0x399b), 0xcd }, { CCI_REG8(0x399c), 0xcd }, ++ { CCI_REG8(0x399d), 0xcd }, { CCI_REG8(0x399e), 0xcd }, ++ { CCI_REG8(0x399f), 0xcd }, { CCI_REG8(0x39a0), 0xcd }, ++ { CCI_REG8(0x39a1), 0xcd }, { CCI_REG8(0x39a2), 0xcd }, ++ { CCI_REG8(0x39a3), 0xcd }, { CCI_REG8(0x39a4), 0xcd }, ++ { CCI_REG8(0x39a5), 0xcd }, { CCI_REG8(0x39a6), 0xcd }, ++ { CCI_REG8(0x39a7), 0xcd }, { CCI_REG8(0x39a8), 0xcd }, ++ { CCI_REG8(0x39a9), 0xcd }, { CCI_REG8(0x39aa), 0xcd }, ++ { CCI_REG8(0x39ab), 0xcd }, { CCI_REG8(0x39ac), 0xcd }, ++ { CCI_REG8(0x39ad), 0xcd }, { CCI_REG8(0x39ae), 0xcd }, ++ { CCI_REG8(0x39af), 0xcd }, { CCI_REG8(0x39b0), 0xcd }, ++ { CCI_REG8(0x39b1), 0xcd }, { CCI_REG8(0x39b2), 0xcd }, ++ { CCI_REG8(0x39b3), 0xcd }, { CCI_REG8(0x39b4), 0xcd }, ++ { CCI_REG8(0x39b5), 0xcd }, { CCI_REG8(0x39b6), 0xcd }, ++ { CCI_REG8(0x39b7), 0xcd }, { CCI_REG8(0x39b8), 0xcd }, ++ { CCI_REG8(0x39b9), 0xcd }, { CCI_REG8(0x39ba), 0xcd }, ++ { CCI_REG8(0x39bb), 0xcd }, { CCI_REG8(0x39bc), 0xcd }, ++ { CCI_REG8(0x39bd), 0xcd }, { CCI_REG8(0x39be), 0xcd }, ++ { CCI_REG8(0x39bf), 0xcd }, { CCI_REG8(0x39c0), 0xcd }, ++ { CCI_REG8(0x39c1), 0xcd }, { CCI_REG8(0x39c2), 0xcd }, ++ { CCI_REG8(0x39c3), 0xcd }, { CCI_REG8(0x39c4), 0xcd }, ++ { CCI_REG8(0x39c5), 0xcd }, { CCI_REG8(0x39c6), 0xcd }, ++ { CCI_REG8(0x39c7), 0xcd }, { CCI_REG8(0x39c8), 0xcd }, ++ { CCI_REG8(0x39c9), 0xcd }, { CCI_REG8(0x39ca), 0xcd }, ++ { CCI_REG8(0x39cb), 0xcd }, { CCI_REG8(0x39cc), 0xcd }, ++ { CCI_REG8(0x39cd), 0xcd }, { CCI_REG8(0x39ce), 0xcd }, ++ { CCI_REG8(0x39cf), 0xcd }, { CCI_REG8(0x39d0), 0xcd }, ++ { CCI_REG8(0x39d1), 0xcd }, { CCI_REG8(0x39d2), 0xcd }, ++ { CCI_REG8(0x39d3), 0xcd }, { CCI_REG8(0x39d4), 0xcd }, ++ { CCI_REG8(0x39d5), 0xcd }, { CCI_REG8(0x39d6), 0xcd }, ++ { CCI_REG8(0x39d7), 0xcd }, { CCI_REG8(0x39d8), 0xcd }, ++ { CCI_REG8(0x39d9), 0xcd }, { CCI_REG8(0x39da), 0xcd }, ++ { CCI_REG8(0x39db), 0xcd }, { CCI_REG8(0x39dc), 0xcd }, ++ { CCI_REG8(0x39dd), 0xcd }, { CCI_REG8(0x39de), 0xcd }, ++ { CCI_REG8(0x39df), 0xcd }, { CCI_REG8(0x39e0), 0xcd }, ++ { CCI_REG8(0x39e1), 0x40 }, { CCI_REG8(0x39e2), 0x40 }, ++ { CCI_REG8(0x39e3), 0x40 }, { CCI_REG8(0x39e4), 0x40 }, ++ { CCI_REG8(0x39e5), 0x40 }, { CCI_REG8(0x39e6), 0x40 }, ++ { CCI_REG8(0x39e7), 0x40 }, { CCI_REG8(0x39e8), 0x40 }, ++ { CCI_REG8(0x39e9), 0x40 }, { CCI_REG8(0x39ea), 0x40 }, ++ { CCI_REG8(0x39eb), 0x40 }, { CCI_REG8(0x39ec), 0x40 }, ++ { CCI_REG8(0x39ed), 0x40 }, { CCI_REG8(0x39ee), 0x40 }, ++ { CCI_REG8(0x39ef), 0x40 }, { CCI_REG8(0x39f0), 0x40 }, ++ { CCI_REG8(0x39f1), 0x40 }, { CCI_REG8(0x39f2), 0x40 }, ++ { CCI_REG8(0x39f3), 0x40 }, { CCI_REG8(0x39f4), 0x40 }, ++ { CCI_REG8(0x39f5), 0x40 }, { CCI_REG8(0x39f6), 0x40 }, ++ { CCI_REG8(0x39f7), 0x40 }, { CCI_REG8(0x39f8), 0x40 }, ++ { CCI_REG8(0x39f9), 0x40 }, { CCI_REG8(0x39fa), 0x40 }, ++ { CCI_REG8(0x39fb), 0x40 }, { CCI_REG8(0x39fc), 0x40 }, ++ { CCI_REG8(0x39fd), 0x40 }, { CCI_REG8(0x39fe), 0x40 }, ++ { CCI_REG8(0x39ff), 0x40 }, { CCI_REG8(0x3a00), 0x40 }, ++ { CCI_REG8(0x3a01), 0x40 }, { CCI_REG8(0x3a02), 0x40 }, ++ { CCI_REG8(0x3a03), 0x40 }, { CCI_REG8(0x3a04), 0x40 }, ++ { CCI_REG8(0x3a05), 0x40 }, { CCI_REG8(0x3a06), 0x40 }, ++ { CCI_REG8(0x3a07), 0x40 }, { CCI_REG8(0x3a08), 0x40 }, ++ { CCI_REG8(0x3a09), 0x40 }, { CCI_REG8(0x3a0a), 0x40 }, ++ { CCI_REG8(0x3a0b), 0x40 }, { CCI_REG8(0x3a0c), 0x40 }, ++ { CCI_REG8(0x3a0d), 0x40 }, { CCI_REG8(0x3a0e), 0x40 }, ++ { CCI_REG8(0x3a0f), 0x40 }, { CCI_REG8(0x3a10), 0x40 }, ++ { CCI_REG8(0x3a11), 0x40 }, { CCI_REG8(0x3a12), 0x40 }, ++ { CCI_REG8(0x3a13), 0x40 }, { CCI_REG8(0x3a14), 0x40 }, ++ { CCI_REG8(0x3a15), 0x40 }, { CCI_REG8(0x3a16), 0x40 }, ++ { CCI_REG8(0x3a17), 0x40 }, { CCI_REG8(0x3a18), 0x40 }, ++ { CCI_REG8(0x3a19), 0x40 }, { CCI_REG8(0x3a1a), 0x40 }, ++ { CCI_REG8(0x3a1b), 0x40 }, { CCI_REG8(0x3a1c), 0x40 }, ++ { CCI_REG8(0x3a1d), 0x40 }, { CCI_REG8(0x3a1e), 0x40 }, ++ { CCI_REG8(0x3a1f), 0x40 }, { CCI_REG8(0x3a20), 0x40 }, ++ { CCI_REG8(0x3a21), 0x40 }, { CCI_REG8(0x3a22), 0x40 }, ++ { CCI_REG8(0x3a23), 0x40 }, { CCI_REG8(0x3a24), 0x40 }, ++ { CCI_REG8(0x3a25), 0x40 }, { CCI_REG8(0x3a26), 0x40 }, ++ { CCI_REG8(0x3a27), 0x40 }, { CCI_REG8(0x3a28), 0x40 }, ++ { CCI_REG8(0x3a29), 0x40 }, { CCI_REG8(0x3a2a), 0x40 }, ++ { CCI_REG8(0x3a2b), 0x40 }, { CCI_REG8(0x3a2c), 0x40 }, ++ { CCI_REG8(0x3a2d), 0x40 }, { CCI_REG8(0x3a2e), 0x40 }, ++ { CCI_REG8(0x3a2f), 0x40 }, { CCI_REG8(0x3a30), 0x40 }, ++ { CCI_REG8(0x3a31), 0x40 }, { CCI_REG8(0x3a32), 0x40 }, ++ { CCI_REG8(0x3a33), 0x40 }, { CCI_REG8(0x3a34), 0x40 }, ++ { CCI_REG8(0x3a35), 0x40 }, { CCI_REG8(0x3a36), 0x40 }, ++ { CCI_REG8(0x3a37), 0x40 }, { CCI_REG8(0x3a38), 0x40 }, ++ { CCI_REG8(0x3a39), 0x40 }, { CCI_REG8(0x3a3a), 0x40 }, ++ { CCI_REG8(0x3a3b), 0xcd }, { CCI_REG8(0x3a3c), 0xcd }, ++ { CCI_REG8(0x3a3d), 0xcd }, { CCI_REG8(0x3a3e), 0xcd }, ++ { CCI_REG8(0x3a3f), 0xcd }, { CCI_REG8(0x3a40), 0xcd }, ++ { CCI_REG8(0x3a41), 0xcd }, { CCI_REG8(0x3a42), 0xcd }, ++ { CCI_REG8(0x3a43), 0xcd }, { CCI_REG8(0x3a44), 0xcd }, ++ { CCI_REG8(0x3a45), 0xcd }, { CCI_REG8(0x3a46), 0xcd }, ++ { CCI_REG8(0x3a47), 0xcd }, { CCI_REG8(0x3a48), 0xcd }, ++ { CCI_REG8(0x3a49), 0xcd }, { CCI_REG8(0x3a4a), 0xcd }, ++ { CCI_REG8(0x3a4b), 0xcd }, { CCI_REG8(0x3a4c), 0xcd }, ++ { CCI_REG8(0x3a4d), 0xcd }, { CCI_REG8(0x3a4e), 0xcd }, ++ { CCI_REG8(0x3a4f), 0xcd }, { CCI_REG8(0x3a50), 0xcd }, ++ { CCI_REG8(0x3a51), 0xcd }, { CCI_REG8(0x3a52), 0xcd }, ++ { CCI_REG8(0x3a53), 0xcd }, { CCI_REG8(0x3a54), 0xcd }, ++ { CCI_REG8(0x3a55), 0xcd }, { CCI_REG8(0x3a56), 0xcd }, ++ { CCI_REG8(0x3a57), 0xcd }, { CCI_REG8(0x3a58), 0xcd }, ++ { CCI_REG8(0x3a59), 0xcd }, { CCI_REG8(0x3a5a), 0xcd }, ++ { CCI_REG8(0x3a5b), 0xcd }, { CCI_REG8(0x3a5c), 0xcd }, ++ { CCI_REG8(0x3a5d), 0xcd }, { CCI_REG8(0x3a5e), 0xcd }, ++ { CCI_REG8(0x3a5f), 0xcd }, { CCI_REG8(0x3a60), 0xcd }, ++ { CCI_REG8(0x3a61), 0xcd }, { CCI_REG8(0x3a62), 0xcd }, ++ { CCI_REG8(0x3a63), 0xcd }, { CCI_REG8(0x3a64), 0xcd }, ++ { CCI_REG8(0x3a65), 0xcd }, { CCI_REG8(0x3a66), 0xcd }, ++ { CCI_REG8(0x3a67), 0xcd }, { CCI_REG8(0x3a68), 0xcd }, ++ { CCI_REG8(0x3a69), 0xcd }, { CCI_REG8(0x3a6a), 0xcd }, ++ { CCI_REG8(0x3a6b), 0xcd }, { CCI_REG8(0x3a6c), 0xcd }, ++ { CCI_REG8(0x3a6d), 0xcd }, { CCI_REG8(0x3a6e), 0xcd }, ++ { CCI_REG8(0x3a6f), 0xcd }, { CCI_REG8(0x3a70), 0xcd }, ++ { CCI_REG8(0x3a71), 0xcd }, { CCI_REG8(0x3a72), 0xcd }, ++ { CCI_REG8(0x3a73), 0xcd }, { CCI_REG8(0x3a74), 0xcd }, ++ { CCI_REG8(0x3a75), 0xcd }, { CCI_REG8(0x3a76), 0xcd }, ++ { CCI_REG8(0x3a77), 0xcd }, { CCI_REG8(0x3a78), 0xcd }, ++ { CCI_REG8(0x3a79), 0xcd }, { CCI_REG8(0x3a7a), 0xcd }, ++ { CCI_REG8(0x3a7b), 0xcd }, { CCI_REG8(0x3a7c), 0xcd }, ++ { CCI_REG8(0x3a7d), 0xcd }, { CCI_REG8(0x3a7e), 0xcd }, ++ { CCI_REG8(0x3a7f), 0xcd }, { CCI_REG8(0x3a80), 0xcd }, ++ { CCI_REG8(0x3a81), 0xcd }, { CCI_REG8(0x3a82), 0xcd }, ++ { CCI_REG8(0x3a83), 0xcd }, { CCI_REG8(0x3a84), 0xcd }, ++ { CCI_REG8(0x3a85), 0xcd }, { CCI_REG8(0x3a86), 0xcd }, ++ { CCI_REG8(0x3a87), 0xcd }, { CCI_REG8(0x3a88), 0xcd }, ++ { CCI_REG8(0x3a89), 0xcd }, { CCI_REG8(0x3a8a), 0xcd }, ++ { CCI_REG8(0x3a8b), 0xcd }, { CCI_REG8(0x3a8c), 0xcd }, ++ { CCI_REG8(0x3a8d), 0xcd }, { CCI_REG8(0x3a8e), 0xcd }, ++ { CCI_REG8(0x3a8f), 0xcd }, { CCI_REG8(0x3a90), 0xcd }, ++ { CCI_REG8(0x3a91), 0xcd }, { CCI_REG8(0x3a92), 0xcd }, ++ { CCI_REG8(0x3a93), 0xcd }, { CCI_REG8(0x3a94), 0xcd }, ++ { CCI_REG8(0x3a95), 0x40 }, { CCI_REG8(0x3a96), 0x40 }, ++ { CCI_REG8(0x3a97), 0x40 }, { CCI_REG8(0x3a98), 0x40 }, ++ { CCI_REG8(0x3a99), 0x40 }, { CCI_REG8(0x3a9a), 0x40 }, ++ { CCI_REG8(0x3a9b), 0x40 }, { CCI_REG8(0x3a9c), 0x40 }, ++ { CCI_REG8(0x3a9d), 0x40 }, { CCI_REG8(0x3a9e), 0x40 }, ++ { CCI_REG8(0x3a9f), 0x40 }, { CCI_REG8(0x3aa0), 0x40 }, ++ { CCI_REG8(0x3aa1), 0x40 }, { CCI_REG8(0x3aa2), 0x40 }, ++ { CCI_REG8(0x3aa3), 0x40 }, { CCI_REG8(0x3aa4), 0x40 }, ++ { CCI_REG8(0x3aa5), 0x40 }, { CCI_REG8(0x3aa6), 0x40 }, ++ { CCI_REG8(0x3aa7), 0x40 }, { CCI_REG8(0x3aa8), 0x40 }, ++ { CCI_REG8(0x3aa9), 0x40 }, { CCI_REG8(0x3aaa), 0x40 }, ++ { CCI_REG8(0x3aab), 0x40 }, { CCI_REG8(0x3aac), 0x40 }, ++ { CCI_REG8(0x3aad), 0x40 }, { CCI_REG8(0x3aae), 0x40 }, ++ { CCI_REG8(0x3aaf), 0x40 }, { CCI_REG8(0x3ab0), 0x40 }, ++ { CCI_REG8(0x3ab1), 0x40 }, { CCI_REG8(0x3ab2), 0x40 }, ++ { CCI_REG8(0x3ab3), 0x40 }, { CCI_REG8(0x3ab4), 0x40 }, ++ { CCI_REG8(0x3ab5), 0x40 }, { CCI_REG8(0x3ab6), 0x40 }, ++ { CCI_REG8(0x3ab7), 0x40 }, { CCI_REG8(0x3ab8), 0x40 }, ++ { CCI_REG8(0x3ab9), 0x40 }, { CCI_REG8(0x3aba), 0x40 }, ++ { CCI_REG8(0x3abb), 0x40 }, { CCI_REG8(0x3abc), 0x40 }, ++ { CCI_REG8(0x3abd), 0x40 }, { CCI_REG8(0x3abe), 0x40 }, ++ { CCI_REG8(0x3abf), 0x40 }, { CCI_REG8(0x3ac0), 0x40 }, ++ { CCI_REG8(0x3ac1), 0x40 }, { CCI_REG8(0x3ac2), 0x40 }, ++ { CCI_REG8(0x3ac3), 0x40 }, { CCI_REG8(0x3ac4), 0x40 }, ++ { CCI_REG8(0x3ac5), 0x40 }, { CCI_REG8(0x3ac6), 0x40 }, ++ { CCI_REG8(0x3ac7), 0x40 }, { CCI_REG8(0x3ac8), 0x40 }, ++ { CCI_REG8(0x3ac9), 0x40 }, { CCI_REG8(0x3aca), 0x40 }, ++ { CCI_REG8(0x3acb), 0x40 }, { CCI_REG8(0x3acc), 0x40 }, ++ { CCI_REG8(0x3acd), 0x40 }, { CCI_REG8(0x3ace), 0x40 }, ++ { CCI_REG8(0x3acf), 0x40 }, { CCI_REG8(0x3ad0), 0x40 }, ++ { CCI_REG8(0x3ad1), 0x40 }, { CCI_REG8(0x3ad2), 0x40 }, ++ { CCI_REG8(0x3ad3), 0x40 }, { CCI_REG8(0x3ad4), 0x40 }, ++ { CCI_REG8(0x3ad5), 0x40 }, { CCI_REG8(0x3ad6), 0x40 }, ++ { CCI_REG8(0x3ad7), 0x40 }, { CCI_REG8(0x3ad8), 0x40 }, ++ { CCI_REG8(0x3ad9), 0x40 }, { CCI_REG8(0x3ada), 0x40 }, ++ { CCI_REG8(0x3adb), 0x40 }, { CCI_REG8(0x3adc), 0x40 }, ++ { CCI_REG8(0x3add), 0x40 }, { CCI_REG8(0x3ade), 0x40 }, ++ { CCI_REG8(0x3adf), 0x40 }, { CCI_REG8(0x3ae0), 0x40 }, ++ { CCI_REG8(0x3ae1), 0x40 }, { CCI_REG8(0x3ae2), 0x40 }, ++ { CCI_REG8(0x3ae3), 0x40 }, { CCI_REG8(0x3ae4), 0x40 }, ++ { CCI_REG8(0x3ae5), 0x40 }, { CCI_REG8(0x3ae6), 0x40 }, ++ { CCI_REG8(0x3ae7), 0x40 }, { CCI_REG8(0x3ae8), 0x40 }, ++ { CCI_REG8(0x3ae9), 0x40 }, { CCI_REG8(0x3aea), 0x40 }, ++ { CCI_REG8(0x3aeb), 0x40 }, { CCI_REG8(0x3aec), 0x40 }, ++ { CCI_REG8(0x3aed), 0x40 }, { CCI_REG8(0x3aee), 0x40 }, ++ { CCI_REG8(0x3aef), 0xcd }, { CCI_REG8(0x3af0), 0xcd }, ++ { CCI_REG8(0x3af1), 0xcd }, { CCI_REG8(0x3af2), 0xcd }, ++ { CCI_REG8(0x3af3), 0xcd }, { CCI_REG8(0x3af4), 0xcd }, ++ { CCI_REG8(0x3af5), 0xcd }, { CCI_REG8(0x3af6), 0xcd }, ++ { CCI_REG8(0x3af7), 0xcd }, { CCI_REG8(0x3af8), 0xcd }, ++ { CCI_REG8(0x3af9), 0xcd }, { CCI_REG8(0x3afa), 0xcd }, ++ { CCI_REG8(0x3afb), 0xcd }, { CCI_REG8(0x3afc), 0xcd }, ++ { CCI_REG8(0x3afd), 0xcd }, { CCI_REG8(0x3afe), 0xcd }, ++ { CCI_REG8(0x3aff), 0xcd }, { CCI_REG8(0x3b00), 0xcd }, ++ { CCI_REG8(0x3b01), 0xcd }, { CCI_REG8(0x3b02), 0xcd }, ++ { CCI_REG8(0x3b03), 0xcd }, { CCI_REG8(0x3b04), 0xcd }, ++ { CCI_REG8(0x3b05), 0xcd }, { CCI_REG8(0x3b06), 0xcd }, ++ { CCI_REG8(0x3b07), 0xcd }, { CCI_REG8(0x3b08), 0xcd }, ++ { CCI_REG8(0x3b09), 0xcd }, { CCI_REG8(0x3b0a), 0xcd }, ++ { CCI_REG8(0x3b0b), 0xcd }, { CCI_REG8(0x3b0c), 0xcd }, ++ { CCI_REG8(0x3b0d), 0xcd }, { CCI_REG8(0x3b0e), 0xcd }, ++ { CCI_REG8(0x3b0f), 0xcd }, { CCI_REG8(0x3b10), 0xcd }, ++ { CCI_REG8(0x3b11), 0xcd }, { CCI_REG8(0x3b12), 0xcd }, ++ { CCI_REG8(0x3b13), 0xcd }, { CCI_REG8(0x3b14), 0xcd }, ++ { CCI_REG8(0x3b15), 0xcd }, { CCI_REG8(0x3b16), 0xcd }, ++ { CCI_REG8(0x3b17), 0xcd }, { CCI_REG8(0x3b18), 0xcd }, ++ { CCI_REG8(0x3b19), 0xcd }, { CCI_REG8(0x3b1a), 0xcd }, ++ { CCI_REG8(0x3b1b), 0xcd }, { CCI_REG8(0x3b1c), 0xcd }, ++ { CCI_REG8(0x3b1d), 0xcd }, { CCI_REG8(0x3b1e), 0xcd }, ++ { CCI_REG8(0x3b1f), 0xcd }, { CCI_REG8(0x3b20), 0xcd }, ++ { CCI_REG8(0x3b21), 0xcd }, { CCI_REG8(0x3b22), 0xcd }, ++ { CCI_REG8(0x3b23), 0xcd }, { CCI_REG8(0x3b24), 0xcd }, ++ { CCI_REG8(0x3b25), 0xcd }, { CCI_REG8(0x3b26), 0xcd }, ++ { CCI_REG8(0x3b27), 0xcd }, { CCI_REG8(0x3b28), 0xcd }, ++ { CCI_REG8(0x3b29), 0xcd }, { CCI_REG8(0x3b2a), 0xcd }, ++ { CCI_REG8(0x3b2b), 0xcd }, { CCI_REG8(0x3b2c), 0xcd }, ++ { CCI_REG8(0x3b2d), 0xcd }, { CCI_REG8(0x3b2e), 0xcd }, ++ { CCI_REG8(0x3b2f), 0xcd }, { CCI_REG8(0x3b30), 0xcd }, ++ { CCI_REG8(0x3b31), 0xcd }, { CCI_REG8(0x3b32), 0xcd }, ++ { CCI_REG8(0x3b33), 0xcd }, { CCI_REG8(0x3b34), 0xcd }, ++ { CCI_REG8(0x3b35), 0xcd }, { CCI_REG8(0x3b36), 0xcd }, ++ { CCI_REG8(0x3b37), 0xcd }, { CCI_REG8(0x3b38), 0xcd }, ++ { CCI_REG8(0x3b39), 0xcd }, { CCI_REG8(0x3b3a), 0xcd }, ++ { CCI_REG8(0x3b3b), 0xcd }, { CCI_REG8(0x3b3c), 0xcd }, ++ { CCI_REG8(0x3b3d), 0xcd }, { CCI_REG8(0x3b3e), 0xcd }, ++ { CCI_REG8(0x3b3f), 0xcd }, { CCI_REG8(0x3b40), 0xcd }, ++ { CCI_REG8(0x3b41), 0xcd }, { CCI_REG8(0x3b42), 0xcd }, ++ { CCI_REG8(0x3b43), 0xcd }, { CCI_REG8(0x3b44), 0xcd }, ++ { CCI_REG8(0x3b45), 0xcd }, { CCI_REG8(0x3b46), 0xcd }, ++ { CCI_REG8(0x3b47), 0xcd }, { CCI_REG8(0x3b48), 0xcd }, ++ { CCI_REG8(0x3b49), 0xcd }, { CCI_REG8(0x3b4a), 0xcd }, ++ { CCI_REG8(0x3b4b), 0xcd }, { CCI_REG8(0x3b4c), 0xcd }, ++ { CCI_REG8(0x3b4d), 0xcd }, { CCI_REG8(0x3b4e), 0xcd }, ++ { CCI_REG8(0x3b4f), 0xcd }, { CCI_REG8(0x3b50), 0xcd }, ++ { CCI_REG8(0x3b51), 0xcd }, { CCI_REG8(0x3b52), 0xcd }, ++ { CCI_REG8(0x3b53), 0xcd }, { CCI_REG8(0x3b54), 0xcd }, ++ { CCI_REG8(0x3b55), 0xcd }, { CCI_REG8(0x3b56), 0xcd }, ++ { CCI_REG8(0x3b57), 0xcd }, { CCI_REG8(0x3b58), 0xcd }, ++ { CCI_REG8(0x3b59), 0xcd }, { CCI_REG8(0x3b5a), 0xcd }, ++ { CCI_REG8(0x3b5b), 0xcd }, { CCI_REG8(0x3b5c), 0xcd }, ++ { CCI_REG8(0x3b5d), 0xcd }, { CCI_REG8(0x3b5e), 0xcd }, ++ { CCI_REG8(0x3b5f), 0xcd }, { CCI_REG8(0x3b60), 0xcd }, ++ { CCI_REG8(0x3b61), 0xcd }, { CCI_REG8(0x3b62), 0xcd }, ++ { CCI_REG8(0x3b63), 0xcd }, { CCI_REG8(0x3b64), 0xcd }, ++ { CCI_REG8(0x3b65), 0xcd }, { CCI_REG8(0x3b66), 0xcd }, ++ { CCI_REG8(0x3b67), 0xcd }, { CCI_REG8(0x3b68), 0xcd }, ++ { CCI_REG8(0x3b69), 0xcd }, { CCI_REG8(0x3b6a), 0xcd }, ++ { CCI_REG8(0x3b6b), 0xcd }, { CCI_REG8(0x3b6c), 0xcd }, ++ { CCI_REG8(0x3b6d), 0xcd }, { CCI_REG8(0x3b6e), 0xcd }, ++ { CCI_REG8(0x3b6f), 0xcd }, { CCI_REG8(0x3b70), 0xcd }, ++ { CCI_REG8(0x3b71), 0xcd }, { CCI_REG8(0x3b72), 0xcd }, ++ { CCI_REG8(0x3b73), 0xcd }, { CCI_REG8(0x3b74), 0xcd }, ++ { CCI_REG8(0x3b75), 0xcd }, { CCI_REG8(0x3b76), 0xcd }, ++ { CCI_REG8(0x3b77), 0xcd }, { CCI_REG8(0x3b78), 0xcd }, ++ { CCI_REG8(0x3b79), 0xcd }, { CCI_REG8(0x3b7a), 0xcd }, ++ { CCI_REG8(0x3b7b), 0xcd }, { CCI_REG8(0x3b7c), 0xcd }, ++ { CCI_REG8(0x3b7d), 0xcd }, { CCI_REG8(0x3b7e), 0xcd }, ++ { CCI_REG8(0x3b7f), 0xcd }, { CCI_REG8(0x3b80), 0xcd }, ++ { CCI_REG8(0x3b81), 0xcd }, { CCI_REG8(0x3b82), 0xcd }, ++ { CCI_REG8(0x3b83), 0xcd }, { CCI_REG8(0x3b84), 0xcd }, ++ { CCI_REG8(0x3b85), 0xcd }, { CCI_REG8(0x3b86), 0xcd }, ++ { CCI_REG8(0x3b87), 0xcd }, { CCI_REG8(0x3b88), 0xcd }, ++ { CCI_REG8(0x3b89), 0xcd }, { CCI_REG8(0x3b8a), 0xcd }, ++ { CCI_REG8(0x3b8b), 0xcd }, { CCI_REG8(0x3b8c), 0xcd }, ++ { CCI_REG8(0x3b8d), 0xcd }, { CCI_REG8(0x3b8e), 0xcd }, ++ { CCI_REG8(0x3b8f), 0xcd }, { CCI_REG8(0x3b90), 0xcd }, ++ { CCI_REG8(0x3b91), 0xcd }, { CCI_REG8(0x3b92), 0xcd }, ++ { CCI_REG8(0x3b93), 0xcd }, { CCI_REG8(0x3b94), 0xcd }, ++ { CCI_REG8(0x3b95), 0xcd }, { CCI_REG8(0x3b96), 0xcd }, ++ { CCI_REG8(0x3b97), 0xcd }, { CCI_REG8(0x3b98), 0xcd }, ++ { CCI_REG8(0x3b99), 0xcd }, { CCI_REG8(0x3b9a), 0xcd }, ++ { CCI_REG8(0x3b9b), 0xcd }, { CCI_REG8(0x3b9c), 0xcd }, ++ { CCI_REG8(0x3b9d), 0xcd }, { CCI_REG8(0x3b9e), 0xcd }, ++ { CCI_REG8(0x3b9f), 0xcd }, { CCI_REG8(0x3ba0), 0xcd }, ++ { CCI_REG8(0x3ba1), 0xcd }, { CCI_REG8(0x3ba2), 0xcd }, ++ { CCI_REG8(0x3ba3), 0xcd }, { CCI_REG8(0x3ba4), 0xcd }, ++ { CCI_REG8(0x3ba5), 0xcd }, { CCI_REG8(0x3ba6), 0xcd }, ++ { CCI_REG8(0x3ba7), 0xcd }, { CCI_REG8(0x3ba8), 0xcd }, ++ { CCI_REG8(0x3ba9), 0xcd }, { CCI_REG8(0x3baa), 0xcd }, ++ { CCI_REG8(0x3bab), 0xcd }, { CCI_REG8(0x3bac), 0xcd }, ++ { CCI_REG8(0x3bad), 0xcd }, { CCI_REG8(0x3bae), 0xcd }, ++ { CCI_REG8(0x3baf), 0xcd }, { CCI_REG8(0x3bb0), 0xcd }, ++ { CCI_REG8(0x3bb1), 0xcd }, { CCI_REG8(0x3bb2), 0xcd }, ++ { CCI_REG8(0x3bb3), 0xcd }, { CCI_REG8(0x3bb4), 0xcd }, ++ { CCI_REG8(0x3bb5), 0xcd }, { CCI_REG8(0x3bb6), 0xcd }, ++ { CCI_REG8(0x3bb7), 0xcd }, { CCI_REG8(0x3bb8), 0xcd }, ++ { CCI_REG8(0x3bb9), 0xcd }, { CCI_REG8(0x3bba), 0xcd }, ++ { CCI_REG8(0x3bbb), 0xcd }, { CCI_REG8(0x3bbc), 0xcd }, ++ { CCI_REG8(0x3bbd), 0xcd }, { CCI_REG8(0x3bbe), 0xcd }, ++ { CCI_REG8(0x3bbf), 0xcd }, { CCI_REG8(0x3bc0), 0xcd }, ++ { CCI_REG8(0x3bc1), 0xcd }, { CCI_REG8(0x3bc2), 0xcd }, ++ { CCI_REG8(0x3bc3), 0xcd }, { CCI_REG8(0x3bc4), 0xcd }, ++ { CCI_REG8(0x3bc5), 0xcd }, { CCI_REG8(0x3bc6), 0xcd }, ++ { CCI_REG8(0x3bc7), 0xcd }, { CCI_REG8(0x3bc8), 0xcd }, ++ { CCI_REG8(0x3bc9), 0xcd }, { CCI_REG8(0x3bca), 0xcd }, ++ { CCI_REG8(0x3bcb), 0xcd }, { CCI_REG8(0x3bcc), 0xcd }, ++ { CCI_REG8(0x3bcd), 0xcd }, { CCI_REG8(0x3bce), 0xcd }, ++ { CCI_REG8(0x3bcf), 0xcd }, { CCI_REG8(0x3bd0), 0xcd }, ++ { CCI_REG8(0x3bd1), 0xcd }, { CCI_REG8(0x3bd2), 0xcd }, ++ { CCI_REG8(0x3bd3), 0xcd }, { CCI_REG8(0x3bd4), 0xcd }, ++ { CCI_REG8(0x3bd5), 0xcd }, { CCI_REG8(0x3bd6), 0xcd }, ++ { CCI_REG8(0x3bd7), 0xcd }, { CCI_REG8(0x3bd8), 0xcd }, ++ { CCI_REG8(0x3bd9), 0xcd }, { CCI_REG8(0x3bda), 0xcd }, ++ { CCI_REG8(0x3bdb), 0xcd }, { CCI_REG8(0x3bdc), 0xcd }, ++ { CCI_REG8(0x3bdd), 0xcd }, { CCI_REG8(0x3bde), 0xcd }, ++ { CCI_REG8(0x3bdf), 0xcd }, { CCI_REG8(0x3be0), 0xcd }, ++ { CCI_REG8(0x3be1), 0xcd }, { CCI_REG8(0x3be2), 0xcd }, ++ { CCI_REG8(0x3be3), 0xcd }, { CCI_REG8(0x3be4), 0xcd }, ++ { CCI_REG8(0x3be5), 0xcd }, { CCI_REG8(0x3be6), 0xcd }, ++ { CCI_REG8(0x3be7), 0xcd }, { CCI_REG8(0x3be8), 0xcd }, ++ { CCI_REG8(0x3be9), 0xcd }, { CCI_REG8(0x3bea), 0xcd }, ++ { CCI_REG8(0x3beb), 0xcd }, { CCI_REG8(0x3bec), 0xcd }, ++ { CCI_REG8(0x3bed), 0xcd }, { CCI_REG8(0x3bee), 0xcd }, ++ { CCI_REG8(0x3bef), 0xcd }, { CCI_REG8(0x3bf0), 0xcd }, ++ { CCI_REG8(0x3bf1), 0xcd }, { CCI_REG8(0x3bf2), 0xcd }, ++ { CCI_REG8(0x3bf3), 0xcd }, { CCI_REG8(0x3bf4), 0xcd }, ++ { CCI_REG8(0x3bf5), 0xcd }, { CCI_REG8(0x3bf6), 0xcd }, ++ { CCI_REG8(0x3bf7), 0xcd }, { CCI_REG8(0x3bf8), 0xcd }, ++ { CCI_REG8(0x3bf9), 0xcd }, { CCI_REG8(0x3bfa), 0xcd }, ++ { CCI_REG8(0x3bfb), 0xcd }, { CCI_REG8(0x3bfc), 0xcd }, ++ { CCI_REG8(0x3bfd), 0xcd }, { CCI_REG8(0x3bfe), 0xcd }, ++ { CCI_REG8(0x3bff), 0xcd }, { CCI_REG8(0x3c00), 0xcd }, ++ { CCI_REG8(0x3c01), 0xcd }, { CCI_REG8(0x3c02), 0xcd }, ++ { CCI_REG8(0x3c03), 0xcd }, { CCI_REG8(0x3c04), 0xcd }, ++ { CCI_REG8(0x3c05), 0xcd }, { CCI_REG8(0x3c06), 0xcd }, ++ { CCI_REG8(0x3c07), 0xcd }, { CCI_REG8(0x3c08), 0xcd }, ++ { CCI_REG8(0x3c09), 0xcd }, { CCI_REG8(0x3c0a), 0xcd }, ++ { CCI_REG8(0x3c0b), 0xcd }, { CCI_REG8(0x3c0c), 0xcd }, ++ { CCI_REG8(0x3c0d), 0xcd }, { CCI_REG8(0x3c0e), 0xcd }, ++ { CCI_REG8(0x3c0f), 0xcd }, { CCI_REG8(0x3c10), 0xcd }, ++ { CCI_REG8(0x3c11), 0xcd }, { CCI_REG8(0x3c12), 0xcd }, ++ { CCI_REG8(0x3c13), 0xcd }, { CCI_REG8(0x3c14), 0xcd }, ++ { CCI_REG8(0x3c15), 0xcd }, { CCI_REG8(0x3c16), 0xcd }, ++ { CCI_REG8(0x3c17), 0xcd }, { CCI_REG8(0x3c18), 0xcd }, ++ { CCI_REG8(0x3c19), 0xcd }, { CCI_REG8(0x3c1a), 0xcd }, ++ { CCI_REG8(0x3c1b), 0xcd }, { CCI_REG8(0x3c1c), 0xcd }, ++ { CCI_REG8(0x3c1d), 0xcd }, { CCI_REG8(0x3c1e), 0xcd }, ++ { CCI_REG8(0x3c1f), 0xcd }, { CCI_REG8(0x3c20), 0xcd }, ++ { CCI_REG8(0x3c21), 0xcd }, { CCI_REG8(0x3c22), 0xcd }, ++ { CCI_REG8(0x3c23), 0xcd }, { CCI_REG8(0x3c24), 0xcd }, ++ { CCI_REG8(0x3c25), 0xcd }, { CCI_REG8(0x3c26), 0xcd }, ++ { CCI_REG8(0x3c27), 0xcd }, { CCI_REG8(0x3c28), 0xcd }, ++ { CCI_REG8(0x3c29), 0xcd }, { CCI_REG8(0x3c2a), 0xcd }, ++ { CCI_REG8(0x3c2b), 0xcd }, { CCI_REG8(0x3c2c), 0xcd }, ++ { CCI_REG8(0x3c2d), 0xcd }, { CCI_REG8(0x3c2e), 0xcd }, ++ { CCI_REG8(0x3c2f), 0xcd }, { CCI_REG8(0x3c30), 0xcd }, ++ { CCI_REG8(0x3c31), 0xcd }, { CCI_REG8(0x3c32), 0xcd }, ++ { CCI_REG8(0x3c33), 0xcd }, { CCI_REG8(0x3c34), 0xcd }, ++ { CCI_REG8(0x3c35), 0xcd }, { CCI_REG8(0x3c36), 0xcd }, ++ { CCI_REG8(0x3c37), 0xcd }, { CCI_REG8(0x3c38), 0xcd }, ++ { CCI_REG8(0x3c39), 0xcd }, { CCI_REG8(0x3c3a), 0xcd }, ++ { CCI_REG8(0x3c3b), 0xcd }, { CCI_REG8(0x3c3c), 0xcd }, ++ { CCI_REG8(0x3c3d), 0xcd }, { CCI_REG8(0x3c3e), 0xcd }, ++ { CCI_REG8(0x3c3f), 0xcd }, { CCI_REG8(0x3c40), 0xcd }, ++ { CCI_REG8(0x3c41), 0xcd }, { CCI_REG8(0x3c42), 0xcd }, ++ { CCI_REG8(0x3c43), 0xcd }, { CCI_REG8(0x3c44), 0xcd }, ++ { CCI_REG8(0x3c45), 0xcd }, { CCI_REG8(0x3c46), 0xcd }, ++ { CCI_REG8(0x3c47), 0xcd }, { CCI_REG8(0x3c48), 0xcd }, ++ { CCI_REG8(0x3c49), 0xcd }, { CCI_REG8(0x3c4a), 0xcd }, ++ { CCI_REG8(0x3c4b), 0xcd }, { CCI_REG8(0x3c4c), 0xcd }, ++ { CCI_REG8(0x3c4d), 0xcd }, { CCI_REG8(0x3c4e), 0xcd }, ++ { CCI_REG8(0x3c4f), 0xcd }, { CCI_REG8(0x3c50), 0xcd }, ++ { CCI_REG8(0x3c51), 0xcd }, { CCI_REG8(0x3c52), 0xcd }, ++ { CCI_REG8(0x3c53), 0xcd }, { CCI_REG8(0x3c54), 0xcd }, ++ { CCI_REG8(0x3c55), 0xcd }, { CCI_REG8(0x3c56), 0xcd }, ++ { CCI_REG8(0x3c57), 0xcd }, { CCI_REG8(0x3c58), 0xcd }, ++ { CCI_REG8(0x3c59), 0xcd }, { CCI_REG8(0x3c5a), 0xcd }, ++ { CCI_REG8(0x3c5b), 0xcd }, { CCI_REG8(0x3c5c), 0xcd }, ++ { CCI_REG8(0x3c5d), 0xcd }, { CCI_REG8(0x3c5e), 0xcd }, ++ { CCI_REG8(0x3c5f), 0xcd }, { CCI_REG8(0x3c60), 0xcd }, ++ { CCI_REG8(0x3c61), 0xcd }, { CCI_REG8(0x3c62), 0xcd }, ++ { CCI_REG8(0x3c63), 0xcd }, { CCI_REG8(0x3c64), 0xcd }, ++ { CCI_REG8(0x3c65), 0xcd }, { CCI_REG8(0x3c66), 0xcd }, ++ { CCI_REG8(0x3c67), 0xcd }, { CCI_REG8(0x3c68), 0xcd }, ++ { CCI_REG8(0x3c69), 0xcd }, { CCI_REG8(0x3c6a), 0xcd }, ++ { CCI_REG8(0x3c6b), 0xcd }, { CCI_REG8(0x3c6c), 0xcd }, ++ { CCI_REG8(0x3c6d), 0xcd }, { CCI_REG8(0x3c6e), 0xcd }, ++ { CCI_REG8(0x3c6f), 0xcd }, { CCI_REG8(0x3c70), 0xcd }, ++ { CCI_REG8(0x3c71), 0xcd }, { CCI_REG8(0x3c72), 0xcd }, ++ { CCI_REG8(0x3c73), 0xcd }, { CCI_REG8(0x3c74), 0xcd }, ++ { CCI_REG8(0x3c75), 0xcd }, { CCI_REG8(0x3c76), 0xcd }, ++ { CCI_REG8(0x3c77), 0xcd }, { CCI_REG8(0x3c78), 0xcd }, ++ { CCI_REG8(0x3c79), 0xcd }, { CCI_REG8(0x3c7a), 0xcd }, ++ { CCI_REG8(0x3c7b), 0xcd }, { CCI_REG8(0x3c7c), 0xcd }, ++ { CCI_REG8(0x3c7d), 0xcd }, { CCI_REG8(0x3c7e), 0xcd }, ++ { CCI_REG8(0x3c7f), 0xcd }, { CCI_REG8(0x3c80), 0xcd }, ++ { CCI_REG8(0x3c81), 0xcd }, { CCI_REG8(0x3c82), 0xcd }, ++ { CCI_REG8(0x3c83), 0xcd }, { CCI_REG8(0x3c84), 0xcd }, ++ { CCI_REG8(0x3c85), 0xcd }, { CCI_REG8(0x3c86), 0xcd }, ++ { CCI_REG8(0x3c87), 0xcd }, { CCI_REG8(0x3c88), 0xcd }, ++ { CCI_REG8(0x3c89), 0xcd }, { CCI_REG8(0x3c8a), 0xcd }, ++ { CCI_REG8(0x3c8b), 0xcd }, { CCI_REG8(0x3c8c), 0xcd }, ++ { CCI_REG8(0x3c8d), 0xcd }, { CCI_REG8(0x3c8e), 0xcd }, ++ { CCI_REG8(0x3c8f), 0xcd }, { CCI_REG8(0x3c90), 0xcd }, ++ { CCI_REG8(0x3c91), 0xcd }, { CCI_REG8(0x3c92), 0xcd }, ++ { CCI_REG8(0x3c93), 0xcd }, { CCI_REG8(0x3c94), 0xcd }, ++ { CCI_REG8(0x3c95), 0xcd }, { CCI_REG8(0x3c96), 0xcd }, ++ { CCI_REG8(0x3c97), 0xcd }, { CCI_REG8(0x3c98), 0xcd }, ++ { CCI_REG8(0x3c99), 0xcd }, { CCI_REG8(0x3c9a), 0xcd }, ++ { CCI_REG8(0x3c9b), 0xcd }, { CCI_REG8(0x3c9c), 0xcd }, ++ { CCI_REG8(0x3c9d), 0xcd }, { CCI_REG8(0x3c9e), 0xcd }, ++ { CCI_REG8(0x3c9f), 0xcd }, { CCI_REG8(0x3ca0), 0xcd }, ++ { CCI_REG8(0x3ca1), 0xcd }, { CCI_REG8(0x3ca2), 0xcd }, ++ { CCI_REG8(0x3ca3), 0xcd }, { CCI_REG8(0x3ca4), 0xcd }, ++ { CCI_REG8(0x3ca5), 0xcd }, { CCI_REG8(0x3ca6), 0xcd }, ++ { CCI_REG8(0x3ca7), 0xcd }, { CCI_REG8(0x3ca8), 0xcd }, ++ { CCI_REG8(0x3ca9), 0xcd }, { CCI_REG8(0x3caa), 0xcd }, ++ { CCI_REG8(0x3cab), 0xcd }, { CCI_REG8(0x3cac), 0xcd }, ++ { CCI_REG8(0x3cad), 0xcd }, { CCI_REG8(0x3cae), 0xcd }, ++ { CCI_REG8(0x3caf), 0xcd }, { CCI_REG8(0x3cb0), 0xcd }, ++ { CCI_REG8(0x3cb1), 0x40 }, { CCI_REG8(0x3cb2), 0x40 }, ++ { CCI_REG8(0x3cb3), 0x40 }, { CCI_REG8(0x3cb4), 0x40 }, ++ { CCI_REG8(0x3cb5), 0x40 }, { CCI_REG8(0x3cb6), 0x40 }, ++ { CCI_REG8(0x3cb7), 0x40 }, { CCI_REG8(0x3cb8), 0x40 }, ++ { CCI_REG8(0x3cb9), 0x40 }, { CCI_REG8(0x3cba), 0x40 }, ++ { CCI_REG8(0x3cbb), 0x40 }, { CCI_REG8(0x3cbc), 0x40 }, ++ { CCI_REG8(0x3cbd), 0x40 }, { CCI_REG8(0x3cbe), 0x40 }, ++ { CCI_REG8(0x3cbf), 0x40 }, { CCI_REG8(0x3cc0), 0x40 }, ++ { CCI_REG8(0x3cc1), 0x40 }, { CCI_REG8(0x3cc2), 0x40 }, ++ { CCI_REG8(0x3cc3), 0x40 }, { CCI_REG8(0x3cc4), 0x40 }, ++ { CCI_REG8(0x3cc5), 0x40 }, { CCI_REG8(0x3cc6), 0x40 }, ++ { CCI_REG8(0x3cc7), 0x40 }, { CCI_REG8(0x3cc8), 0x40 }, ++ { CCI_REG8(0x3cc9), 0x40 }, { CCI_REG8(0x3cca), 0x40 }, ++ { CCI_REG8(0x3ccb), 0x40 }, { CCI_REG8(0x3ccc), 0x40 }, ++ { CCI_REG8(0x3ccd), 0x40 }, { CCI_REG8(0x3cce), 0x40 }, ++ { CCI_REG8(0x3ccf), 0x40 }, { CCI_REG8(0x3cd0), 0x40 }, ++ { CCI_REG8(0x3cd1), 0x40 }, { CCI_REG8(0x3cd2), 0x40 }, ++ { CCI_REG8(0x3cd3), 0x40 }, { CCI_REG8(0x3cd4), 0x40 }, ++ { CCI_REG8(0x3cd5), 0x40 }, { CCI_REG8(0x3cd6), 0x40 }, ++ { CCI_REG8(0x3cd7), 0x40 }, { CCI_REG8(0x3cd8), 0x40 }, ++ { CCI_REG8(0x3cd9), 0x40 }, { CCI_REG8(0x3cda), 0x40 }, ++ { CCI_REG8(0x3cdb), 0x40 }, { CCI_REG8(0x3cdc), 0x40 }, ++ { CCI_REG8(0x3cdd), 0x40 }, { CCI_REG8(0x3cde), 0x40 }, ++ { CCI_REG8(0x3cdf), 0x40 }, { CCI_REG8(0x3ce0), 0x40 }, ++ { CCI_REG8(0x3ce1), 0x40 }, { CCI_REG8(0x3ce2), 0x40 }, ++ { CCI_REG8(0x3ce3), 0x40 }, { CCI_REG8(0x3ce4), 0x40 }, ++ { CCI_REG8(0x3ce5), 0x40 }, { CCI_REG8(0x3ce6), 0x40 }, ++ { CCI_REG8(0x3ce7), 0x40 }, { CCI_REG8(0x3ce8), 0x40 }, ++ { CCI_REG8(0x3ce9), 0x40 }, { CCI_REG8(0x3cea), 0x40 }, ++ { CCI_REG8(0x3ceb), 0x40 }, { CCI_REG8(0x3cec), 0x40 }, ++ { CCI_REG8(0x3ced), 0x40 }, { CCI_REG8(0x3cee), 0x40 }, ++ { CCI_REG8(0x3cef), 0x40 }, { CCI_REG8(0x3cf0), 0x40 }, ++ { CCI_REG8(0x3cf1), 0x40 }, { CCI_REG8(0x3cf2), 0x40 }, ++ { CCI_REG8(0x3cf3), 0x40 }, { CCI_REG8(0x3cf4), 0x40 }, ++ { CCI_REG8(0x3cf5), 0x40 }, { CCI_REG8(0x3cf6), 0x40 }, ++ { CCI_REG8(0x3cf7), 0x40 }, { CCI_REG8(0x3cf8), 0x40 }, ++ { CCI_REG8(0x3cf9), 0x40 }, { CCI_REG8(0x3cfa), 0x40 }, ++ { CCI_REG8(0x3cfb), 0x40 }, { CCI_REG8(0x3cfc), 0x40 }, ++ { CCI_REG8(0x3cfd), 0x40 }, { CCI_REG8(0x3cfe), 0x40 }, ++ { CCI_REG8(0x3cff), 0x40 }, { CCI_REG8(0x3d00), 0x40 }, ++ { CCI_REG8(0x3d01), 0x40 }, { CCI_REG8(0x3d02), 0x40 }, ++ { CCI_REG8(0x3d03), 0x40 }, { CCI_REG8(0x3d04), 0x40 }, ++ { CCI_REG8(0x3d05), 0x40 }, { CCI_REG8(0x3d06), 0x40 }, ++ { CCI_REG8(0x3d07), 0x40 }, { CCI_REG8(0x3d08), 0x40 }, ++ { CCI_REG8(0x3d09), 0x40 }, { CCI_REG8(0x3d0a), 0x40 }, ++ { CCI_REG8(0x3d0b), 0xcd }, { CCI_REG8(0x3d0c), 0xcd }, ++ { CCI_REG8(0x3d0d), 0xcd }, { CCI_REG8(0x3d0e), 0xcd }, ++ { CCI_REG8(0x3d0f), 0xcd }, { CCI_REG8(0x3d10), 0xcd }, ++ { CCI_REG8(0x3d11), 0xcd }, { CCI_REG8(0x3d12), 0xcd }, ++ { CCI_REG8(0x3d13), 0xcd }, { CCI_REG8(0x3d14), 0xcd }, ++ { CCI_REG8(0x3d15), 0xcd }, { CCI_REG8(0x3d16), 0xcd }, ++ { CCI_REG8(0x3d17), 0xcd }, { CCI_REG8(0x3d18), 0xcd }, ++ { CCI_REG8(0x3d19), 0xcd }, { CCI_REG8(0x3d1a), 0xcd }, ++ { CCI_REG8(0x3d1b), 0xcd }, { CCI_REG8(0x3d1c), 0xcd }, ++ { CCI_REG8(0x3d1d), 0xcd }, { CCI_REG8(0x3d1e), 0xcd }, ++ { CCI_REG8(0x3d1f), 0xcd }, { CCI_REG8(0x3d20), 0xcd }, ++ { CCI_REG8(0x3d21), 0xcd }, { CCI_REG8(0x3d22), 0xcd }, ++ { CCI_REG8(0x3d23), 0xcd }, { CCI_REG8(0x3d24), 0xcd }, ++ { CCI_REG8(0x3d25), 0xcd }, { CCI_REG8(0x3d26), 0xcd }, ++ { CCI_REG8(0x3d27), 0xcd }, { CCI_REG8(0x3d28), 0xcd }, ++ { CCI_REG8(0x3d29), 0xcd }, { CCI_REG8(0x3d2a), 0xcd }, ++ { CCI_REG8(0x3d2b), 0xcd }, { CCI_REG8(0x3d2c), 0xcd }, ++ { CCI_REG8(0x3d2d), 0xcd }, { CCI_REG8(0x3d2e), 0xcd }, ++ { CCI_REG8(0x3d2f), 0xcd }, { CCI_REG8(0x3d30), 0xcd }, ++ { CCI_REG8(0x3d31), 0xcd }, { CCI_REG8(0x3d32), 0xcd }, ++ { CCI_REG8(0x3d33), 0xcd }, { CCI_REG8(0x3d34), 0xcd }, ++ { CCI_REG8(0x3d35), 0xcd }, { CCI_REG8(0x3d36), 0xcd }, ++ { CCI_REG8(0x3d37), 0xcd }, { CCI_REG8(0x3d38), 0xcd }, ++ { CCI_REG8(0x3d39), 0xcd }, { CCI_REG8(0x3d3a), 0xcd }, ++ { CCI_REG8(0x3d3b), 0xcd }, { CCI_REG8(0x3d3c), 0xcd }, ++ { CCI_REG8(0x3d3d), 0xcd }, { CCI_REG8(0x3d3e), 0xcd }, ++ { CCI_REG8(0x3d3f), 0xcd }, { CCI_REG8(0x3d40), 0xcd }, ++ { CCI_REG8(0x3d41), 0xcd }, { CCI_REG8(0x3d42), 0xcd }, ++ { CCI_REG8(0x3d43), 0xcd }, { CCI_REG8(0x3d44), 0xcd }, ++ { CCI_REG8(0x3d45), 0xcd }, { CCI_REG8(0x3d46), 0xcd }, ++ { CCI_REG8(0x3d47), 0xcd }, { CCI_REG8(0x3d48), 0xcd }, ++ { CCI_REG8(0x3d49), 0xcd }, { CCI_REG8(0x3d4a), 0xcd }, ++ { CCI_REG8(0x3d4b), 0xcd }, { CCI_REG8(0x3d4c), 0xcd }, ++ { CCI_REG8(0x3d4d), 0xcd }, { CCI_REG8(0x3d4e), 0xcd }, ++ { CCI_REG8(0x3d4f), 0xcd }, { CCI_REG8(0x3d50), 0xcd }, ++ { CCI_REG8(0x3d51), 0xcd }, { CCI_REG8(0x3d52), 0xcd }, ++ { CCI_REG8(0x3d53), 0xcd }, { CCI_REG8(0x3d54), 0xcd }, ++ { CCI_REG8(0x3d55), 0xcd }, { CCI_REG8(0x3d56), 0xcd }, ++ { CCI_REG8(0x3d57), 0xcd }, { CCI_REG8(0x3d58), 0xcd }, ++ { CCI_REG8(0x3d59), 0xcd }, { CCI_REG8(0x3d5a), 0xcd }, ++ { CCI_REG8(0x3d5b), 0xcd }, { CCI_REG8(0x3d5c), 0xcd }, ++ { CCI_REG8(0x3d5d), 0xcd }, { CCI_REG8(0x3d5e), 0xcd }, ++ { CCI_REG8(0x3d5f), 0xcd }, { CCI_REG8(0x3d60), 0xcd }, ++ { CCI_REG8(0x3d61), 0xcd }, { CCI_REG8(0x3d62), 0xcd }, ++ { CCI_REG8(0x3d63), 0xcd }, { CCI_REG8(0x3d64), 0xcd }, ++ { CCI_REG8(0x3d65), 0x40 }, { CCI_REG8(0x3d66), 0x40 }, ++ { CCI_REG8(0x3d67), 0x40 }, { CCI_REG8(0x3d68), 0x40 }, ++ { CCI_REG8(0x3d69), 0x40 }, { CCI_REG8(0x3d6a), 0x40 }, ++ { CCI_REG8(0x3d6b), 0x40 }, { CCI_REG8(0x3d6c), 0x40 }, ++ { CCI_REG8(0x3d6d), 0x40 }, { CCI_REG8(0x3d6e), 0x40 }, ++ { CCI_REG8(0x3d6f), 0x40 }, { CCI_REG8(0x3d70), 0x40 }, ++ { CCI_REG8(0x3d71), 0x40 }, { CCI_REG8(0x3d72), 0x40 }, ++ { CCI_REG8(0x3d73), 0x40 }, { CCI_REG8(0x3d74), 0x40 }, ++ { CCI_REG8(0x3d75), 0x40 }, { CCI_REG8(0x3d76), 0x40 }, ++ { CCI_REG8(0x3d77), 0x40 }, { CCI_REG8(0x3d78), 0x40 }, ++ { CCI_REG8(0x3d79), 0x40 }, { CCI_REG8(0x3d7a), 0x40 }, ++ { CCI_REG8(0x3d7b), 0x40 }, { CCI_REG8(0x3d7c), 0x40 }, ++ { CCI_REG8(0x3d7d), 0x40 }, { CCI_REG8(0x3d7e), 0x40 }, ++ { CCI_REG8(0x3d7f), 0x40 }, { CCI_REG8(0x3d80), 0x40 }, ++ { CCI_REG8(0x3d81), 0x40 }, { CCI_REG8(0x3d82), 0x40 }, ++ { CCI_REG8(0x3d83), 0x40 }, { CCI_REG8(0x3d84), 0x40 }, ++ { CCI_REG8(0x3d85), 0x40 }, { CCI_REG8(0x3d86), 0x40 }, ++ { CCI_REG8(0x3d87), 0x40 }, { CCI_REG8(0x3d88), 0x40 }, ++ { CCI_REG8(0x3d89), 0x40 }, { CCI_REG8(0x3d8a), 0x40 }, ++ { CCI_REG8(0x3d8b), 0x40 }, { CCI_REG8(0x3d8c), 0x40 }, ++ { CCI_REG8(0x3d8d), 0x40 }, { CCI_REG8(0x3d8e), 0x40 }, ++ { CCI_REG8(0x3d8f), 0x40 }, { CCI_REG8(0x3d90), 0x40 }, ++ { CCI_REG8(0x3d91), 0x40 }, { CCI_REG8(0x3d92), 0x40 }, ++ { CCI_REG8(0x3d93), 0x40 }, { CCI_REG8(0x3d94), 0x40 }, ++ { CCI_REG8(0x3d95), 0x40 }, { CCI_REG8(0x3d96), 0x40 }, ++ { CCI_REG8(0x3d97), 0x40 }, { CCI_REG8(0x3d98), 0x40 }, ++ { CCI_REG8(0x3d99), 0x40 }, { CCI_REG8(0x3d9a), 0x40 }, ++ { CCI_REG8(0x3d9b), 0x40 }, { CCI_REG8(0x3d9c), 0x40 }, ++ { CCI_REG8(0x3d9d), 0x40 }, { CCI_REG8(0x3d9e), 0x40 }, ++ { CCI_REG8(0x3d9f), 0x40 }, { CCI_REG8(0x3da0), 0x40 }, ++ { CCI_REG8(0x3da1), 0x40 }, { CCI_REG8(0x3da2), 0x40 }, ++ { CCI_REG8(0x3da3), 0x40 }, { CCI_REG8(0x3da4), 0x40 }, ++ { CCI_REG8(0x3da5), 0x40 }, { CCI_REG8(0x3da6), 0x40 }, ++ { CCI_REG8(0x3da7), 0x40 }, { CCI_REG8(0x3da8), 0x40 }, ++ { CCI_REG8(0x3da9), 0x40 }, { CCI_REG8(0x3daa), 0x40 }, ++ { CCI_REG8(0x3dab), 0x40 }, { CCI_REG8(0x3dac), 0x40 }, ++ { CCI_REG8(0x3dad), 0x40 }, { CCI_REG8(0x3dae), 0x40 }, ++ { CCI_REG8(0x3daf), 0x40 }, { CCI_REG8(0x3db0), 0x40 }, ++ { CCI_REG8(0x3db1), 0x40 }, { CCI_REG8(0x3db2), 0x40 }, ++ { CCI_REG8(0x3db3), 0x40 }, { CCI_REG8(0x3db4), 0x40 }, ++ { CCI_REG8(0x3db5), 0x40 }, { CCI_REG8(0x3db6), 0x40 }, ++ { CCI_REG8(0x3db7), 0x40 }, { CCI_REG8(0x3db8), 0x40 }, ++ { CCI_REG8(0x3db9), 0x40 }, { CCI_REG8(0x3dba), 0x40 }, ++ { CCI_REG8(0x3dbb), 0x40 }, { CCI_REG8(0x3dbc), 0x40 }, ++ { CCI_REG8(0x3dbd), 0x40 }, { CCI_REG8(0x3dbe), 0x40 }, ++ { CCI_REG8(0x3dbf), 0xcd }, { CCI_REG8(0x3dc0), 0xcd }, ++ { CCI_REG8(0x3dc1), 0xcd }, { CCI_REG8(0x3dc2), 0xcd }, ++ { CCI_REG8(0x3dc3), 0xcd }, { CCI_REG8(0x3dc4), 0xcd }, ++ { CCI_REG8(0x3dc5), 0xcd }, { CCI_REG8(0x3dc6), 0xcd }, ++ { CCI_REG8(0x3dc7), 0xcd }, { CCI_REG8(0x3dc8), 0xcd }, ++ { CCI_REG8(0x3dc9), 0xcd }, { CCI_REG8(0x3dca), 0xcd }, ++ { CCI_REG8(0x3dcb), 0xcd }, { CCI_REG8(0x3dcc), 0xcd }, ++ { CCI_REG8(0x3dcd), 0xcd }, { CCI_REG8(0x3dce), 0xcd }, ++ { CCI_REG8(0x3dcf), 0xcd }, { CCI_REG8(0x3dd0), 0xcd }, ++ { CCI_REG8(0x3dd1), 0xcd }, { CCI_REG8(0x3dd2), 0xcd }, ++ { CCI_REG8(0x3dd3), 0xcd }, { CCI_REG8(0x3dd4), 0xcd }, ++ { CCI_REG8(0x3dd5), 0xcd }, { CCI_REG8(0x3dd6), 0xcd }, ++ { CCI_REG8(0x3dd7), 0xcd }, { CCI_REG8(0x3dd8), 0xcd }, ++ { CCI_REG8(0x3dd9), 0xcd }, { CCI_REG8(0x3dda), 0xcd }, ++ { CCI_REG8(0x3ddb), 0xcd }, { CCI_REG8(0x3ddc), 0xcd }, ++ { CCI_REG8(0x3ddd), 0xcd }, { CCI_REG8(0x3dde), 0xcd }, ++ { CCI_REG8(0x3ddf), 0xcd }, { CCI_REG8(0x3de0), 0xcd }, ++ { CCI_REG8(0x3de1), 0xcd }, { CCI_REG8(0x3de2), 0xcd }, ++ { CCI_REG8(0x3de3), 0xcd }, { CCI_REG8(0x3de4), 0xcd }, ++ { CCI_REG8(0x3de5), 0xcd }, { CCI_REG8(0x3de6), 0xcd }, ++ { CCI_REG8(0x3de7), 0xcd }, { CCI_REG8(0x3de8), 0xcd }, ++ { CCI_REG8(0x3de9), 0xcd }, { CCI_REG8(0x3dea), 0xcd }, ++ { CCI_REG8(0x3deb), 0xcd }, { CCI_REG8(0x3dec), 0xcd }, ++ { CCI_REG8(0x3ded), 0xcd }, { CCI_REG8(0x3dee), 0xcd }, ++ { CCI_REG8(0x3def), 0xcd }, { CCI_REG8(0x3df0), 0xcd }, ++ { CCI_REG8(0x3df1), 0xcd }, { CCI_REG8(0x3df2), 0xcd }, ++ { CCI_REG8(0x3df3), 0xcd }, { CCI_REG8(0x3df4), 0xcd }, ++ { CCI_REG8(0x3df5), 0xcd }, { CCI_REG8(0x3df6), 0xcd }, ++ { CCI_REG8(0x3df7), 0xcd }, { CCI_REG8(0x3df8), 0xcd }, ++ { CCI_REG8(0x3df9), 0xcd }, { CCI_REG8(0x3dfa), 0xcd }, ++ { CCI_REG8(0x3dfb), 0xcd }, { CCI_REG8(0x3dfc), 0xcd }, ++ { CCI_REG8(0x3dfd), 0xcd }, { CCI_REG8(0x3dfe), 0xcd }, ++ { CCI_REG8(0x3dff), 0xcd }, { CCI_REG8(0x3e00), 0xcd }, ++ { CCI_REG8(0x3e01), 0xcd }, { CCI_REG8(0x3e02), 0xcd }, ++ { CCI_REG8(0x3e03), 0xcd }, { CCI_REG8(0x3e04), 0xcd }, ++ { CCI_REG8(0x3e05), 0xcd }, { CCI_REG8(0x3e06), 0xcd }, ++ { CCI_REG8(0x3e07), 0xcd }, { CCI_REG8(0x3e08), 0xcd }, ++ { CCI_REG8(0x3e09), 0xcd }, { CCI_REG8(0x3e0a), 0xcd }, ++ { CCI_REG8(0x3e0b), 0xcd }, { CCI_REG8(0x3e0c), 0xcd }, ++ { CCI_REG8(0x3e0d), 0xcd }, { CCI_REG8(0x3e0e), 0xcd }, ++ { CCI_REG8(0x3e0f), 0xcd }, { CCI_REG8(0x3e10), 0xcd }, ++ { CCI_REG8(0x3e11), 0xcd }, { CCI_REG8(0x3e12), 0xcd }, ++ { CCI_REG8(0x3e13), 0xcd }, { CCI_REG8(0x3e14), 0xcd }, ++ { CCI_REG8(0x3e15), 0xcd }, { CCI_REG8(0x3e16), 0xcd }, ++ { CCI_REG8(0x3e17), 0xcd }, { CCI_REG8(0x3e18), 0xcd }, ++ { CCI_REG8(0x3e19), 0xcd }, { CCI_REG8(0x3e1a), 0xcd }, ++ { CCI_REG8(0x3e1b), 0xcd }, { CCI_REG8(0x3e1c), 0xcd }, ++ { CCI_REG8(0x3e1d), 0xcd }, { CCI_REG8(0x3e1e), 0xcd }, ++ { CCI_REG8(0x3e1f), 0xcd }, { CCI_REG8(0x3e20), 0xcd }, ++ { CCI_REG8(0x3e21), 0xcd }, { CCI_REG8(0x3e22), 0xcd }, ++ { CCI_REG8(0x3e23), 0xcd }, { CCI_REG8(0x3e24), 0xcd }, ++ { CCI_REG8(0x3e25), 0xcd }, { CCI_REG8(0x3e26), 0xcd }, ++ { CCI_REG8(0x3e27), 0xcd }, { CCI_REG8(0x3e28), 0xcd }, ++ { CCI_REG8(0x3e29), 0xcd }, { CCI_REG8(0x3e2a), 0xcd }, ++ { CCI_REG8(0x3e2b), 0xcd }, { CCI_REG8(0x3e2c), 0xcd }, ++ { CCI_REG8(0x3e2d), 0xcd }, { CCI_REG8(0x3e2e), 0xcd }, ++ { CCI_REG8(0x3e2f), 0xcd }, { CCI_REG8(0x3e30), 0xcd }, ++ { CCI_REG8(0x3e31), 0xcd }, { CCI_REG8(0x3e32), 0xcd }, ++ { CCI_REG8(0x3e33), 0xcd }, { CCI_REG8(0x3e34), 0xcd }, ++ { CCI_REG8(0x3e35), 0xcd }, { CCI_REG8(0x3e36), 0xcd }, ++ { CCI_REG8(0x3e37), 0xcd }, { CCI_REG8(0x3e38), 0xcd }, ++ { CCI_REG8(0x3e39), 0xcd }, { CCI_REG8(0x3e3a), 0xcd }, ++ { CCI_REG8(0x3e3b), 0xcd }, { CCI_REG8(0x3e3c), 0xcd }, ++ { CCI_REG8(0x3e3d), 0xcd }, { CCI_REG8(0x3e3e), 0xcd }, ++ { CCI_REG8(0x3e3f), 0xcd }, { CCI_REG8(0x3e40), 0xcd }, ++ { CCI_REG8(0x3e41), 0xcd }, { CCI_REG8(0x3e42), 0xcd }, ++ { CCI_REG8(0x3e43), 0xcd }, { CCI_REG8(0x3e44), 0xcd }, ++ { CCI_REG8(0x3e45), 0xcd }, { CCI_REG8(0x3e46), 0xcd }, ++ { CCI_REG8(0x3e47), 0xcd }, { CCI_REG8(0x3e48), 0xcd }, ++ { CCI_REG8(0x3e49), 0xcd }, { CCI_REG8(0x3e4a), 0xcd }, ++ { CCI_REG8(0x3e4b), 0xcd }, { CCI_REG8(0x3e4c), 0xcd }, ++ { CCI_REG8(0x3e4d), 0xcd }, { CCI_REG8(0x3e4e), 0xcd }, ++ { CCI_REG8(0x3e4f), 0xcd }, { CCI_REG8(0x3e50), 0xcd }, ++ { CCI_REG8(0x3e51), 0xcd }, { CCI_REG8(0x3e52), 0xcd }, ++ { CCI_REG8(0x3e53), 0xcd }, { CCI_REG8(0x3e54), 0xcd }, ++ { CCI_REG8(0x3e55), 0xcd }, { CCI_REG8(0x3e56), 0xcd }, ++ { CCI_REG8(0x3e57), 0xcd }, { CCI_REG8(0x3e58), 0xcd }, ++ { CCI_REG8(0x3e59), 0xcd }, { CCI_REG8(0x3e5a), 0xcd }, ++ { CCI_REG8(0x3e5b), 0xcd }, { CCI_REG8(0x3e5c), 0xcd }, ++ { CCI_REG8(0x3e5d), 0xcd }, { CCI_REG8(0x3e5e), 0xcd }, ++ { CCI_REG8(0x3e5f), 0xcd }, { CCI_REG8(0x3e60), 0xcd }, ++ { CCI_REG8(0x3e61), 0xcd }, { CCI_REG8(0x3e62), 0xcd }, ++ { CCI_REG8(0x3e63), 0xcd }, { CCI_REG8(0x3e64), 0xcd }, ++ { CCI_REG8(0x3e65), 0xcd }, { CCI_REG8(0x3e66), 0xcd }, ++ { CCI_REG8(0x3e67), 0xcd }, { CCI_REG8(0x3e68), 0xcd }, ++ { CCI_REG8(0x3e69), 0xcd }, { CCI_REG8(0x3e6a), 0xcd }, ++ { CCI_REG8(0x3e6b), 0xcd }, { CCI_REG8(0x3e6c), 0xcd }, ++ { CCI_REG8(0x3e6d), 0xcd }, { CCI_REG8(0x3e6e), 0xcd }, ++ { CCI_REG8(0x3e6f), 0xcd }, { CCI_REG8(0x3e70), 0xcd }, ++ { CCI_REG8(0x3e71), 0xcd }, { CCI_REG8(0x3e72), 0xcd }, ++ { CCI_REG8(0x3e73), 0xcd }, { CCI_REG8(0x3e74), 0xcd }, ++ { CCI_REG8(0x3e75), 0xcd }, { CCI_REG8(0x3e76), 0xcd }, ++ { CCI_REG8(0x3e77), 0xcd }, { CCI_REG8(0x3e78), 0xcd }, ++ { CCI_REG8(0x3e79), 0xcd }, { CCI_REG8(0x3e7a), 0xcd }, ++ { CCI_REG8(0x3e7b), 0xcd }, { CCI_REG8(0x3e7c), 0xcd }, ++ { CCI_REG8(0x3e7d), 0xcd }, { CCI_REG8(0x3e7e), 0xcd }, ++ { CCI_REG8(0x3e7f), 0xcd }, { CCI_REG8(0x3e80), 0xcd }, ++ { CCI_REG8(0x3e81), 0xcd }, { CCI_REG8(0x3e82), 0xcd }, ++ { CCI_REG8(0x3e83), 0xcd }, { CCI_REG8(0x3e84), 0xcd }, ++ { CCI_REG8(0x3e85), 0xcd }, { CCI_REG8(0x3e86), 0xcd }, ++ { CCI_REG8(0x3e87), 0xcd }, { CCI_REG8(0x3e88), 0xcd }, ++ { CCI_REG8(0x3e89), 0xcd }, { CCI_REG8(0x3e8a), 0xcd }, ++ { CCI_REG8(0x3e8b), 0xcd }, { CCI_REG8(0x3e8c), 0xcd }, ++ { CCI_REG8(0x3e8d), 0xcd }, { CCI_REG8(0x3e8e), 0xcd }, ++ { CCI_REG8(0x3e8f), 0xcd }, { CCI_REG8(0x3e90), 0xcd }, ++ { CCI_REG8(0x3e91), 0xcd }, { CCI_REG8(0x3e92), 0xcd }, ++ { CCI_REG8(0x3e93), 0xcd }, { CCI_REG8(0x3e94), 0xcd }, ++ { CCI_REG8(0x3e95), 0xcd }, { CCI_REG8(0x3e96), 0xcd }, ++ { CCI_REG8(0x3e97), 0xcd }, { CCI_REG8(0x3e98), 0xcd }, ++ { CCI_REG8(0x3e99), 0xcd }, { CCI_REG8(0x3e9a), 0xcd }, ++ { CCI_REG8(0x3e9b), 0xcd }, { CCI_REG8(0x3e9c), 0xcd }, ++ { CCI_REG8(0x3e9d), 0xcd }, { CCI_REG8(0x3e9e), 0xcd }, ++ { CCI_REG8(0x3e9f), 0xcd }, { CCI_REG8(0xfff9), 0x06 }, ++ { CCI_REG8(0xc03f), 0x01 }, { CCI_REG8(0xc03e), 0x08 }, ++ { CCI_REG8(0xc02c), 0xff }, { CCI_REG8(0xc005), 0x06 }, ++ { CCI_REG8(0xc006), 0x30 }, { CCI_REG8(0xc007), 0xc0 }, ++ { CCI_REG8(0xc027), 0x01 }, { CCI_REG8(0x30c0), 0x05 }, ++ { CCI_REG8(0x30c1), 0x9f }, { CCI_REG8(0x30c2), 0x06 }, ++ { CCI_REG8(0x30c3), 0x5f }, { CCI_REG8(0x30c4), 0x80 }, ++ { CCI_REG8(0x30c5), 0x08 }, { CCI_REG8(0x30c6), 0x39 }, ++ { CCI_REG8(0x30c7), 0x00 }, { CCI_REG8(0xc046), 0x20 }, ++ { CCI_REG8(0xc043), 0x01 }, { CCI_REG8(0xc04b), 0x01 }, ++ { CCI_REG8(0x0102), 0x01 }, { CCI_REG8(0x0100), 0x00 }, ++ { CCI_REG8(0x0102), 0x00 }, { CCI_REG8(0x3015), 0xf0 }, ++ { CCI_REG8(0x3018), 0xf0 }, { CCI_REG8(0x301c), 0xf0 }, ++ { CCI_REG8(0x301d), 0xf6 }, { CCI_REG8(0x301e), 0xf1 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_9248x6944[] = { ++ { CCI_REG8(0x0305), 0x98 }, { CCI_REG8(0x0306), 0x04 }, ++ { CCI_REG8(0x0307), 0x01 }, { CCI_REG8(0x4837), 0x1a }, ++ { CCI_REG8(0x4888), 0x10 }, { CCI_REG8(0x4860), 0x00 }, ++ { CCI_REG8(0x4850), 0x43 }, { CCI_REG8(0x480C), 0x92 }, ++ { CCI_REG8(0x5001), 0x21 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_8000x6000[] = { ++ { CCI_REG8(0x0305), 0x98 }, { CCI_REG8(0x0306), 0x04 }, ++ { CCI_REG8(0x0307), 0x01 }, { CCI_REG8(0x4837), 0x1a }, ++ { CCI_REG8(0x4888), 0x10 }, { CCI_REG8(0x4860), 0x00 }, ++ { CCI_REG8(0x4850), 0x43 }, { CCI_REG8(0x480C), 0x92 }, ++ { CCI_REG8(0x5001), 0x21 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_4624_3472[] = { ++ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x3504), 0x08 }, ++ { CCI_REG8(0x360d), 0x82 }, { CCI_REG8(0x368a), 0x2e }, ++ { CCI_REG8(0x3712), 0x50 }, { CCI_REG8(0x3822), 0x00 }, ++ { CCI_REG8(0x3827), 0x40 }, { CCI_REG8(0x383d), 0x08 }, ++ { CCI_REG8(0x383f), 0x00 }, { CCI_REG8(0x384c), 0x02 }, ++ { CCI_REG8(0x384d), 0xba }, { CCI_REG8(0x3852), 0x00 }, ++ { CCI_REG8(0x3856), 0x08 }, { CCI_REG8(0x3857), 0x08 }, ++ { CCI_REG8(0x3858), 0x10 }, { CCI_REG8(0x3859), 0x10 }, ++ { CCI_REG8(0x4016), 0x0f }, { CCI_REG8(0x4018), 0x03 }, ++ { CCI_REG8(0x4504), 0x1e }, { CCI_REG8(0x4523), 0x41 }, ++ { CCI_REG8(0x45c0), 0x01 }, { CCI_REG8(0x4641), 0x12 }, ++ { CCI_REG8(0x4643), 0x0c }, { CCI_REG8(0x4915), 0x02 }, ++ { CCI_REG8(0x4916), 0x1d }, { CCI_REG8(0x4a15), 0x02 }, ++ { CCI_REG8(0x4a16), 0x1d }, { CCI_REG8(0x3703), 0x72 }, ++ { CCI_REG8(0x3709), 0xe6 }, { CCI_REG8(0x3a60), 0x68 }, ++ { CCI_REG8(0x3a6f), 0x68 }, { CCI_REG8(0x3a5e), 0xdc }, ++ { CCI_REG8(0x3a6d), 0xdc }, { CCI_REG8(0x3721), 0xc9 }, ++ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x527a), 0x00 }, ++ { CCI_REG8(0x527b), 0x65 }, { CCI_REG8(0x527c), 0x00 }, ++ { CCI_REG8(0x527d), 0x82 }, { CCI_REG8(0x5280), 0x24 }, ++ { CCI_REG8(0x5281), 0x40 }, { CCI_REG8(0x5282), 0x1b }, ++ { CCI_REG8(0x5283), 0x40 }, { CCI_REG8(0x5284), 0x24 }, ++ { CCI_REG8(0x5285), 0x40 }, { CCI_REG8(0x5286), 0x1b }, ++ { CCI_REG8(0x5287), 0x40 }, { CCI_REG8(0x5200), 0x24 }, ++ { CCI_REG8(0x5201), 0x40 }, { CCI_REG8(0x5202), 0x1b }, ++ { CCI_REG8(0x5203), 0x40 }, { CCI_REG8(0x481b), 0x35 }, ++ { CCI_REG8(0x4862), 0x25 }, { CCI_REG8(0x3400), 0x00 }, ++ { CCI_REG8(0x3421), 0x23 }, { CCI_REG8(0x3422), 0xfc }, ++ { CCI_REG8(0x3423), 0x07 }, { CCI_REG8(0x3424), 0x01 }, ++ { CCI_REG8(0x3425), 0x04 }, { CCI_REG8(0x3426), 0x50 }, ++ { CCI_REG8(0x3427), 0x55 }, { CCI_REG8(0x3428), 0x15 }, ++ { CCI_REG8(0x3429), 0x00 }, { CCI_REG8(0x3025), 0x03 }, ++ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x0305), 0x98 }, ++ { CCI_REG8(0x0306), 0x04 }, { CCI_REG8(0x0307), 0x01 }, ++ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 }, ++ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 }, ++ { CCI_REG8(0x480C), 0x92 }, { CCI_REG8(0x5001), 0x21 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_3840x2160[] = { ++ { CCI_REG8(0x034a), 0x05 }, { CCI_REG8(0x034b), 0x05 }, ++ { CCI_REG8(0x3504), 0x08 }, { CCI_REG8(0x360d), 0x82 }, ++ { CCI_REG8(0x368a), 0x2e }, { CCI_REG8(0x3712), 0x50 }, ++ { CCI_REG8(0x3822), 0x00 }, { CCI_REG8(0x3827), 0x40 }, ++ { CCI_REG8(0x383d), 0x08 }, { CCI_REG8(0x383f), 0x00 }, ++ { CCI_REG8(0x384c), 0x02 }, { CCI_REG8(0x384d), 0xba }, ++ { CCI_REG8(0x3852), 0x00 }, { CCI_REG8(0x3856), 0x08 }, ++ { CCI_REG8(0x3857), 0x08 }, { CCI_REG8(0x3858), 0x10 }, ++ { CCI_REG8(0x3859), 0x10 }, { CCI_REG8(0x4016), 0x0f }, ++ { CCI_REG8(0x4018), 0x03 }, { CCI_REG8(0x4504), 0x1e }, ++ { CCI_REG8(0x4523), 0x41 }, { CCI_REG8(0x45c0), 0x01 }, ++ { CCI_REG8(0x4641), 0x12 }, { CCI_REG8(0x4643), 0x0c }, ++ { CCI_REG8(0x4915), 0x02 }, { CCI_REG8(0x4916), 0x1d }, ++ { CCI_REG8(0x4a15), 0x02 }, { CCI_REG8(0x4a16), 0x1d }, ++ { CCI_REG8(0x3703), 0x72 }, { CCI_REG8(0x3709), 0xe6 }, ++ { CCI_REG8(0x3a60), 0x68 }, { CCI_REG8(0x3a6f), 0x68 }, ++ { CCI_REG8(0x3a5e), 0xdc }, { CCI_REG8(0x3a6d), 0xdc }, ++ { CCI_REG8(0x3721), 0xc9 }, { CCI_REG8(0x5250), 0x06 }, ++ { CCI_REG8(0x527a), 0x00 }, { CCI_REG8(0x527b), 0x65 }, ++ { CCI_REG8(0x527c), 0x00 }, { CCI_REG8(0x527d), 0x82 }, ++ { CCI_REG8(0x5280), 0x24 }, { CCI_REG8(0x5281), 0x40 }, ++ { CCI_REG8(0x5282), 0x1b }, { CCI_REG8(0x5283), 0x40 }, ++ { CCI_REG8(0x5284), 0x24 }, { CCI_REG8(0x5285), 0x40 }, ++ { CCI_REG8(0x5286), 0x1b }, { CCI_REG8(0x5287), 0x40 }, ++ { CCI_REG8(0x5200), 0x24 }, { CCI_REG8(0x5201), 0x40 }, ++ { CCI_REG8(0x5202), 0x1b }, { CCI_REG8(0x5203), 0x40 }, ++ { CCI_REG8(0x481b), 0x35 }, { CCI_REG8(0x4862), 0x25 }, ++ { CCI_REG8(0x3400), 0x00 }, { CCI_REG8(0x3421), 0x23 }, ++ { CCI_REG8(0x3422), 0xfc }, { CCI_REG8(0x3423), 0x07 }, ++ { CCI_REG8(0x3424), 0x01 }, { CCI_REG8(0x3425), 0x04 }, ++ { CCI_REG8(0x3426), 0x50 }, { CCI_REG8(0x3427), 0x55 }, ++ { CCI_REG8(0x3428), 0x15 }, { CCI_REG8(0x3429), 0x00 }, ++ { CCI_REG8(0x3025), 0x03 }, { CCI_REG8(0x5250), 0x06 }, ++ { CCI_REG8(0x0305), 0x98 }, { CCI_REG8(0x0306), 0x04 }, ++ { CCI_REG8(0x0345), 0x90 }, { CCI_REG8(0x0307), 0x01 }, ++ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 }, ++ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 }, ++ { CCI_REG8(0x480C), 0x92 }, { CCI_REG8(0x5001), 0x21 }, ++ { CCI_REG8(0x5000), 0x01 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_2312_1736[] = { ++ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x3504), 0x08 }, ++ { CCI_REG8(0x360d), 0x82 }, { CCI_REG8(0x368a), 0x2e }, ++ { CCI_REG8(0x3712), 0x00 }, { CCI_REG8(0x3822), 0x08 }, ++ { CCI_REG8(0x3827), 0x40 }, { CCI_REG8(0x383d), 0x04 }, ++ { CCI_REG8(0x383f), 0x00 }, { CCI_REG8(0x384c), 0x01 }, ++ { CCI_REG8(0x384d), 0x12 }, { CCI_REG8(0x3852), 0x00 }, ++ { CCI_REG8(0x3856), 0x04 }, { CCI_REG8(0x3857), 0x04 }, ++ { CCI_REG8(0x3858), 0x08 }, { CCI_REG8(0x3859), 0x08 }, ++ { CCI_REG8(0x4016), 0x07 }, { CCI_REG8(0x4018), 0x01 }, ++ { CCI_REG8(0x4504), 0x00 }, { CCI_REG8(0x4523), 0x00 }, ++ { CCI_REG8(0x45c0), 0x01 }, { CCI_REG8(0x4641), 0x24 }, ++ { CCI_REG8(0x4643), 0x0c }, { CCI_REG8(0x4837), 0x0b }, ++ { CCI_REG8(0x4915), 0x02 }, { CCI_REG8(0x4916), 0x1d }, ++ { CCI_REG8(0x4a15), 0x02 }, { CCI_REG8(0x4a16), 0x1d }, ++ { CCI_REG8(0x5000), 0x55 }, { CCI_REG8(0x5001), 0x00 }, ++ { CCI_REG8(0x5002), 0x35 }, { CCI_REG8(0x5004), 0xc0 }, ++ { CCI_REG8(0x5068), 0x02 }, { CCI_REG8(0x3703), 0x6a }, ++ { CCI_REG8(0x3709), 0xa3 }, { CCI_REG8(0x3a60), 0x60 }, ++ { CCI_REG8(0x3a6f), 0x60 }, { CCI_REG8(0x3a5e), 0x99 }, ++ { CCI_REG8(0x3a6d), 0x99 }, { CCI_REG8(0x3721), 0xc1 }, ++ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x527a), 0x00 }, ++ { CCI_REG8(0x527b), 0x65 }, { CCI_REG8(0x527c), 0x00 }, ++ { CCI_REG8(0x527d), 0x82 }, { CCI_REG8(0x5280), 0x24 }, ++ { CCI_REG8(0x5281), 0x40 }, { CCI_REG8(0x5282), 0x1b }, ++ { CCI_REG8(0x5283), 0x40 }, { CCI_REG8(0x5284), 0x24 }, ++ { CCI_REG8(0x5285), 0x40 }, { CCI_REG8(0x5286), 0x1b }, ++ { CCI_REG8(0x5287), 0x40 }, { CCI_REG8(0x5200), 0x24 }, ++ { CCI_REG8(0x5201), 0x40 }, { CCI_REG8(0x5202), 0x1b }, ++ { CCI_REG8(0x5203), 0x40 }, { CCI_REG8(0x3684), 0x05 }, ++ { CCI_REG8(0x481b), 0x20 }, { CCI_REG8(0x51b0), 0x38 }, ++ { CCI_REG8(0x51b3), 0x0e }, { CCI_REG8(0x51b5), 0x04 }, ++ { CCI_REG8(0x51b6), 0x00 }, { CCI_REG8(0x51b7), 0x00 }, ++ { CCI_REG8(0x51b9), 0x70 }, { CCI_REG8(0x51bb), 0x10 }, ++ { CCI_REG8(0x51bc), 0x00 }, { CCI_REG8(0x51bd), 0x00 }, ++ { CCI_REG8(0x51b0), 0x38 }, { CCI_REG8(0x54b0), 0x38 }, ++ { CCI_REG8(0x54b3), 0x0e }, { CCI_REG8(0x54b5), 0x04 }, ++ { CCI_REG8(0x54b6), 0x00 }, { CCI_REG8(0x54b7), 0x00 }, ++ { CCI_REG8(0x54b9), 0x70 }, { CCI_REG8(0x54bb), 0x10 }, ++ { CCI_REG8(0x54bc), 0x00 }, { CCI_REG8(0x54bd), 0x00 }, ++ { CCI_REG8(0x57b0), 0x38 }, { CCI_REG8(0x57b3), 0x0e }, ++ { CCI_REG8(0x57b5), 0x04 }, { CCI_REG8(0x57b6), 0x00 }, ++ { CCI_REG8(0x57b7), 0x00 }, { CCI_REG8(0x57b9), 0x70 }, ++ { CCI_REG8(0x57bb), 0x10 }, { CCI_REG8(0x57bc), 0x00 }, ++ { CCI_REG8(0x57bd), 0x00 }, { CCI_REG8(0x0305), 0x98 }, ++ { CCI_REG8(0x0306), 0x04 }, { CCI_REG8(0x0307), 0x01 }, ++ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 }, ++ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 }, ++ { CCI_REG8(0x480C), 0x92 } ++}; ++ ++static const struct cci_reg_sequence ov64a40_1920x1080[] = { ++ { CCI_REG8(0x034b), 0x02 }, { CCI_REG8(0x3504), 0x08 }, ++ { CCI_REG8(0x360d), 0x82 }, { CCI_REG8(0x368a), 0x2e }, ++ { CCI_REG8(0x3712), 0x00 }, { CCI_REG8(0x3822), 0x08 }, ++ { CCI_REG8(0x3827), 0x40 }, { CCI_REG8(0x383d), 0x04 }, ++ { CCI_REG8(0x383f), 0x00 }, { CCI_REG8(0x384c), 0x01 }, ++ { CCI_REG8(0x384d), 0x12 }, { CCI_REG8(0x3852), 0x00 }, ++ { CCI_REG8(0x3856), 0x04 }, { CCI_REG8(0x3857), 0x04 }, ++ { CCI_REG8(0x3858), 0x08 }, { CCI_REG8(0x3859), 0x08 }, ++ { CCI_REG8(0x4016), 0x07 }, { CCI_REG8(0x4018), 0x01 }, ++ { CCI_REG8(0x4504), 0x00 }, { CCI_REG8(0x4523), 0x00 }, ++ { CCI_REG8(0x45c0), 0x01 }, { CCI_REG8(0x4641), 0x24 }, ++ { CCI_REG8(0x4643), 0x0c }, { CCI_REG8(0x4837), 0x0b }, ++ { CCI_REG8(0x4915), 0x02 }, { CCI_REG8(0x4916), 0x1d }, ++ { CCI_REG8(0x4a15), 0x02 }, { CCI_REG8(0x4a16), 0x1d }, ++ { CCI_REG8(0x5000), 0x55 }, { CCI_REG8(0x5001), 0x00 }, ++ { CCI_REG8(0x5002), 0x35 }, { CCI_REG8(0x5004), 0xc0 }, ++ { CCI_REG8(0x5068), 0x02 }, { CCI_REG8(0x3703), 0x6a }, ++ { CCI_REG8(0x3709), 0xa3 }, { CCI_REG8(0x3a60), 0x60 }, ++ { CCI_REG8(0x3a6f), 0x60 }, { CCI_REG8(0x3a5e), 0x99 }, ++ { CCI_REG8(0x3a6d), 0x99 }, { CCI_REG8(0x3721), 0xc1 }, ++ { CCI_REG8(0x5250), 0x06 }, { CCI_REG8(0x527a), 0x00 }, ++ { CCI_REG8(0x527b), 0x65 }, { CCI_REG8(0x527c), 0x00 }, ++ { CCI_REG8(0x527d), 0x82 }, { CCI_REG8(0x5280), 0x24 }, ++ { CCI_REG8(0x5281), 0x40 }, { CCI_REG8(0x5282), 0x1b }, ++ { CCI_REG8(0x5283), 0x40 }, { CCI_REG8(0x5284), 0x24 }, ++ { CCI_REG8(0x5285), 0x40 }, { CCI_REG8(0x5286), 0x1b }, ++ { CCI_REG8(0x5287), 0x40 }, { CCI_REG8(0x5200), 0x24 }, ++ { CCI_REG8(0x5201), 0x40 }, { CCI_REG8(0x5202), 0x1b }, ++ { CCI_REG8(0x5203), 0x40 }, { CCI_REG8(0x3684), 0x05 }, ++ { CCI_REG8(0x481b), 0x20 }, { CCI_REG8(0x51b0), 0x38 }, ++ { CCI_REG8(0x51b3), 0x0e }, { CCI_REG8(0x51b5), 0x04 }, ++ { CCI_REG8(0x51b6), 0x00 }, { CCI_REG8(0x51b7), 0x00 }, ++ { CCI_REG8(0x51b9), 0x70 }, { CCI_REG8(0x51bb), 0x10 }, ++ { CCI_REG8(0x51bc), 0x00 }, { CCI_REG8(0x51bd), 0x00 }, ++ { CCI_REG8(0x51b0), 0x38 }, { CCI_REG8(0x54b0), 0x38 }, ++ { CCI_REG8(0x54b3), 0x0e }, { CCI_REG8(0x54b5), 0x04 }, ++ { CCI_REG8(0x54b6), 0x00 }, { CCI_REG8(0x54b7), 0x00 }, ++ { CCI_REG8(0x54b9), 0x70 }, { CCI_REG8(0x54bb), 0x10 }, ++ { CCI_REG8(0x54bc), 0x00 }, { CCI_REG8(0x54bd), 0x00 }, ++ { CCI_REG8(0x57b0), 0x38 }, { CCI_REG8(0x57b3), 0x0e }, ++ { CCI_REG8(0x57b5), 0x04 }, { CCI_REG8(0x57b6), 0x00 }, ++ { CCI_REG8(0x57b7), 0x00 }, { CCI_REG8(0x57b9), 0x70 }, ++ { CCI_REG8(0x57bb), 0x10 }, { CCI_REG8(0x57bc), 0x00 }, ++ { CCI_REG8(0x57bd), 0x00 }, { CCI_REG8(0x0305), 0x98 }, ++ { CCI_REG8(0x0306), 0x04 }, { CCI_REG8(0x0307), 0x01 }, ++ { CCI_REG8(0x4837), 0x1a }, { CCI_REG8(0x4888), 0x10 }, ++ { CCI_REG8(0x4860), 0x00 }, { CCI_REG8(0x4850), 0x43 }, ++ { CCI_REG8(0x480C), 0x92 } ++}; ++ ++/* 456MHz MIPI link frequency with 24MHz input clock. */ ++static const struct cci_reg_sequence ov64a40_pll_config[] = { ++ { OV64A40_PLL1_PRE_DIV0, 0x88 }, ++ { OV64A40_PLL1_PRE_DIV, 0x02 }, ++ { OV64A40_PLL1_MULTIPLIER, 0x0098 }, ++ { OV64A40_PLL1_M_DIV, 0x01 }, ++ { OV64A40_PLL2_SEL_BAK_SA1, 0x00 }, ++ { OV64A40_PLL2_PRE_DIV, 0x12 }, ++ { OV64A40_PLL2_MULTIPLIER, 0x0190 }, ++ { OV64A40_PLL2_PRE_DIV0, 0xd7 }, ++ { OV64A40_PLL2_DIVSP, 0x00 }, ++ { OV64A40_PLL2_DIVDAC, 0x00 }, ++ { OV64A40_PLL2_DACPREDIV, 0x00 } ++}; ++ ++struct ov64a40_reglist { ++ unsigned int num_regs; ++ const struct cci_reg_sequence *regvals; ++}; ++ ++struct ov64a40_subsampling { ++ unsigned int x_odd_inc; ++ unsigned int x_even_inc; ++ unsigned int y_odd_inc; ++ unsigned int y_even_inc; ++ bool vbin; ++ bool hbin; ++}; ++ ++static struct ov64a40_mode { ++ unsigned int width; ++ unsigned int height; ++ struct ov64a40_timings { ++ unsigned int vts; ++ unsigned int ppl; ++ } timings_default[OV64A40_NUM_LINK_FREQ]; ++ const struct ov64a40_reglist reglist; ++ struct v4l2_rect analogue_crop; ++ struct v4l2_rect digital_crop; ++ struct ov64a40_subsampling subsampling; ++} ov64a40_modes[] = { ++ /* Full resolution */ ++ { ++ .width = 9248, ++ .height = 6944, ++ .timings_default = { ++ /* 2.6 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 7072, ++ .ppl = 4072, ++ }, ++ /* 2 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 7072, ++ .ppl = 5248, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_9248x6944), ++ .regvals = ov64a40_9248x6944, ++ }, ++ .analogue_crop = { ++ .left = 0, ++ .top = 0, ++ .width = 9279, ++ .height = 6975, ++ }, ++ .digital_crop = { ++ .left = 17, ++ .top = 16, ++ .width = 9248, ++ .height = 6944, ++ }, ++ .subsampling = { ++ .x_odd_inc = 1, ++ .x_even_inc = 1, ++ .y_odd_inc = 1, ++ .y_even_inc = 1, ++ .vbin = false, ++ .hbin = false, ++ }, ++ }, ++ /* Analogue crop + digital crop */ ++ { ++ .width = 8000, ++ .height = 6000, ++ .timings_default = { ++ /* 3.0 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 6400, ++ .ppl = 3848, ++ }, ++ /* 2.5 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 6304, ++ .ppl = 4736, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_8000x6000), ++ .regvals = ov64a40_8000x6000, ++ }, ++ .analogue_crop = { ++ .left = 624, ++ .top = 472, ++ .width = 8047, ++ .height = 6031, ++ }, ++ .digital_crop = { ++ .left = 17, ++ .top = 16, ++ .width = 8000, ++ .height = 6000, ++ }, ++ .subsampling = { ++ .x_odd_inc = 1, ++ .x_even_inc = 1, ++ .y_odd_inc = 1, ++ .y_even_inc = 1, ++ .vbin = false, ++ .hbin = false, ++ }, ++ }, ++ /* 2x2 downscaled */ ++ { ++ .width = 4624, ++ .height = 3472, ++ .timings_default = { ++ /* 10 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 3533, ++ .ppl = 2112, ++ }, ++ /* 7 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 3939, ++ .ppl = 2720, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_4624_3472), ++ .regvals = ov64a40_4624_3472, ++ }, ++ .analogue_crop = { ++ .left = 0, ++ .top = 0, ++ .width = 9279, ++ .height = 6975, ++ }, ++ .digital_crop = { ++ .left = 9, ++ .top = 8, ++ .width = 4624, ++ .height = 3472, ++ }, ++ .subsampling = { ++ .x_odd_inc = 3, ++ .x_even_inc = 1, ++ .y_odd_inc = 1, ++ .y_even_inc = 1, ++ .vbin = true, ++ .hbin = false, ++ }, ++ }, ++ /* Analogue crop + 2x2 downscale + digital crop */ ++ { ++ .width = 3840, ++ .height = 2160, ++ .timings_default = { ++ /* 20 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 2218, ++ .ppl = 1690, ++ }, ++ /* 15 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 2270, ++ .ppl = 2202, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_3840x2160), ++ .regvals = ov64a40_3840x2160, ++ }, ++ .analogue_crop = { ++ .left = 784, ++ .top = 1312, ++ .width = 7711, ++ .height = 4351, ++ }, ++ .digital_crop = { ++ .left = 9, ++ .top = 8, ++ .width = 3840, ++ .height = 2160, ++ }, ++ .subsampling = { ++ .x_odd_inc = 3, ++ .x_even_inc = 1, ++ .y_odd_inc = 1, ++ .y_even_inc = 1, ++ .vbin = true, ++ .hbin = false, ++ }, ++ }, ++ /* 4x4 downscaled */ ++ { ++ .width = 2312, ++ .height = 1736, ++ .timings_default = { ++ /* 30 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 1998, ++ .ppl = 1248, ++ }, ++ /* 25 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 1994, ++ .ppl = 1504, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_2312_1736), ++ .regvals = ov64a40_2312_1736, ++ }, ++ .analogue_crop = { ++ .left = 0, ++ .top = 0, ++ .width = 9279, ++ .height = 6975, ++ }, ++ .digital_crop = { ++ .left = 5, ++ .top = 4, ++ .width = 2312, ++ .height = 1736, ++ }, ++ .subsampling = { ++ .x_odd_inc = 3, ++ .x_even_inc = 1, ++ .y_odd_inc = 3, ++ .y_even_inc = 1, ++ .vbin = true, ++ .hbin = true, ++ }, ++ }, ++ /* Analogue crop + 4x4 downscale + digital crop */ ++ { ++ .width = 1920, ++ .height = 1080, ++ .timings_default = { ++ /* 60 FPS */ ++ [OV64A40_LINK_FREQ_456M_ID] = { ++ .vts = 1397, ++ .ppl = 880, ++ }, ++ /* 45 FPS */ ++ [OV64A40_LINK_FREQ_360M_ID] = { ++ .vts = 1216, ++ .ppl = 1360, ++ }, ++ }, ++ .reglist = { ++ .num_regs = ARRAY_SIZE(ov64a40_1920x1080), ++ .regvals = ov64a40_1920x1080, ++ }, ++ .analogue_crop = { ++ .left = 784, ++ .top = 1312, ++ .width = 7711, ++ .height = 4351, ++ }, ++ .digital_crop = { ++ .left = 7, ++ .top = 6, ++ .width = 1920, ++ .height = 1080, ++ }, ++ .subsampling = { ++ .x_odd_inc = 3, ++ .x_even_inc = 1, ++ .y_odd_inc = 3, ++ .y_even_inc = 1, ++ .vbin = true, ++ .hbin = true, ++ }, ++ }, ++}; ++ ++struct ov64a40 { ++ struct device *dev; ++ ++ struct v4l2_subdev sd; ++ struct media_pad pad; ++ ++ struct regmap *cci; ++ ++ struct ov64a40_mode *mode; ++ ++ struct clk *xclk; ++ ++ struct gpio_desc *reset_gpio; ++ struct regulator_bulk_data supplies[ARRAY_SIZE(ov64a40_supply_names)]; ++ ++ s64 *link_frequencies; ++ unsigned int num_link_frequencies; ++ ++ struct v4l2_ctrl_handler ctrl_handler; ++ struct v4l2_ctrl *exposure; ++ struct v4l2_ctrl *link_freq; ++ struct v4l2_ctrl *vblank; ++ struct v4l2_ctrl *hblank; ++ struct v4l2_ctrl *vflip; ++ struct v4l2_ctrl *hflip; ++}; ++ ++static inline struct ov64a40 *sd_to_ov64a40(struct v4l2_subdev *sd) ++{ ++ return container_of(sd, struct ov64a40, sd); ++} ++ ++static const struct ov64a40_timings * ++ov64a40_get_timings(struct ov64a40 *ov64a40, unsigned int link_freq_index) ++{ ++ s64 link_freq = ov64a40->link_frequencies[link_freq_index]; ++ unsigned int timings_index = link_freq == OV64A40_LINK_FREQ_360M ++ ? OV64A40_LINK_FREQ_360M_ID ++ : OV64A40_LINK_FREQ_456M_ID; ++ ++ return &ov64a40->mode->timings_default[timings_index]; ++} ++ ++static int ov64a40_program_geometry(struct ov64a40 *ov64a40) ++{ ++ struct ov64a40_mode *mode = ov64a40->mode; ++ struct v4l2_rect *anacrop = &mode->analogue_crop; ++ struct v4l2_rect *digicrop = &mode->digital_crop; ++ const struct ov64a40_timings *timings; ++ int ret = 0; ++ ++ /* Analogue crop. */ ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL0, ++ anacrop->left, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL2, ++ anacrop->top, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL4, ++ anacrop->width + anacrop->left, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL6, ++ anacrop->height + anacrop->top, &ret); ++ ++ /* ISP windowing. */ ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL10, ++ digicrop->left, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL12, ++ digicrop->top, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL8, ++ digicrop->width, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLA, ++ digicrop->height, &ret); ++ ++ /* Total timings. */ ++ timings = ov64a40_get_timings(ov64a40, ov64a40->link_freq->cur.val); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLC, timings->ppl, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRLE, timings->vts, &ret); ++ ++ return ret; ++} ++ ++static int ov64a40_program_subsampling(struct ov64a40 *ov64a40) ++{ ++ struct ov64a40_subsampling *subsampling = &ov64a40->mode->subsampling; ++ int ret = 0; ++ ++ /* Skipping configuration */ ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL14, ++ OV64A40_SKIPPING_CONFIG(subsampling->x_odd_inc, ++ subsampling->x_even_inc), &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMING_CTRL15, ++ OV64A40_SKIPPING_CONFIG(subsampling->y_odd_inc, ++ subsampling->y_even_inc), &ret); ++ ++ /* Binning configuration */ ++ cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_20, ++ OV64A40_TIMING_CTRL_20_VBIN, ++ subsampling->vbin ? OV64A40_TIMING_CTRL_20_VBIN : 0, ++ &ret); ++ cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_21, ++ OV64A40_TIMING_CTRL_21_HBIN_CONF, ++ subsampling->hbin ? ++ OV64A40_TIMING_CTRL_21_HBIN_CONF : 0, &ret); ++ ++ return ret; ++} ++ ++static int ov64a40_start_streaming(struct ov64a40 *ov64a40, ++ struct v4l2_subdev_state *state) ++{ ++ const struct ov64a40_reglist *reglist = &ov64a40->mode->reglist; ++ const struct ov64a40_timings *timings; ++ unsigned long delay; ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(ov64a40->dev); ++ if (ret < 0) ++ return ret; ++ ++ ret = cci_multi_reg_write(ov64a40->cci, ov64a40_init, ++ ARRAY_SIZE(ov64a40_init), NULL); ++ if (ret) ++ goto error_power_off; ++ ++ ret = cci_multi_reg_write(ov64a40->cci, reglist->regvals, ++ reglist->num_regs, NULL); ++ if (ret) ++ goto error_power_off; ++ ++ ret = ov64a40_program_geometry(ov64a40); ++ if (ret) ++ goto error_power_off; ++ ++ ret = ov64a40_program_subsampling(ov64a40); ++ if (ret) ++ goto error_power_off; ++ ++ ret = __v4l2_ctrl_handler_setup(&ov64a40->ctrl_handler); ++ if (ret) ++ goto error_power_off; ++ ++ ret = cci_write(ov64a40->cci, OV64A40_REG_SMIA, ++ OV64A40_REG_SMIA_STREAMING, NULL); ++ if (ret) ++ goto error_power_off; ++ ++ /* Link frequency and flips cannot change while streaming. */ ++ __v4l2_ctrl_grab(ov64a40->link_freq, true); ++ __v4l2_ctrl_grab(ov64a40->vflip, true); ++ __v4l2_ctrl_grab(ov64a40->hflip, true); ++ ++ /* delay: max(4096 xclk pulses, 150usec) + exposure time */ ++ timings = ov64a40_get_timings(ov64a40, ov64a40->link_freq->cur.val); ++ delay = DIV_ROUND_UP(4096, OV64A40_XCLK_FREQ / 1000 / 1000); ++ delay = max(delay, 150ul); ++ ++ /* The sensor has an internal x4 multiplier on the line length. */ ++ delay += DIV_ROUND_UP(timings->ppl * 4 * ov64a40->exposure->cur.val, ++ OV64A40_PIXEL_RATE / 1000 / 1000); ++ fsleep(delay); ++ ++ return 0; ++ ++error_power_off: ++ pm_runtime_mark_last_busy(ov64a40->dev); ++ pm_runtime_put_autosuspend(ov64a40->dev); ++ ++ return ret; ++} ++ ++static int ov64a40_stop_streaming(struct ov64a40 *ov64a40, ++ struct v4l2_subdev_state *state) ++{ ++ cci_update_bits(ov64a40->cci, OV64A40_REG_SMIA, BIT(0), 0, NULL); ++ pm_runtime_mark_last_busy(ov64a40->dev); ++ pm_runtime_put_autosuspend(ov64a40->dev); ++ ++ __v4l2_ctrl_grab(ov64a40->link_freq, false); ++ __v4l2_ctrl_grab(ov64a40->vflip, false); ++ __v4l2_ctrl_grab(ov64a40->hflip, false); ++ ++ return 0; ++} ++ ++static int ov64a40_set_stream(struct v4l2_subdev *sd, int enable) ++{ ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ struct v4l2_subdev_state *state; ++ int ret; ++ ++ state = v4l2_subdev_lock_and_get_active_state(sd); ++ if (enable) ++ ret = ov64a40_start_streaming(ov64a40, state); ++ else ++ ret = ov64a40_stop_streaming(ov64a40, state); ++ v4l2_subdev_unlock_state(state); ++ ++ return ret; ++} ++ ++static const struct v4l2_subdev_video_ops ov64a40_video_ops = { ++ .s_stream = ov64a40_set_stream, ++}; ++ ++static u32 ov64a40_mbus_code(struct ov64a40 *ov64a40) ++{ ++ unsigned int index = ov64a40->hflip->val << 1 | ov64a40->vflip->val; ++ ++ return ov64a40_mbus_codes[index]; ++} ++ ++static void ov64a40_update_pad_fmt(struct ov64a40 *ov64a40, ++ struct ov64a40_mode *mode, ++ struct v4l2_mbus_framefmt *fmt) ++{ ++ fmt->code = ov64a40_mbus_code(ov64a40); ++ fmt->width = mode->width; ++ fmt->height = mode->height; ++ fmt->field = V4L2_FIELD_NONE; ++ fmt->colorspace = V4L2_COLORSPACE_RAW; ++ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; ++ fmt->xfer_func = V4L2_XFER_FUNC_NONE; ++ fmt->ycbcr_enc = V4L2_YCBCR_ENC_601; ++} ++ ++static int ov64a40_init_cfg(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state) ++{ ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ struct v4l2_mbus_framefmt *format; ++ struct v4l2_rect *crop; ++ ++ format = v4l2_subdev_get_pad_format(sd, state, 0); ++ ov64a40_update_pad_fmt(ov64a40, &ov64a40_modes[0], format); ++ ++ crop = v4l2_subdev_get_pad_crop(sd, state, 0); ++ crop->top = OV64A40_PIXEL_ARRAY_TOP; ++ crop->left = OV64A40_PIXEL_ARRAY_LEFT; ++ crop->width = OV64A40_PIXEL_ARRAY_WIDTH; ++ crop->height = OV64A40_PIXEL_ARRAY_HEIGHT; ++ ++ return 0; ++} ++ ++static int ov64a40_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ ++ if (code->index) ++ return -EINVAL; ++ ++ code->code = ov64a40_mbus_code(ov64a40); ++ ++ return 0; ++} ++ ++static int ov64a40_enum_frame_size(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_frame_size_enum *fse) ++{ ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ struct ov64a40_mode *mode; ++ u32 code; ++ ++ if (fse->index >= ARRAY_SIZE(ov64a40_modes)) ++ return -EINVAL; ++ ++ code = ov64a40_mbus_code(ov64a40); ++ if (fse->code != code) ++ return -EINVAL; ++ ++ mode = &ov64a40_modes[fse->index]; ++ fse->min_width = mode->width; ++ fse->max_width = mode->width; ++ fse->min_height = mode->height; ++ fse->max_height = mode->height; ++ ++ return 0; ++} ++ ++static int ov64a40_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_selection *sel) ++{ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP: ++ sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0); ++ ++ return 0; ++ ++ case V4L2_SEL_TGT_NATIVE_SIZE: ++ sel->r.top = 0; ++ sel->r.left = 0; ++ sel->r.width = OV64A40_NATIVE_WIDTH; ++ sel->r.height = OV64A40_NATIVE_HEIGHT; ++ ++ return 0; ++ ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.top = OV64A40_PIXEL_ARRAY_TOP; ++ sel->r.left = OV64A40_PIXEL_ARRAY_LEFT; ++ sel->r.width = OV64A40_PIXEL_ARRAY_WIDTH; ++ sel->r.height = OV64A40_PIXEL_ARRAY_HEIGHT; ++ ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static int ov64a40_set_format(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_format *fmt) ++{ ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ struct v4l2_mbus_framefmt *format; ++ struct ov64a40_mode *mode; ++ ++ mode = v4l2_find_nearest_size(ov64a40_modes, ++ ARRAY_SIZE(ov64a40_modes), ++ width, height, ++ fmt->format.width, fmt->format.height); ++ ++ ov64a40_update_pad_fmt(ov64a40, mode, &fmt->format); ++ ++ format = v4l2_subdev_get_pad_format(sd, sd_state, 0); ++ if (ov64a40->mode == mode && format->code == fmt->format.code) ++ return 0; ++ ++ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { ++ const struct ov64a40_timings *timings; ++ int vblank_max, vblank_def; ++ int hblank_val; ++ int exp_max; ++ ++ ov64a40->mode = mode; ++ *v4l2_subdev_get_pad_crop(sd, sd_state, 0) = mode->analogue_crop; ++ ++ /* Update control limits according to the new mode. */ ++ timings = ov64a40_get_timings(ov64a40, ++ ov64a40->link_freq->cur.val); ++ vblank_max = OV64A40_VTS_MAX - mode->height; ++ vblank_def = timings->vts - mode->height; ++ __v4l2_ctrl_modify_range(ov64a40->vblank, OV64A40_VBLANK_MIN, ++ vblank_max, 1, vblank_def); ++ __v4l2_ctrl_s_ctrl(ov64a40->vblank, vblank_def); ++ ++ exp_max = timings->vts - OV64A40_EXPOSURE_MARGIN; ++ __v4l2_ctrl_modify_range(ov64a40->exposure, ++ OV64A40_EXPOSURE_MIN, exp_max, ++ 1, OV64A40_EXPOSURE_MIN); ++ ++ hblank_val = timings->ppl * 4 - mode->width; ++ __v4l2_ctrl_modify_range(ov64a40->hblank, ++ hblank_val, hblank_val, 1, hblank_val); ++ } ++ ++ *format = fmt->format; ++ ++ return 0; ++} ++ ++static const struct v4l2_subdev_pad_ops ov64a40_pad_ops = { ++ .init_cfg = ov64a40_init_cfg, ++ .enum_mbus_code = ov64a40_enum_mbus_code, ++ .enum_frame_size = ov64a40_enum_frame_size, ++ .get_fmt = v4l2_subdev_get_fmt, ++ .set_fmt = ov64a40_set_format, ++ .get_selection = ov64a40_get_selection, ++}; ++ ++static const struct v4l2_subdev_core_ops ov64a40_core_ops = { ++ .subscribe_event = v4l2_ctrl_subdev_subscribe_event, ++ .unsubscribe_event = v4l2_event_subdev_unsubscribe, ++}; ++ ++static const struct v4l2_subdev_ops ov64a40_subdev_ops = { ++ .core = &ov64a40_core_ops, ++ .video = &ov64a40_video_ops, ++ .pad = &ov64a40_pad_ops, ++}; ++ ++static int ov64a40_power_on(struct device *dev) ++{ ++ struct v4l2_subdev *sd = dev_get_drvdata(dev); ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ int ret; ++ ++ ret = clk_prepare_enable(ov64a40->xclk); ++ if (ret) ++ return ret; ++ ++ ret = regulator_bulk_enable(ARRAY_SIZE(ov64a40_supply_names), ++ ov64a40->supplies); ++ if (ret) { ++ clk_disable_unprepare(ov64a40->xclk); ++ dev_err(dev, "Failed to enable regulators: %d\n", ret); ++ return ret; ++ } ++ ++ gpiod_set_value_cansleep(ov64a40->reset_gpio, 0); ++ ++ fsleep(5000); ++ ++ return 0; ++} ++ ++static int ov64a40_power_off(struct device *dev) ++{ ++ struct v4l2_subdev *sd = dev_get_drvdata(dev); ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ ++ gpiod_set_value_cansleep(ov64a40->reset_gpio, 1); ++ regulator_bulk_disable(ARRAY_SIZE(ov64a40_supply_names), ++ ov64a40->supplies); ++ clk_disable_unprepare(ov64a40->xclk); ++ ++ return 0; ++} ++ ++static int ov64a40_link_freq_config(struct ov64a40 *ov64a40, int link_freq_id) ++{ ++ s64 link_frequency; ++ int ret = 0; ++ ++ /* Default 456MHz with 24MHz input clock. */ ++ cci_multi_reg_write(ov64a40->cci, ov64a40_pll_config, ++ ARRAY_SIZE(ov64a40_pll_config), &ret); ++ ++ /* Decrease the PLL1 multiplier to obtain 360MHz mipi link frequency. */ ++ link_frequency = ov64a40->link_frequencies[link_freq_id]; ++ if (link_frequency == OV64A40_LINK_FREQ_360M) ++ cci_write(ov64a40->cci, OV64A40_PLL1_MULTIPLIER, 0x0078, &ret); ++ ++ return ret; ++} ++ ++static int ov64a40_set_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct ov64a40 *ov64a40 = container_of(ctrl->handler, struct ov64a40, ++ ctrl_handler); ++ int pm_status; ++ int ret = 0; ++ ++ if (ctrl->id == V4L2_CID_VBLANK) { ++ int exp_max = ov64a40->mode->height + ctrl->val ++ - OV64A40_EXPOSURE_MARGIN; ++ int exp_val = min(ov64a40->exposure->cur.val, exp_max); ++ ++ __v4l2_ctrl_modify_range(ov64a40->exposure, ++ ov64a40->exposure->minimum, ++ exp_max, 1, exp_val); ++ } ++ ++ pm_status = pm_runtime_get_if_active(ov64a40->dev, true); ++ if (!pm_status) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_EXPOSURE: ++ ret = cci_write(ov64a40->cci, OV64A40_REG_MEC_LONG_EXPO, ++ ctrl->val, NULL); ++ break; ++ case V4L2_CID_ANALOGUE_GAIN: ++ ret = cci_write(ov64a40->cci, OV64A40_REG_MEC_LONG_GAIN, ++ ctrl->val << 1, NULL); ++ break; ++ case V4L2_CID_VBLANK: { ++ int vts = ctrl->val + ov64a40->mode->height; ++ ++ cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_LOW, vts, &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_MID, ++ (vts >> 8), &ret); ++ cci_write(ov64a40->cci, OV64A40_REG_TIMINGS_VTS_HIGH, ++ (vts >> 16), &ret); ++ break; ++ } ++ case V4L2_CID_VFLIP: ++ ret = cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_20, ++ OV64A40_TIMING_CTRL_20_VFLIP, ++ ctrl->val << 2, ++ NULL); ++ break; ++ case V4L2_CID_HFLIP: ++ ret = cci_update_bits(ov64a40->cci, OV64A40_REG_TIMING_CTRL_21, ++ OV64A40_TIMING_CTRL_21_HFLIP, ++ ctrl->val ? 0 ++ : OV64A40_TIMING_CTRL_21_HFLIP, ++ NULL); ++ break; ++ case V4L2_CID_TEST_PATTERN: ++ ret = cci_write(ov64a40->cci, OV64A40_REG_TEST_PATTERN, ++ ov64a40_test_pattern_val[ctrl->val], NULL); ++ break; ++ case V4L2_CID_LINK_FREQ: ++ ret = ov64a40_link_freq_config(ov64a40, ctrl->val); ++ break; ++ default: ++ dev_err(ov64a40->dev, "Unhandled control: %#x\n", ctrl->id); ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (pm_status > 0) { ++ pm_runtime_mark_last_busy(ov64a40->dev); ++ pm_runtime_put_autosuspend(ov64a40->dev); ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov64a40_ctrl_ops = { ++ .s_ctrl = ov64a40_set_ctrl, ++}; ++ ++static int ov64a40_init_controls(struct ov64a40 *ov64a40) ++{ ++ int exp_max, hblank_val, vblank_max, vblank_def; ++ struct v4l2_ctrl_handler *hdlr = &ov64a40->ctrl_handler; ++ struct v4l2_fwnode_device_properties props; ++ const struct ov64a40_timings *timings; ++ int ret; ++ ++ ret = v4l2_ctrl_handler_init(hdlr, 11); ++ if (ret) ++ return ret; ++ ++ v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, V4L2_CID_PIXEL_RATE, ++ OV64A40_PIXEL_RATE, OV64A40_PIXEL_RATE, 1, ++ OV64A40_PIXEL_RATE); ++ ++ ov64a40->link_freq = ++ v4l2_ctrl_new_int_menu(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_LINK_FREQ, ++ ov64a40->num_link_frequencies - 1, ++ 0, ov64a40->link_frequencies); ++ ++ v4l2_ctrl_new_std_menu_items(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_TEST_PATTERN, ++ ARRAY_SIZE(ov64a40_test_pattern_menu) - 1, ++ 0, 0, ov64a40_test_pattern_menu); ++ ++ timings = ov64a40_get_timings(ov64a40, 0); ++ exp_max = timings->vts - OV64A40_EXPOSURE_MARGIN; ++ ov64a40->exposure = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_EXPOSURE, ++ OV64A40_EXPOSURE_MIN, exp_max, 1, ++ OV64A40_EXPOSURE_MIN); ++ ++ hblank_val = timings->ppl * 4 - ov64a40->mode->width; ++ ov64a40->hblank = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_HBLANK, hblank_val, ++ hblank_val, 1, hblank_val); ++ if (ov64a40->hblank) ++ ov64a40->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ ++ vblank_def = timings->vts - ov64a40->mode->height; ++ vblank_max = OV64A40_VTS_MAX - ov64a40->mode->height; ++ ov64a40->vblank = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_VBLANK, OV64A40_VBLANK_MIN, ++ vblank_max, 1, vblank_def); ++ ++ v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, ++ OV64A40_ANA_GAIN_MIN, OV64A40_ANA_GAIN_MAX, 1, ++ OV64A40_ANA_GAIN_DEFAULT); ++ ++ ov64a40->hflip = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ if (ov64a40->hflip) ++ ov64a40->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; ++ ++ ov64a40->vflip = v4l2_ctrl_new_std(hdlr, &ov64a40_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ if (ov64a40->vflip) ++ ov64a40->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; ++ ++ if (hdlr->error) { ++ ret = hdlr->error; ++ dev_err(ov64a40->dev, "control init failed: %d\n", ret); ++ goto error_free_hdlr; ++ } ++ ++ ret = v4l2_fwnode_device_parse(ov64a40->dev, &props); ++ if (ret) ++ goto error_free_hdlr; ++ ++ ret = v4l2_ctrl_new_fwnode_properties(hdlr, &ov64a40_ctrl_ops, ++ &props); ++ if (ret) ++ goto error_free_hdlr; ++ ++ ov64a40->sd.ctrl_handler = hdlr; ++ ++ return 0; ++ ++error_free_hdlr: ++ v4l2_ctrl_handler_free(hdlr); ++ return ret; ++} ++ ++static int ov64a40_identify(struct ov64a40 *ov64a40) ++{ ++ int ret; ++ u64 id; ++ ++ ret = cci_read(ov64a40->cci, OV64A40_REG_CHIP_ID, &id, NULL); ++ if (ret) { ++ dev_err(ov64a40->dev, "Failed to read chip id: %d\n", ret); ++ return ret; ++ } ++ ++ if (id != OV64A40_CHIP_ID) { ++ dev_err(ov64a40->dev, "chip id mismatch: %#llx\n", id); ++ return -ENODEV; ++ } ++ ++ dev_dbg(ov64a40->dev, "OV64A40 chip identified: %#llx\n", id); ++ ++ return 0; ++} ++ ++static int ov64a40_parse_dt(struct ov64a40 *ov64a40) ++{ ++ struct v4l2_fwnode_endpoint v4l2_fwnode = { ++ .bus_type = V4L2_MBUS_CSI2_DPHY ++ }; ++ struct fwnode_handle *endpoint; ++ int ret = -EINVAL; ++ unsigned int i; ++ ++ endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(ov64a40->dev), ++ NULL); ++ if (!endpoint) { ++ dev_err(ov64a40->dev, "Failed to find endpoint\n"); ++ return -EINVAL; ++ } ++ ++ if (v4l2_fwnode_endpoint_alloc_parse(endpoint, &v4l2_fwnode)) { ++ dev_err(ov64a40->dev, "Failed to parse endpoint\n"); ++ goto error_put_fwnode; ++ ++ } ++ ++ if (v4l2_fwnode.bus.mipi_csi2.num_data_lanes != 2) { ++ dev_err(ov64a40->dev, "Unsupported number of data lanes: %u\n", ++ v4l2_fwnode.bus.mipi_csi2.num_data_lanes); ++ goto error_free_fwnode; ++ } ++ ++ if (!v4l2_fwnode.nr_of_link_frequencies) { ++ dev_warn(ov64a40->dev, "no link frequencies defined\n"); ++ goto error_free_fwnode; ++ } ++ ++ if (v4l2_fwnode.nr_of_link_frequencies > 2) { ++ dev_warn(ov64a40->dev, ++ "Unsupported number of link frequencies\n"); ++ goto error_free_fwnode; ++ } ++ ++ ov64a40->link_frequencies = ++ devm_kcalloc(ov64a40->dev, v4l2_fwnode.nr_of_link_frequencies, ++ sizeof(v4l2_fwnode.link_frequencies[0]), ++ GFP_KERNEL); ++ if (!ov64a40->link_frequencies) { ++ ret = -ENOMEM; ++ goto error_free_fwnode; ++ } ++ ov64a40->num_link_frequencies = v4l2_fwnode.nr_of_link_frequencies; ++ ++ for (i = 0; i < v4l2_fwnode.nr_of_link_frequencies; ++i) { ++ if (v4l2_fwnode.link_frequencies[i] != OV64A40_LINK_FREQ_360M && ++ v4l2_fwnode.link_frequencies[i] != OV64A40_LINK_FREQ_456M) { ++ dev_err(ov64a40->dev, ++ "Unsupported link frequency %lld\n", ++ v4l2_fwnode.link_frequencies[i]); ++ goto error_free_fwnode; ++ } ++ ++ ov64a40->link_frequencies[i] = v4l2_fwnode.link_frequencies[i]; ++ } ++ ++ v4l2_fwnode_endpoint_free(&v4l2_fwnode); ++ ++ /* Register the subdev on the endpoint, so don't put it yet. */ ++ ov64a40->sd.fwnode = endpoint; ++ ++ return 0; ++ ++error_free_fwnode: ++ v4l2_fwnode_endpoint_free(&v4l2_fwnode); ++error_put_fwnode: ++ fwnode_handle_put(endpoint); ++ return ret; ++} ++ ++static int ov64a40_get_regulators(struct ov64a40 *ov64a40) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&ov64a40->sd); ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ov64a40_supply_names); i++) ++ ov64a40->supplies[i].supply = ov64a40_supply_names[i]; ++ ++ return devm_regulator_bulk_get(&client->dev, ++ ARRAY_SIZE(ov64a40_supply_names), ++ ov64a40->supplies); ++} ++ ++static int ov64a40_probe(struct i2c_client *client) ++{ ++ struct ov64a40 *ov64a40; ++ u32 xclk_freq; ++ int ret; ++ ++ ov64a40 = devm_kzalloc(&client->dev, sizeof(*ov64a40), GFP_KERNEL); ++ if (!ov64a40) ++ return -ENOMEM; ++ ++ ov64a40->dev = &client->dev; ++ v4l2_i2c_subdev_init(&ov64a40->sd, client, &ov64a40_subdev_ops); ++ ++ ov64a40->cci = devm_cci_regmap_init_i2c(client, 16); ++ if (IS_ERR(ov64a40->cci)) { ++ dev_err(&client->dev, "Failed to initialize CCI\n"); ++ return PTR_ERR(ov64a40->cci); ++ } ++ ++ ov64a40->xclk = devm_clk_get(&client->dev, NULL); ++ if (!ov64a40->xclk) ++ return dev_err_probe(&client->dev, PTR_ERR(ov64a40->xclk), ++ "Failed to get clock\n"); ++ ++ xclk_freq = clk_get_rate(ov64a40->xclk); ++ if (xclk_freq != OV64A40_XCLK_FREQ) { ++ dev_err(&client->dev, "Unsupported xclk frequency %u\n", ++ xclk_freq); ++ return -EINVAL; ++ } ++ ++ ret = ov64a40_get_regulators(ov64a40); ++ if (ret) ++ return ret; ++ ++ ov64a40->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", ++ GPIOD_OUT_LOW); ++ if (IS_ERR(ov64a40->reset_gpio)) ++ return dev_err_probe(&client->dev, PTR_ERR(ov64a40->reset_gpio), ++ "Failed to get reset gpio\n"); ++ ++ ret = ov64a40_parse_dt(ov64a40); ++ if (ret) ++ return ret; ++ ++ ret = ov64a40_power_on(&client->dev); ++ if (ret) ++ goto error_put_fwnode; ++ ++ ret = ov64a40_identify(ov64a40); ++ if (ret) ++ goto error_poweroff; ++ ++ ov64a40->mode = &ov64a40_modes[0]; ++ ++ pm_runtime_set_active(&client->dev); ++ pm_runtime_get_noresume(&client->dev); ++ pm_runtime_enable(&client->dev); ++ pm_runtime_set_autosuspend_delay(&client->dev, 1000); ++ pm_runtime_use_autosuspend(&client->dev); ++ ++ ret = ov64a40_init_controls(ov64a40); ++ if (ret) ++ goto error_poweroff; ++ ++ /* Initialize subdev */ ++ ov64a40->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE ++ | V4L2_SUBDEV_FL_HAS_EVENTS; ++ ov64a40->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; ++ ++ ov64a40->pad.flags = MEDIA_PAD_FL_SOURCE; ++ ret = media_entity_pads_init(&ov64a40->sd.entity, 1, &ov64a40->pad); ++ if (ret) { ++ dev_err(&client->dev, "failed to init entity pads: %d\n", ret); ++ goto error_handler_free; ++ } ++ ++ ov64a40->sd.state_lock = ov64a40->ctrl_handler.lock; ++ ret = v4l2_subdev_init_finalize(&ov64a40->sd); ++ if (ret < 0) { ++ dev_err(&client->dev, "subdev init error: %d\n", ret); ++ goto error_media_entity; ++ } ++ ++ ret = v4l2_async_register_subdev_sensor(&ov64a40->sd); ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "failed to register sensor sub-device: %d\n", ret); ++ goto error_subdev_cleanup; ++ } ++ ++ pm_runtime_mark_last_busy(&client->dev); ++ pm_runtime_put_autosuspend(&client->dev); ++ ++ return 0; ++ ++error_subdev_cleanup: ++ v4l2_subdev_cleanup(&ov64a40->sd); ++error_media_entity: ++ media_entity_cleanup(&ov64a40->sd.entity); ++error_handler_free: ++ v4l2_ctrl_handler_free(ov64a40->sd.ctrl_handler); ++error_poweroff: ++ ov64a40_power_off(&client->dev); ++ pm_runtime_set_suspended(&client->dev); ++error_put_fwnode: ++ fwnode_handle_put(ov64a40->sd.fwnode); ++ ++ return ret; ++} ++ ++static void ov64a40_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct ov64a40 *ov64a40 = sd_to_ov64a40(sd); ++ ++ v4l2_async_unregister_subdev(sd); ++ fwnode_handle_put(ov64a40->sd.fwnode); ++ v4l2_subdev_cleanup(sd); ++ media_entity_cleanup(&sd->entity); ++ v4l2_ctrl_handler_free(sd->ctrl_handler); ++ ++ pm_runtime_disable(&client->dev); ++ if (!pm_runtime_status_suspended(&client->dev)) ++ ov64a40_power_off(&client->dev); ++ pm_runtime_set_suspended(&client->dev); ++} ++ ++static const struct of_device_id ov64a40_of_ids[] = { ++ { .compatible = "ovti,ov64a40" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, ov64a40_of_ids); ++ ++static const struct dev_pm_ops ov64a40_pm_ops = { ++ SET_RUNTIME_PM_OPS(ov64a40_power_off, ov64a40_power_on, NULL) ++}; ++ ++static struct i2c_driver ov64a40_i2c_driver = { ++ .driver = { ++ .name = "ov64a40", ++ .of_match_table = ov64a40_of_ids, ++ .pm = &ov64a40_pm_ops, ++ }, ++ .probe_new = ov64a40_probe, ++ .remove = ov64a40_remove, ++}; ++ ++module_i2c_driver(ov64a40_i2c_driver); ++ ++MODULE_AUTHOR("Jacopo Mondi "); ++MODULE_DESCRIPTION("OmniVision OV64A40 sensor driver"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/bcm27xx/patches-6.1/950-1196-media-i2c-Add-ROHM-BU64754-Camera-Autofocus-Actuator.patch b/target/linux/bcm27xx/patches-6.1/950-1196-media-i2c-Add-ROHM-BU64754-Camera-Autofocus-Actuator.patch new file mode 100644 index 0000000000..a50617ee56 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1196-media-i2c-Add-ROHM-BU64754-Camera-Autofocus-Actuator.patch @@ -0,0 +1,368 @@ +From 97ec6aeb265df0bfe7193f00c249b38873fb0fb7 Mon Sep 17 00:00:00 2001 +From: Kieran Bingham +Date: Wed, 13 Sep 2023 17:53:54 +0100 +Subject: [PATCH] media: i2c: Add ROHM BU64754 Camera Autofocus Actuator + +Add support for the ROHM BU64754 Motor Driver for Camera Autofocus. A +V4L2 Subdevice is registered and provides a single +V4L2_CID_FOCUS_ABSOLUTE control. + +Signed-off-by: Kieran Bingham +Signed-off-by: Jacopo Mondi +--- + drivers/media/i2c/Kconfig | 13 ++ + drivers/media/i2c/Makefile | 1 + + drivers/media/i2c/bu64754.c | 315 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 329 insertions(+) + create mode 100644 drivers/media/i2c/bu64754.c + +--- a/drivers/media/i2c/Kconfig ++++ b/drivers/media/i2c/Kconfig +@@ -917,6 +917,19 @@ config VIDEO_AK7375 + capability. This is designed for linear control of + voice coil motors, controlled via I2C serial interface. + ++config VIDEO_BU64754 ++ tristate "BU64754 Motor Driver for Camera Autofocus" ++ depends on I2C && VIDEO_DEV ++ select MEDIA_CONTROLLER ++ select VIDEO_V4L2_SUBDEV_API ++ select V4L2_ASYNC ++ select V4L2_CCI_I2C ++ help ++ This is a driver for the BU64754 Motor Driver for Camera ++ Autofocus. The BU64754GWZ is an actuator driver IC which ++ can be controlled the actuator position precisely using ++ with internal Hall Sensor. ++ + config VIDEO_DW9714 + tristate "DW9714 lens voice coil support" + depends on I2C && VIDEO_DEV +--- a/drivers/media/i2c/Makefile ++++ b/drivers/media/i2c/Makefile +@@ -26,6 +26,7 @@ obj-$(CONFIG_VIDEO_ARDUCAM_PIVARIETY) += + obj-$(CONFIG_VIDEO_BT819) += bt819.o + obj-$(CONFIG_VIDEO_BT856) += bt856.o + obj-$(CONFIG_VIDEO_BT866) += bt866.o ++obj-$(CONFIG_VIDEO_BU64754) += bu64754.o + obj-$(CONFIG_VIDEO_CCS) += ccs/ + obj-$(CONFIG_VIDEO_CCS_PLL) += ccs-pll.o + obj-$(CONFIG_VIDEO_CS3308) += cs3308.o +--- /dev/null ++++ b/drivers/media/i2c/bu64754.c +@@ -0,0 +1,315 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * The BU64754GWZ is an actuator driver IC which can control the ++ * actuator position precisely using an internal Hall Sensor. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define BU64754_REG_ACTIVE CCI_REG16(0x07) ++#define BU64754_ACTIVE_MODE 0x8080 ++ ++#define BU64754_REG_SERVE CCI_REG16(0xd9) ++#define BU64754_SERVE_ON 0x0404 ++ ++#define BU64754_REG_POSITION CCI_REG16(0x45) ++#define BU64753_POSITION_MAX 1023 /* 0x3ff */ ++#define BU64753_POSITION_STEPS 1 ++ ++#define BU64754_POWER_ON_DELAY 800 /* uS : t1, t3 */ ++ ++struct bu64754 { ++ struct device *dev; ++ ++ struct v4l2_ctrl_handler ctrls_vcm; ++ struct v4l2_subdev sd; ++ struct regmap *cci; ++ ++ u16 current_val; ++ struct regulator *vdd; ++ struct notifier_block notifier; ++}; ++ ++static inline struct bu64754 *sd_to_bu64754(struct v4l2_subdev *subdev) ++{ ++ return container_of(subdev, struct bu64754, sd); ++} ++ ++static int bu64754_set(struct bu64754 *bu64754, u16 position) ++{ ++ int ret; ++ ++ position &= 0x3ff; /* BU64753_POSITION_MAX */ ++ ret = cci_write(bu64754->cci, BU64754_REG_POSITION, position, NULL); ++ if (ret) { ++ dev_err(bu64754->dev, "Set position failed ret=%d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int bu64754_active(struct bu64754 *bu64754) ++{ ++ int ret; ++ ++ /* Power on */ ++ ret = cci_write(bu64754->cci, BU64754_REG_ACTIVE, BU64754_ACTIVE_MODE, NULL); ++ if (ret < 0) { ++ dev_err(bu64754->dev, "Failed to set active mode ret = %d\n", ++ ret); ++ return ret; ++ } ++ ++ /* Serve on */ ++ ret = cci_write(bu64754->cci, BU64754_REG_SERVE, BU64754_SERVE_ON, NULL); ++ if (ret < 0) { ++ dev_err(bu64754->dev, "Failed to enable serve ret = %d\n", ++ ret); ++ return ret; ++ } ++ ++ return bu64754_set(bu64754, bu64754->current_val); ++} ++ ++static int bu64754_standby(struct bu64754 *bu64754) ++{ ++ int ret; ++ ++ ret = cci_write(bu64754->cci, BU64754_REG_ACTIVE, 0, NULL); ++ if (ret < 0) ++ dev_err(bu64754->dev, "Failed to enter standby mode ret = %d\n", ++ ret); ++ ++ return ret; ++} ++ ++static int bu64754_regulator_event(struct notifier_block *nb, ++ unsigned long action, void *data) ++{ ++ struct bu64754 *bu64754 = container_of(nb, struct bu64754, notifier); ++ ++ if (action & REGULATOR_EVENT_ENABLE) { ++ /* ++ * Initialisation delay between VDD low->high and availability ++ * i2c operation. ++ */ ++ usleep_range(BU64754_POWER_ON_DELAY, ++ BU64754_POWER_ON_DELAY + 100); ++ ++ bu64754_active(bu64754); ++ } else if (action & REGULATOR_EVENT_PRE_DISABLE) { ++ bu64754_standby(bu64754); ++ } ++ ++ return 0; ++} ++ ++static int bu64754_set_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct bu64754 *bu64754 = container_of(ctrl->handler, ++ struct bu64754, ctrls_vcm); ++ ++ if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) { ++ bu64754->current_val = ctrl->val; ++ return bu64754_set(bu64754, ctrl->val); ++ } ++ ++ return -EINVAL; ++} ++ ++static const struct v4l2_ctrl_ops bu64754_vcm_ctrl_ops = { ++ .s_ctrl = bu64754_set_ctrl, ++}; ++ ++static int bu64754_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) ++{ ++ return pm_runtime_resume_and_get(sd->dev); ++} ++ ++static int bu64754_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) ++{ ++ pm_runtime_put(sd->dev); ++ return 0; ++} ++ ++static const struct v4l2_subdev_internal_ops bu64754_int_ops = { ++ .open = bu64754_open, ++ .close = bu64754_close, ++}; ++ ++static const struct v4l2_subdev_ops bu64754_ops = { }; ++ ++static void bu64754_subdev_cleanup(struct bu64754 *bu64754) ++{ ++ v4l2_async_unregister_subdev(&bu64754->sd); ++ v4l2_ctrl_handler_free(&bu64754->ctrls_vcm); ++ media_entity_cleanup(&bu64754->sd.entity); ++} ++ ++static int bu64754_init_controls(struct bu64754 *bu64754) ++{ ++ struct v4l2_ctrl_handler *hdl = &bu64754->ctrls_vcm; ++ const struct v4l2_ctrl_ops *ops = &bu64754_vcm_ctrl_ops; ++ ++ v4l2_ctrl_handler_init(hdl, 1); ++ ++ v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE, ++ 0, BU64753_POSITION_MAX, BU64753_POSITION_STEPS, ++ 0); ++ ++ bu64754->current_val = 0; ++ ++ bu64754->sd.ctrl_handler = hdl; ++ if (hdl->error) { ++ dev_err(bu64754->dev, "%s fail error: 0x%x\n", ++ __func__, hdl->error); ++ return hdl->error; ++ } ++ ++ return 0; ++} ++ ++static int bu64754_probe(struct i2c_client *client) ++{ ++ struct bu64754 *bu64754; ++ int ret; ++ ++ bu64754 = devm_kzalloc(&client->dev, sizeof(*bu64754), GFP_KERNEL); ++ if (!bu64754) ++ return -ENOMEM; ++ ++ bu64754->dev = &client->dev; ++ ++ bu64754->cci = devm_cci_regmap_init_i2c(client, 8); ++ if (IS_ERR(bu64754->cci)) { ++ dev_err(bu64754->dev, "Failed to initialize CCI\n"); ++ return PTR_ERR(bu64754->cci); ++ } ++ ++ bu64754->vdd = devm_regulator_get_optional(&client->dev, "vdd"); ++ if (IS_ERR(bu64754->vdd)) { ++ if (PTR_ERR(bu64754->vdd) != -ENODEV) ++ return PTR_ERR(bu64754->vdd); ++ ++ bu64754->vdd = NULL; ++ } else { ++ bu64754->notifier.notifier_call = bu64754_regulator_event; ++ ++ ret = regulator_register_notifier(bu64754->vdd, ++ &bu64754->notifier); ++ if (ret) { ++ dev_err(bu64754->dev, ++ "could not register regulator notifier\n"); ++ return ret; ++ } ++ } ++ ++ v4l2_i2c_subdev_init(&bu64754->sd, client, &bu64754_ops); ++ bu64754->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ++ bu64754->sd.internal_ops = &bu64754_int_ops; ++ bu64754->sd.entity.function = MEDIA_ENT_F_LENS; ++ ++ ret = bu64754_init_controls(bu64754); ++ if (ret) ++ goto err_cleanup; ++ ++ ret = media_entity_pads_init(&bu64754->sd.entity, 0, NULL); ++ if (ret < 0) ++ goto err_cleanup; ++ ++ bu64754->sd.entity.function = MEDIA_ENT_F_LENS; ++ ++ ret = v4l2_async_register_subdev(&bu64754->sd); ++ if (ret < 0) ++ goto err_cleanup; ++ ++ if (!bu64754->vdd) ++ pm_runtime_set_active(&client->dev); ++ ++ pm_runtime_enable(&client->dev); ++ pm_runtime_idle(&client->dev); ++ ++ return 0; ++ ++err_cleanup: ++ v4l2_ctrl_handler_free(&bu64754->ctrls_vcm); ++ media_entity_cleanup(&bu64754->sd.entity); ++ ++ return ret; ++} ++ ++static void bu64754_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct bu64754 *bu64754 = sd_to_bu64754(sd); ++ ++ if (bu64754->vdd) ++ regulator_unregister_notifier(bu64754->vdd, ++ &bu64754->notifier); ++ ++ pm_runtime_disable(&client->dev); ++ ++ bu64754_subdev_cleanup(bu64754); ++} ++ ++static int __maybe_unused bu64754_vcm_suspend(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct bu64754 *bu64754 = sd_to_bu64754(sd); ++ ++ if (bu64754->vdd) ++ return regulator_disable(bu64754->vdd); ++ ++ return bu64754_standby(bu64754); ++} ++ ++static int __maybe_unused bu64754_vcm_resume(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct v4l2_subdev *sd = i2c_get_clientdata(client); ++ struct bu64754 *bu64754 = sd_to_bu64754(sd); ++ ++ if (bu64754->vdd) ++ return regulator_enable(bu64754->vdd); ++ ++ return bu64754_active(bu64754); ++} ++ ++static const struct of_device_id bu64754_of_table[] = { ++ { .compatible = "rohm,bu64754", }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, bu64754_of_table); ++ ++static const struct dev_pm_ops bu64754_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(bu64754_vcm_suspend, bu64754_vcm_resume) ++ SET_RUNTIME_PM_OPS(bu64754_vcm_suspend, bu64754_vcm_resume, NULL) ++}; ++ ++static struct i2c_driver bu64754_i2c_driver = { ++ .driver = { ++ .name = "bu64754", ++ .pm = &bu64754_pm_ops, ++ .of_match_table = bu64754_of_table, ++ }, ++ .probe_new = bu64754_probe, ++ .remove = bu64754_remove, ++}; ++ ++module_i2c_driver(bu64754_i2c_driver); ++ ++MODULE_AUTHOR("Kieran Bingham"); ++MODULE_DESCRIPTION("BU64754 VCM driver"); ++MODULE_LICENSE("GPL"); ++ diff --git a/target/linux/bcm27xx/patches-6.1/950-1197-overlays-Add-overlay-for-the-OV64A40-Arducam-Camera-.patch b/target/linux/bcm27xx/patches-6.1/950-1197-overlays-Add-overlay-for-the-OV64A40-Arducam-Camera-.patch new file mode 100644 index 0000000000..d3ee0dc68e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1197-overlays-Add-overlay-for-the-OV64A40-Arducam-Camera-.patch @@ -0,0 +1,426 @@ +From 7f67a45ee7c008c3d8e45fde6fa9c4287fb3bc9e Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Thu, 20 Jul 2023 13:18:34 +0200 +Subject: [PATCH] overlays: Add overlay for the OV64A40 Arducam Camera Module + +Arducam have integrated an Omnivision OV64A40 with a ROHM BU64754 VCM +with a Raspberry Pi compatible cable pinout. + +Provide an overlay to support the module. + +Also add support to the camera mux overlays. + +Signed-off-by: Jacopo Mondi +Signed-off-by: Kieran Bingham +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 25 +++++ + .../dts/overlays/camera-mux-2port-overlay.dts | 32 +++++++ + .../dts/overlays/camera-mux-4port-overlay.dts | 64 +++++++++++++ + .../arm/boot/dts/overlays/ov64a40-overlay.dts | 91 +++++++++++++++++++ + arch/arm/boot/dts/overlays/ov64a40.dtsi | 34 +++++++ + 6 files changed, 247 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/ov64a40-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/ov64a40.dtsi + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -175,6 +175,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + mz61581.dtbo \ + ov2311.dtbo \ + ov5647.dtbo \ ++ ov64a40.dtbo \ + ov7251.dtbo \ + ov9281.dtbo \ + papirus.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -817,6 +817,7 @@ Params: cam0-arducam-64mp Select A + cam0-imx708 Select IMX708 for camera on port 0 + cam0-ov2311 Select OV2311 for camera on port 0 + cam0-ov5647 Select OV5647 for camera on port 0 ++ cam0-ov64a40 Select OV64A40 for camera on port 0 + cam0-ov7251 Select OV7251 for camera on port 0 + cam0-ov9281 Select OV9281 for camera on port 0 + cam0-imx290-clk-freq Set clock frequency for an IMX290 on port 0 +@@ -829,6 +830,7 @@ Params: cam0-arducam-64mp Select A + cam1-imx708 Select IMX708 for camera on port 1 + cam1-ov2311 Select OV2311 for camera on port 1 + cam1-ov5647 Select OV5647 for camera on port 1 ++ cam1-ov64a40 Select OV64A40 for camera on port 1 + cam1-ov7251 Select OV7251 for camera on port 1 + cam1-ov9281 Select OV9281 for camera on port 1 + cam1-imx290-clk-freq Set clock frequency for an IMX290 on port 1 +@@ -850,6 +852,7 @@ Params: cam0-arducam-64mp Select A + cam0-imx708 Select IMX708 for camera on port 0 + cam0-ov2311 Select OV2311 for camera on port 0 + cam0-ov5647 Select OV5647 for camera on port 0 ++ cam0-ov64a40 Select OV64A40 for camera on port 0 + cam0-ov7251 Select OV7251 for camera on port 0 + cam0-ov9281 Select OV9281 for camera on port 0 + cam0-imx290-clk-freq Set clock frequency for an IMX290 on port 0 +@@ -862,6 +865,7 @@ Params: cam0-arducam-64mp Select A + cam1-imx708 Select IMX708 for camera on port 1 + cam1-ov2311 Select OV2311 for camera on port 1 + cam1-ov5647 Select OV5647 for camera on port 1 ++ cam1-ov64a40 Select OV64A40 for camera on port 1 + cam1-ov7251 Select OV7251 for camera on port 1 + cam1-ov9281 Select OV9281 for camera on port 1 + cam1-imx290-clk-freq Set clock frequency for an IMX290 on port 1 +@@ -874,6 +878,7 @@ Params: cam0-arducam-64mp Select A + cam2-imx708 Select IMX708 for camera on port 2 + cam2-ov2311 Select OV2311 for camera on port 2 + cam2-ov5647 Select OV5647 for camera on port 2 ++ cam2-ov64a40 Select OV64A40 for camera on port 2 + cam2-ov7251 Select OV7251 for camera on port 2 + cam2-ov9281 Select OV9281 for camera on port 2 + cam2-imx290-clk-freq Set clock frequency for an IMX290 on port 2 +@@ -886,6 +891,7 @@ Params: cam0-arducam-64mp Select A + cam3-imx708 Select IMX708 for camera on port 3 + cam3-ov2311 Select OV2311 for camera on port 3 + cam3-ov5647 Select OV5647 for camera on port 3 ++ cam3-ov64a40 Select OV64A40 for camera on port 3 + cam3-ov7251 Select OV7251 for camera on port 3 + cam3-ov9281 Select OV9281 for camera on port 3 + cam3-imx290-clk-freq Set clock frequency for an IMX290 on port 3 +@@ -3222,6 +3228,25 @@ Params: rotation Mounting + vcm Configure a VCM focus drive on the sensor. + + ++Name: ov64a40 ++Info: Arducam OV64A40 camera module. ++ Uses Unicam 1, which is the standard camera connector on most Pi ++ variants. ++Load: dtoverlay=ov64a40,= ++Params: rotation Mounting rotation of the camera sensor (0 or ++ 180, default 0) ++ orientation Sensor orientation (0 = front, 1 = rear, ++ 2 = external, default external) ++ media-controller Configure use of Media Controller API for ++ configuring the sensor (default on) ++ cam0 Adopt the default configuration for CAM0 on a ++ Compute Module (CSI0, i2c_vc, and cam0_reg). ++ vcm Select lens driver state. Default is enabled, ++ but vcm=off will disable. ++ link-frequency Allowable link frequency values to use in Hz: ++ 456000000 (default), 360000000 ++ ++ + Name: ov7251 + Info: Omnivision OV7251 camera module. + Uses Unicam 1, which is the standard camera connector on most Pi +--- a/arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts ++++ b/arch/arm/boot/dts/overlays/camera-mux-2port-overlay.dts +@@ -189,6 +189,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_0 ++ #define cam_endpoint ov64a40_0_ep ++ #define vcm_node ov64a40_0_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + + i2c@1 { +@@ -289,6 +299,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_1 ++ #define cam_endpoint ov64a40_1_ep ++ #define vcm_node ov64a40_1_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + }; + }; +@@ -450,6 +470,12 @@ + cam0-ov2311 = <&mux_in0>, "remote-endpoint:0=",<&ov2311_0_ep>, + <&ov2311_0_ep>, "remote-endpoint:0=",<&mux_in0>, + <&ov2311_0>, "status=okay"; ++ cam0-ov64a40 = <&mux_in0>, "remote-endpoint:0=",<&ov64a40_0_ep>, ++ <&ov64a40_0_ep>, "remote-endpoint:0=",<&mux_in0>, ++ <&mux_in0>, "clock-noncontinuous?", ++ <&ov64a40_0>, "status=okay", ++ <&ov64a40_0_vcm>, "status=okay", ++ <&ov64a40_0>,"lens-focus:0=", <&ov64a40_0_vcm>; + + cam1-arducam-64mp = <&mux_in1>, "remote-endpoint:0=",<&arducam_64mp_1_ep>, + <&arducam_64mp_1_ep>, "remote-endpoint:0=",<&mux_in1>, +@@ -496,6 +522,12 @@ + cam1-ov2311 = <&mux_in1>, "remote-endpoint:0=",<&ov2311_1_ep>, + <&ov2311_1_ep>, "remote-endpoint:0=",<&mux_in1>, + <&ov2311_1>, "status=okay"; ++ cam1-ov64a40 = <&mux_in1>, "remote-endpoint:0=",<&ov64a40_1_ep>, ++ <&ov64a40_1_ep>, "remote-endpoint:0=",<&mux_in1>, ++ <&mux_in1>, "clock-noncontinuous?", ++ <&ov64a40_1>, "status=okay", ++ <&ov64a40_1_vcm>, "status=okay", ++ <&ov64a40_1>,"lens-focus:0=", <&ov64a40_1_vcm>; + + cam0-imx290-clk-freq = <&clk_imx290>,"clock-frequency:0", + <&imx290_0>,"clock-frequency:0"; +--- a/arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts ++++ b/arch/arm/boot/dts/overlays/camera-mux-4port-overlay.dts +@@ -247,6 +247,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_0 ++ #define cam_endpoint ov64a40_0_ep ++ #define vcm_node ov64a40_0_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + + i2c@1 { +@@ -347,6 +357,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_1 ++ #define cam_endpoint ov64a40_1_ep ++ #define vcm_node ov64a40_1_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + + i2c@2 { +@@ -447,6 +467,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_2 ++ #define cam_endpoint ov64a40_2_ep ++ #define vcm_node ov64a40_2_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + + i2c@3 { +@@ -547,6 +577,16 @@ + #undef cam_node + #undef cam_endpoint + #undef cam1_clk ++ ++ #define cam_node ov64a40_3 ++ #define cam_endpoint ov64a40_3_ep ++ #define vcm_node ov64a40_3_vcm ++ #define cam1_clk clk_24mhz ++ #include "ov64a40.dtsi" ++ #undef cam_node ++ #undef cam_endpoint ++ #undef vcm_node ++ #undef cam1_clk + }; + }; + }; +@@ -725,6 +765,12 @@ + cam0-ov2311 = <&mux_in0>, "remote-endpoint:0=",<&ov2311_0_ep>, + <&ov2311_0_ep>, "remote-endpoint:0=",<&mux_in0>, + <&ov2311_0>, "status=okay"; ++ cam0-ov64a40 = <&mux_in0>, "remote-endpoint:0=",<&ov64a40_0_ep>, ++ <&ov64a40_0_ep>, "remote-endpoint:0=",<&mux_in0>, ++ <&mux_in0>, "clock-noncontinuous?", ++ <&ov64a40_0>, "status=okay", ++ <&ov64a40_0_vcm>, "status=okay", ++ <&ov64a40_0>,"lens-focus:0=", <&ov64a40_0_vcm>; + + cam1-arducam-64mp = <&mux_in1>, "remote-endpoint:0=",<&arducam_64mp_1_ep>, + <&arducam_64mp_1_ep>, "remote-endpoint:0=",<&mux_in1>, +@@ -771,6 +817,12 @@ + cam1-ov2311 = <&mux_in1>, "remote-endpoint:0=",<&ov2311_1_ep>, + <&ov2311_1_ep>, "remote-endpoint:0=",<&mux_in1>, + <&ov2311_1>, "status=okay"; ++ cam1-ov64a40 = <&mux_in1>, "remote-endpoint:0=",<&ov64a40_1_ep>, ++ <&ov64a40_1_ep>, "remote-endpoint:0=",<&mux_in1>, ++ <&mux_in1>, "clock-noncontinuous?", ++ <&ov64a40_1>, "status=okay", ++ <&ov64a40_1_vcm>, "status=okay", ++ <&ov64a40_1>,"lens-focus:0=", <&ov64a40_1_vcm>; + + cam2-arducam-64mp = <&mux_in2>, "remote-endpoint:0=",<&arducam_64mp_2_ep>, + <&arducam_64mp_2_ep>, "remote-endpoint:0=",<&mux_in2>, +@@ -817,6 +869,12 @@ + cam2-ov2311 = <&mux_in2>, "remote-endpoint:0=",<&ov2311_2_ep>, + <&ov2311_2_ep>, "remote-endpoint:0=",<&mux_in2>, + <&ov2311_2>, "status=okay"; ++ cam2-ov64a40 = <&mux_in2>, "remote-endpoint:0=",<&ov64a40_2_ep>, ++ <&ov64a40_2_ep>, "remote-endpoint:0=",<&mux_in2>, ++ <&mux_in2>, "clock-noncontinuous?", ++ <&ov64a40_2>, "status=okay", ++ <&ov64a40_2_vcm>, "status=okay", ++ <&ov64a40_2>,"lens-focus:0=", <&ov64a40_2_vcm>; + + cam3-arducam-64mp = <&mux_in3>, "remote-endpoint:0=",<&arducam_64mp_3_ep>, + <&arducam_64mp_3_ep>, "remote-endpoint:0=",<&mux_in3>, +@@ -863,6 +921,12 @@ + cam3-ov2311 = <&mux_in3>, "remote-endpoint:0=",<&ov2311_3_ep>, + <&ov2311_3_ep>, "remote-endpoint:0=",<&mux_in3>, + <&ov2311_3>, "status=okay"; ++ cam3-ov64a40 = <&mux_in3>, "remote-endpoint:0=",<&ov64a40_3_ep>, ++ <&ov64a40_3_ep>, "remote-endpoint:0=",<&mux_in3>, ++ <&mux_in3>, "clock-noncontinuous?", ++ <&ov64a40_3>, "status=okay", ++ <&ov64a40_3_vcm>, "status=okay", ++ <&ov64a40_3>,"lens-focus:0=", <&ov64a40_3_vcm>; + + cam0-imx290-clk-freq = <&clk_imx290>,"clock-frequency:0", + <&imx290_0>,"clock-frequency:0"; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/ov64a40-overlay.dts +@@ -0,0 +1,91 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++// Definitions for OV64A40 camera module on VC I2C bus ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2835"; ++ ++ i2c_frag: fragment@0 { ++ target = <&i2c_csi_dsi>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ #include "ov64a40.dtsi" ++ }; ++ }; ++ ++ csi_frag: fragment@1 { ++ target = <&csi1>; ++ csi: __overlay__ { ++ status = "okay"; ++ brcm,media-controller; ++ ++ port{ ++ csi_ep: endpoint{ ++ remote-endpoint = <&cam_endpoint>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c0if>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ clk_frag: fragment@3 { ++ target = <&cam1_clk>; ++ __overlay__ { ++ clock-frequency = <24000000>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&i2c0mux>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&cam_node>; ++ __overlay__ { ++ lens-focus = <&vcm_node>; ++ }; ++ }; ++ ++ __overrides__ { ++ rotation = <&cam_node>,"rotation:0"; ++ orientation = <&cam_node>,"orientation:0"; ++ media-controller = <&csi>,"brcm,media-controller?"; ++ cam0 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>, ++ <&csi_frag>, "target:0=",<&csi0>, ++ <&clk_frag>, "target:0=",<&cam0_clk>, ++ <&cam_node>, "clocks:0=",<&cam0_clk>, ++ <&cam_node>, "avdd-supply:0=",<&cam0_reg>, ++ <&vcm_node>, "vdd-supply:0=",<&cam0_reg>; ++ vcm = <&vcm_node>, "status", ++ <0>, "=5"; ++ link-frequency = <&cam_endpoint>,"link-frequencies#0"; ++ }; ++}; ++ ++&cam_node { ++ status = "okay"; ++}; ++ ++&cam_endpoint { ++ remote-endpoint = <&csi_ep>; ++}; ++ ++&vcm_node { ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/ov64a40.dtsi +@@ -0,0 +1,34 @@ ++// Fragment that configures an OV64A40 ++ ++cam_node: ov64a40@36 { ++ compatible = "ovti,ov64a40"; ++ reg = <0x36>; ++ status = "disabled"; ++ ++ clocks = <&cam1_clk>; ++ clock-names = "xclk"; ++ ++ avdd-supply = <&cam1_reg>; /* 2.8v */ ++ dovdd-supply = <&cam_dummy_reg>;/* 1.8v */ ++ dvdd-supply = <&cam_dummy_reg>; /* 1.1v */ ++ ++ rotation = <180>; ++ orientation = <2>; ++ ++ port { ++ cam_endpoint: endpoint { ++ bus-type = <4>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ link-frequencies = ++ /bits/ 64 <456000000>; ++ }; ++ }; ++}; ++ ++vcm_node: bu64754@76 { ++ compatible = "rohm,bu64754"; ++ reg = <0x76>; ++ status = "disabled"; ++ vdd-supply = <&cam1_reg>; ++}; diff --git a/target/linux/bcm27xx/patches-6.1/950-1199-media-rp1-cfe-Fix-verbose-debug-print.patch b/target/linux/bcm27xx/patches-6.1/950-1199-media-rp1-cfe-Fix-verbose-debug-print.patch new file mode 100644 index 0000000000..8ff96cc568 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1199-media-rp1-cfe-Fix-verbose-debug-print.patch @@ -0,0 +1,26 @@ +From 8ef68aadaa3aa29bc2661ab44db4ddc50e77cef5 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Wed, 4 Oct 2023 11:25:16 +0300 +Subject: [PATCH] media: rp1: cfe: Fix verbose debug print + +Switch a debug print from cfe_dbg() to cfe_dbg_verbose() as it will be +printed often while streaming. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -975,8 +975,8 @@ static void cfe_buffer_queue(struct vb2_ + + if (!cfe->job_queued && cfe->job_ready && + test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) { +- cfe_dbg("Preparing job immediately for channel %u\n", +- node->id); ++ cfe_dbg_verbose("Preparing job immediately for channel %u\n", ++ node->id); + cfe_prepare_next_job(cfe); + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1200-media-rp1-cfe-Expose-find_format_by_pix.patch b/target/linux/bcm27xx/patches-6.1/950-1200-media-rp1-cfe-Expose-find_format_by_pix.patch new file mode 100644 index 0000000000..f263648af2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1200-media-rp1-cfe-Expose-find_format_by_pix.patch @@ -0,0 +1,33 @@ +From d978e784f433346d3676b5de805b3cea36b835c4 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 16:23:58 +0300 +Subject: [PATCH] media: rp1: cfe: Expose find_format_by_pix() + +Make find_format_by_pix() accessible to other files in the driver. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.c | 2 +- + drivers/media/platform/raspberrypi/rp1_cfe/cfe.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -461,7 +461,7 @@ const struct cfe_fmt *find_format_by_cod + return NULL; + } + +-static const struct cfe_fmt *find_format_by_pix(u32 pixelformat) ++const struct cfe_fmt *find_format_by_pix(u32 pixelformat) + { + unsigned int i; + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h +@@ -36,5 +36,6 @@ extern const struct v4l2_mbus_framefmt c + extern const struct v4l2_mbus_framefmt cfe_default_meta_format; + + const struct cfe_fmt *find_format_by_code(u32 code); ++const struct cfe_fmt *find_format_by_pix(u32 pixelformat); + + #endif diff --git a/target/linux/bcm27xx/patches-6.1/950-1201-media-rp1-cfe-Add-missing-remaps.patch b/target/linux/bcm27xx/patches-6.1/950-1201-media-rp1-cfe-Add-missing-remaps.patch new file mode 100644 index 0000000000..d6dadb6f27 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1201-media-rp1-cfe-Add-missing-remaps.patch @@ -0,0 +1,43 @@ +From cbed711f05a228d0f8f54b1b01f43d4d6489eccc Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 16:24:14 +0300 +Subject: [PATCH] media: rp1: cfe: Add missing remaps + +8-bit bayer formats are missing remap definitions. Add them. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h +@@ -85,24 +85,28 @@ static const struct cfe_fmt formats[] = + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR }, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .code = MEDIA_BUS_FMT_SGBRG8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG }, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .code = MEDIA_BUS_FMT_SGRBG8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG }, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + .depth = 8, + .csi_dt = 0x2a, ++ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB }, + }, + { + .fourcc = V4L2_PIX_FMT_SBGGR10P, diff --git a/target/linux/bcm27xx/patches-6.1/950-1202-media-rp1-cfe-Add-missing-compressed-remaps.patch b/target/linux/bcm27xx/patches-6.1/950-1202-media-rp1-cfe-Add-missing-compressed-remaps.patch new file mode 100644 index 0000000000..92d7db369c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1202-media-rp1-cfe-Add-missing-compressed-remaps.patch @@ -0,0 +1,43 @@ +From 93c40564b94367c6ce072d66479af58afa3f08e0 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 17:14:31 +0300 +Subject: [PATCH] media: rp1: cfe: Add missing compressed remaps + +16-bit bayer formats are missing compressed remap definitions. Add them. + +Signed-off-by: Tomi Valkeinen +--- + drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe_fmts.h +@@ -197,24 +197,28 @@ static const struct cfe_fmt formats[] = + .code = MEDIA_BUS_FMT_SBGGR16_1X16, + .depth = 16, + .flags = CFE_FORMAT_FLAG_FE_OUT, ++ .remap = { V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_PISP_COMP1_BGGR }, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG16, + .code = MEDIA_BUS_FMT_SGBRG16_1X16, + .depth = 16, + .flags = CFE_FORMAT_FLAG_FE_OUT, ++ .remap = { V4L2_PIX_FMT_SGBRG16, V4L2_PIX_FMT_PISP_COMP1_GBRG }, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG16, + .code = MEDIA_BUS_FMT_SGRBG16_1X16, + .depth = 16, + .flags = CFE_FORMAT_FLAG_FE_OUT, ++ .remap = { V4L2_PIX_FMT_SGRBG16, V4L2_PIX_FMT_PISP_COMP1_GRBG }, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB16, + .code = MEDIA_BUS_FMT_SRGGB16_1X16, + .depth = 16, + .flags = CFE_FORMAT_FLAG_FE_OUT, ++ .remap = { V4L2_PIX_FMT_SRGGB16, V4L2_PIX_FMT_PISP_COMP1_RGGB }, + }, + /* PiSP Compressed Mode 1 */ + { diff --git a/target/linux/bcm27xx/patches-6.1/950-1203-media-rp1-cfe-Add-cfe_find_16bit_code-and-cfe_find_c.patch b/target/linux/bcm27xx/patches-6.1/950-1203-media-rp1-cfe-Add-cfe_find_16bit_code-and-cfe_find_c.patch new file mode 100644 index 0000000000..42c3b6f42b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1203-media-rp1-cfe-Add-cfe_find_16bit_code-and-cfe_find_c.patch @@ -0,0 +1,74 @@ +From 2e0e1d7b493dffe7baa763d499e51ba42f0bad19 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 17:14:11 +0300 +Subject: [PATCH] media: rp1: cfe: Add cfe_find_16bit_code() and + cfe_find_compressed_code() + +Add helper functions which, given an mbus code, return the 16-bit +remapped mbus code or the compressed mbus code. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 40 +++++++++++++++++++ + .../media/platform/raspberrypi/rp1_cfe/cfe.h | 2 + + 2 files changed, 42 insertions(+) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -473,6 +473,46 @@ const struct cfe_fmt *find_format_by_pix + return NULL; + } + ++/* ++ * Given the mbus code, find the 16 bit remapped code. Returns 0 if no remap ++ * possible. ++ */ ++u32 cfe_find_16bit_code(u32 code) ++{ ++ const struct cfe_fmt *cfe_fmt; ++ ++ cfe_fmt = find_format_by_code(code); ++ ++ if (!cfe_fmt || !cfe_fmt->remap[CFE_REMAP_16BIT]) ++ return 0; ++ ++ cfe_fmt = find_format_by_pix(cfe_fmt->remap[CFE_REMAP_16BIT]); ++ if (!cfe_fmt) ++ return 0; ++ ++ return cfe_fmt->code; ++} ++ ++/* ++ * Given the mbus code, find the 8 bit compressed code. Returns 0 if no remap ++ * possible. ++ */ ++u32 cfe_find_compressed_code(u32 code) ++{ ++ const struct cfe_fmt *cfe_fmt; ++ ++ cfe_fmt = find_format_by_code(code); ++ ++ if (!cfe_fmt || !cfe_fmt->remap[CFE_REMAP_COMPRESSED]) ++ return 0; ++ ++ cfe_fmt = find_format_by_pix(cfe_fmt->remap[CFE_REMAP_COMPRESSED]); ++ if (!cfe_fmt) ++ return 0; ++ ++ return cfe_fmt->code; ++} ++ + static int cfe_calc_format_size_bpl(struct cfe_device *cfe, + const struct cfe_fmt *fmt, + struct v4l2_format *f) +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.h +@@ -37,5 +37,7 @@ extern const struct v4l2_mbus_framefmt c + + const struct cfe_fmt *find_format_by_code(u32 code); + const struct cfe_fmt *find_format_by_pix(u32 pixelformat); ++u32 cfe_find_16bit_code(u32 code); ++u32 cfe_find_compressed_code(u32 code); + + #endif diff --git a/target/linux/bcm27xx/patches-6.1/950-1204-media-rp1-csi2-Fix-csi2_pad_set_fmt.patch b/target/linux/bcm27xx/patches-6.1/950-1204-media-rp1-csi2-Fix-csi2_pad_set_fmt.patch new file mode 100644 index 0000000000..d9b8d264d3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1204-media-rp1-csi2-Fix-csi2_pad_set_fmt.patch @@ -0,0 +1,95 @@ +From eaa8a0ae14a1ca797c1896e9dafbefa1fa51a617 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 16:25:10 +0300 +Subject: [PATCH] media: rp1: csi2: Fix csi2_pad_set_fmt() + +The CSI-2 subdev's set_fmt currently allows setting the source and sink +pad formats quite freely. This is not right, as the CSI-2 block can only +do one of the following when processing the stream: 1) pass through as +is, 2) expand to 16-bits, 3) compress. + +The csi2_pad_set_fmt() should take this into account, and only allow +changing the source side mbus code, compared to the sink side format. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 61 +++++++++++++++---- + 1 file changed, 48 insertions(+), 13 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -438,25 +438,60 @@ static int csi2_pad_set_fmt(struct v4l2_ + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *format) + { +- struct v4l2_mbus_framefmt *fmt; +- const struct cfe_fmt *cfe_fmt; +- +- /* TODO: format validation */ ++ if (format->pad < CSI2_NUM_CHANNELS) { ++ /* ++ * Store the sink pad format and propagate it to the source pad. ++ */ ++ ++ struct v4l2_mbus_framefmt *fmt; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); ++ if (!fmt) ++ return -EINVAL; + +- cfe_fmt = find_format_by_code(format->format.code); +- if (!cfe_fmt) +- cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SBGGR10_1X10); ++ *fmt = format->format; + +- format->format.code = cfe_fmt->code; ++ fmt = v4l2_subdev_get_pad_format(sd, state, ++ format->pad + CSI2_NUM_CHANNELS); ++ if (!fmt) ++ return -EINVAL; + +- fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); +- *fmt = format->format; ++ format->format.field = V4L2_FIELD_NONE; + +- if (format->pad < CSI2_NUM_CHANNELS) { +- /* Propagate to the source pad */ +- fmt = v4l2_subdev_get_pad_format(sd, state, +- format->pad + CSI2_NUM_CHANNELS); + *fmt = format->format; ++ } else { ++ /* ++ * Only allow changing the source pad mbus code. ++ */ ++ ++ struct v4l2_mbus_framefmt *sink_fmt, *source_fmt; ++ u32 sink_code; ++ u32 code; ++ ++ sink_fmt = v4l2_subdev_get_pad_format(sd, state, ++ format->pad - CSI2_NUM_CHANNELS); ++ if (!sink_fmt) ++ return -EINVAL; ++ ++ source_fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); ++ if (!source_fmt) ++ return -EINVAL; ++ ++ sink_code = sink_fmt->code; ++ code = format->format.code; ++ ++ /* ++ * If the source code from the user does not match the code in ++ * the sink pad, check that the source code matches either the ++ * 16-bit version or the compressed version of the sink code. ++ */ ++ ++ if (code != sink_code && ++ (code == cfe_find_16bit_code(sink_code) || ++ code == cfe_find_compressed_code(sink_code))) ++ source_fmt->code = code; ++ ++ format->format.code = source_fmt->code; + } + + return 0; diff --git a/target/linux/bcm27xx/patches-6.1/950-1205-media-rp1-fe-Fix-pisp_fe_pad_set_fmt.patch b/target/linux/bcm27xx/patches-6.1/950-1205-media-rp1-fe-Fix-pisp_fe_pad_set_fmt.patch new file mode 100644 index 0000000000..202fe2946d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1205-media-rp1-fe-Fix-pisp_fe_pad_set_fmt.patch @@ -0,0 +1,104 @@ +From 214e8134842a338215831f2efa6d730f413c5ec4 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 29 Sep 2023 17:15:20 +0300 +Subject: [PATCH] media: rp1: fe: Fix pisp_fe_pad_set_fmt() + +pisp_fe_pad_set_fmt() allows setting the pad formats quite freely. This +is not correct, and the function should only allow formats as supported +by the hardware. Fix this by: + +Allow no format changes for FE_CONFIG_PAD and FE_STATS_PAD. They should +always be the hardcoded initial ones. + +Allow setting FE_STREAM_PAD freely (but the mbus code must be +supported), and propagate the format to the FE_OUTPUT0_PAD and +FE_OUTPUT1_PAD pads. + +Allow changing the mbus code for FE_OUTPUT0_PAD and FE_OUTPUT1_PAD pads +only if the mbus code is the compressed version of the sink side code. + +TODO: FE supports scaling and cropping. This should be represented here +too? + +Signed-off-by: Tomi Valkeinen +--- + .../platform/raspberrypi/rp1_cfe/pisp_fe.c | 59 +++++++++++++++---- + 1 file changed, 48 insertions(+), 11 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -433,26 +433,63 @@ static int pisp_fe_pad_set_fmt(struct v4 + + switch (format->pad) { + case FE_STREAM_PAD: +- case FE_OUTPUT0_PAD: +- case FE_OUTPUT1_PAD: + cfe_fmt = find_format_by_code(format->format.code); + if (!cfe_fmt || !(cfe_fmt->flags & CFE_FORMAT_FLAG_FE_OUT)) + cfe_fmt = find_format_by_code(MEDIA_BUS_FMT_SRGGB16_1X16); + + format->format.code = cfe_fmt->code; ++ format->format.field = V4L2_FIELD_NONE; + +- break; ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_STREAM_PAD); ++ *fmt = format->format; + +- case FE_STATS_PAD: +- case FE_CONFIG_PAD: +- format->format.code = MEDIA_BUS_FMT_FIXED; +- break; +- } ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT0_PAD); ++ *fmt = format->format; ++ ++ fmt = v4l2_subdev_get_pad_format(sd, state, FE_OUTPUT1_PAD); ++ *fmt = format->format; ++ ++ return 0; + +- fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); +- *fmt = format->format; ++ case FE_OUTPUT0_PAD: ++ case FE_OUTPUT1_PAD: { ++ /* ++ * TODO: we should allow scaling and cropping by allowing the ++ * user to set the size here. ++ */ ++ struct v4l2_mbus_framefmt *sink_fmt, *source_fmt; ++ u32 sink_code; ++ u32 code; ++ ++ sink_fmt = v4l2_subdev_get_pad_format(sd, state, FE_STREAM_PAD); ++ if (!sink_fmt) ++ return -EINVAL; ++ ++ source_fmt = v4l2_subdev_get_pad_format(sd, state, format->pad); ++ if (!source_fmt) ++ return -EINVAL; ++ ++ sink_code = sink_fmt->code; ++ code = format->format.code; ++ ++ /* ++ * If the source code from the user does not match the code in ++ * the sink pad, check that the source code matches the ++ * compressed version of the sink code. ++ */ ++ ++ if (code != sink_code && ++ code == cfe_find_compressed_code(sink_code)) ++ source_fmt->code = code; ++ ++ return 0; ++ } + +- return 0; ++ case FE_CONFIG_PAD: ++ case FE_STATS_PAD: ++ default: ++ return v4l2_subdev_get_fmt(sd, state, format); ++ } + } + + static int pisp_fe_link_validate(struct v4l2_subdev *sd, diff --git a/target/linux/bcm27xx/patches-6.1/950-1206-media-rp1-csi2-Use-get_frame_desc-to-get-CSI-2-VC-an.patch b/target/linux/bcm27xx/patches-6.1/950-1206-media-rp1-csi2-Use-get_frame_desc-to-get-CSI-2-VC-an.patch new file mode 100644 index 0000000000..bd5789a1b3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1206-media-rp1-csi2-Use-get_frame_desc-to-get-CSI-2-VC-an.patch @@ -0,0 +1,146 @@ +From 425a6b752c38b50c97220db37a67b18b281f56e5 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 21 Sep 2023 15:28:20 +0300 +Subject: [PATCH] media: rp1: csi2: Use get_frame_desc to get CSI-2 VC and DT + +Use get_frame_desc pad op for asking the CSI-2 VC and DT from the source +device driver, instead of hardcoding to VC 0, and getting the DT from a +formats table. To keep backward compatibility with sources that do not +implement get_frame_desc, implement a fallback mechanism that always +uses VC 0, and gets the DT from the formats table, based on the CSI2's +sink pad's format. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 4 +- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 75 ++++++++++++++++++- + .../media/platform/raspberrypi/rp1_cfe/csi2.h | 2 +- + 3 files changed, 77 insertions(+), 4 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -838,7 +838,7 @@ static void cfe_start_channel(struct cfe + * this is handled by the CSI2 AUTO_ARM mode. + */ + csi2_start_channel(&cfe->csi2, cfe->fe_csi2_channel, +- fmt->csi_dt, CSI2_MODE_FE_STREAMING, ++ CSI2_MODE_FE_STREAMING, + true, false, width, height); + csi2_set_buffer(&cfe->csi2, cfe->fe_csi2_channel, 0, 0, -1); + pisp_fe_start(&cfe->fe); +@@ -872,7 +872,7 @@ static void cfe_start_channel(struct cfe + } + } + /* Unconditionally start this CSI2 channel. */ +- csi2_start_channel(&cfe->csi2, node->id, fmt->csi_dt, ++ csi2_start_channel(&cfe->csi2, node->id, + mode, + /* Auto arm */ + false, +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -324,12 +324,84 @@ void csi2_set_compression(struct csi2_de + csi2_reg_write(csi2, CSI2_CH_COMP_CTRL(channel), compression); + } + ++static int csi2_get_vc_dt_fallback(struct csi2_device *csi2, ++ unsigned int channel, u8 *vc, u8 *dt) ++{ ++ struct v4l2_subdev *sd = &csi2->sd; ++ struct v4l2_subdev_state *state; ++ struct v4l2_mbus_framefmt *fmt; ++ const struct cfe_fmt *cfe_fmt; ++ ++ state = v4l2_subdev_get_locked_active_state(sd); ++ ++ /* Without Streams API, the channel number matches the sink pad */ ++ fmt = v4l2_subdev_get_pad_format(sd, state, channel); ++ if (!fmt) ++ return -EINVAL; ++ ++ cfe_fmt = find_format_by_code(fmt->code); ++ if (!cfe_fmt) ++ return -EINVAL; ++ ++ *vc = 0; ++ *dt = cfe_fmt->csi_dt; ++ ++ return 0; ++} ++ ++static int csi2_get_vc_dt(struct csi2_device *csi2, unsigned int channel, ++ u8 *vc, u8 *dt) ++{ ++ struct v4l2_mbus_frame_desc remote_desc; ++ const struct media_pad *remote_pad; ++ struct v4l2_subdev *source_sd; ++ int ret; ++ ++ /* Without Streams API, the channel number matches the sink pad */ ++ remote_pad = media_pad_remote_pad_first(&csi2->pad[channel]); ++ if (!remote_pad) ++ return -EPIPE; ++ ++ source_sd = media_entity_to_v4l2_subdev(remote_pad->entity); ++ ++ ret = v4l2_subdev_call(source_sd, pad, get_frame_desc, ++ remote_pad->index, &remote_desc); ++ if (ret == -ENOIOCTLCMD) { ++ csi2_dbg("source does not support get_frame_desc, use fallback\n"); ++ return csi2_get_vc_dt_fallback(csi2, channel, vc, dt); ++ } else if (ret) { ++ csi2_err("Failed to get frame descriptor\n"); ++ return ret; ++ } ++ ++ if (remote_desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) { ++ csi2_err("Frame descriptor does not describe CSI-2 link"); ++ return -EINVAL; ++ } ++ ++ if (remote_desc.num_entries != 1) { ++ csi2_err("Frame descriptor does not have a single entry"); ++ return -EINVAL; ++ } ++ ++ *vc = remote_desc.entry[0].bus.csi2.vc; ++ *dt = remote_desc.entry[0].bus.csi2.dt; ++ ++ return 0; ++} ++ + void csi2_start_channel(struct csi2_device *csi2, unsigned int channel, +- u16 dt, enum csi2_mode mode, bool auto_arm, ++ enum csi2_mode mode, bool auto_arm, + bool pack_bytes, unsigned int width, + unsigned int height) + { + u32 ctrl; ++ int ret; ++ u8 vc, dt; ++ ++ ret = csi2_get_vc_dt(csi2, channel, &vc, &dt); ++ if (ret) ++ return; + + csi2_dbg("%s [%u]\n", __func__, channel); + +@@ -369,6 +441,7 @@ void csi2_start_channel(struct csi2_devi + csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), 0); + } + ++ set_field(&ctrl, vc, VC_MASK); + set_field(&ctrl, dt, DT_MASK); + csi2_reg_write(csi2, CSI2_CH_CTRL(channel), ctrl); + csi2->num_lines[channel] = height; +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h +@@ -79,7 +79,7 @@ void csi2_set_compression(struct csi2_de + enum csi2_compression_mode mode, unsigned int shift, + unsigned int offset); + void csi2_start_channel(struct csi2_device *csi2, unsigned int channel, +- u16 dt, enum csi2_mode mode, bool auto_arm, ++ enum csi2_mode mode, bool auto_arm, + bool pack_bytes, unsigned int width, + unsigned int height); + void csi2_stop_channel(struct csi2_device *csi2, unsigned int channel); diff --git a/target/linux/bcm27xx/patches-6.1/950-1207-media-rp1-cfe-Add-is_image_node.patch b/target/linux/bcm27xx/patches-6.1/950-1207-media-rp1-cfe-Add-is_image_node.patch new file mode 100644 index 0000000000..ad589d79cf --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1207-media-rp1-cfe-Add-is_image_node.patch @@ -0,0 +1,91 @@ +From 2b6570e66f2769110311593f52f88dba3271a278 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Fri, 22 Sep 2023 13:47:10 +0300 +Subject: [PATCH] media: rp1: cfe: Add is_image_node() + +The hardware supports streaming from memory (in addition to streaming +from the CSI-2 RX), but the driver does not support this at the moment. + +There are multiple places in the driver which uses +is_image_output_node(), even if the "output" part is not relevant. Thus, +in a minor preparation for the possible support for streaming from +memory, and to make it more obvious that the pieces of code are not +about the "output", add is_image_node() which will return true for both +input and output video nodes. + +While at it, reformat also the metadata related macros to fit inside 80 +columns. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 28 +++++++++++-------- + 1 file changed, 17 insertions(+), 11 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -199,13 +199,20 @@ static const struct node_description nod + + #define is_fe_node(node) (((node)->id) >= FE_OUT0) + #define is_csi2_node(node) (!is_fe_node(node)) +-#define is_image_output_node(node) \ ++ ++#define is_image_output_node(node) \ + (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) +-#define is_meta_output_node(node) \ ++#define is_image_input_node(node) \ ++ (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ++#define is_image_node(node) \ ++ (is_image_output_node(node) || is_image_input_node(node)) ++ ++#define is_meta_output_node(node) \ + (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_CAPTURE) +-#define is_meta_input_node(node) \ ++#define is_meta_input_node(node) \ + (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_OUTPUT) +-#define is_meta_node(node) (is_meta_output_node(node) || is_meta_input_node(node)) ++#define is_meta_node(node) \ ++ (is_meta_output_node(node) || is_meta_input_node(node)) + + /* To track state across all nodes. */ + #define NUM_STATES 5 +@@ -426,7 +433,7 @@ static int format_show(struct seq_file * + seq_printf(s, "\nNode %u (%s) state: 0x%lx\n", i, + node_desc[i].name, state); + +- if (is_image_output_node(node)) ++ if (is_image_node(node)) + seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\n" + "resolution: %ux%u\nbpl: %u\nsize: %u\n", + V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat), +@@ -940,9 +947,8 @@ static int cfe_queue_setup(struct vb2_qu + { + struct cfe_node *node = vb2_get_drv_priv(vq); + struct cfe_device *cfe = node->cfe; +- unsigned int size = is_image_output_node(node) ? +- node->fmt.fmt.pix.sizeimage : +- node->fmt.fmt.meta.buffersize; ++ unsigned int size = is_image_node(node) ? node->fmt.fmt.pix.sizeimage : ++ node->fmt.fmt.meta.buffersize; + + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); + +@@ -973,8 +979,8 @@ static int cfe_buffer_prepare(struct vb2 + cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, + node_desc[node->id].name, vb); + +- size = is_image_output_node(node) ? node->fmt.fmt.pix.sizeimage : +- node->fmt.fmt.meta.buffersize; ++ size = is_image_node(node) ? node->fmt.fmt.pix.sizeimage : ++ node->fmt.fmt.meta.buffersize; + if (vb2_plane_size(vb, 0) < size) { + cfe_err("data will not fit into plane (%lu < %lu)\n", + vb2_plane_size(vb, 0), size); +@@ -1757,7 +1763,7 @@ static int cfe_register_node(struct cfe_ + node->cfe = cfe; + node->id = id; + +- if (is_image_output_node(node)) { ++ if (is_image_node(node)) { + fmt = find_format_by_code(cfe_default_format.code); + if (!fmt) { + cfe_err("Failed to find format code\n"); diff --git a/target/linux/bcm27xx/patches-6.1/950-1208-media-rp1-cfe-Dual-purpose-video-nodes.patch b/target/linux/bcm27xx/patches-6.1/950-1208-media-rp1-cfe-Dual-purpose-video-nodes.patch new file mode 100644 index 0000000000..f68aa3975d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1208-media-rp1-cfe-Dual-purpose-video-nodes.patch @@ -0,0 +1,621 @@ +From c54b8d2fc79c684deacc81a94f6baa1cb56c62be Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Wed, 27 Sep 2023 17:18:09 +0300 +Subject: [PATCH] media: rp1: cfe: Dual purpose video nodes + +The RP1 CSI-2 DMA can capture both video and metadata just fine, but at +the moment the video nodes are only set to support either video or +metadata. + +Make the changes to support both video and metadata. This mostly means +tracking both video format and metadata format separately for each video +node, and using vb2_queue_change_type() to change the vb2 queue type +when needed. + +Briefly, this means that the user can get/set both video and meta +formats to a single video node. The vb2 queue buffer type will be +changed when the user calls REQBUFS or CREATE_BUFS ioctls. This buffer +type will be then used as the "mode" for the video node when the user +starts the streaming, and based on that either the video or the meta +format will be used. + +A bunch of macros are added (node_supports_xxx()), which tell if a node +can support a particular mode, whereas the existing macros +(is_xxx_node()) will tell if the node is currently in a particular mode. +Note that the latter will only work correctly between the start of the +streaming and the end of the streaming, and thus should be only used in +those code paths. + +However, as the userspace (libcamera) does not support dual purpose +video nodes, for the time being let's keep the second video node as +V4L2_CAP_META_CAPTURE only to keep the userspace working. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 271 ++++++++++++------ + 1 file changed, 182 insertions(+), 89 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -116,7 +116,7 @@ const struct v4l2_mbus_framefmt cfe_defa + enum node_ids { + /* CSI2 HW output nodes first. */ + CSI2_CH0, +- CSI2_CH1_EMBEDDED, ++ CSI2_CH1, + CSI2_CH2, + CSI2_CH3, + /* FE only nodes from here on. */ +@@ -130,8 +130,7 @@ enum node_ids { + struct node_description { + unsigned int id; + const char *name; +- enum v4l2_buf_type buf_type; +- unsigned int cap; ++ unsigned int caps; + unsigned int pad_flags; + unsigned int link_pad; + }; +@@ -140,58 +139,55 @@ struct node_description { + static const struct node_description node_desc[NUM_NODES] = { + [CSI2_CH0] = { + .name = "csi2_ch0", +- .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +- .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = CSI2_NUM_CHANNELS + 0 + }, +- /* This node is assigned for the embedded data channel! */ +- [CSI2_CH1_EMBEDDED] = { ++ /* ++ * TODO: This node should be named "csi2_ch1" and the caps should be set ++ * to both video and meta capture. However, to keep compatibility with ++ * the current libcamera, keep the name as "embedded" and support ++ * only meta capture. ++ */ ++ [CSI2_CH1] = { + .name = "embedded", +- .buf_type = V4L2_BUF_TYPE_META_CAPTURE, +- .cap = V4L2_CAP_META_CAPTURE, ++ .caps = V4L2_CAP_META_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = CSI2_NUM_CHANNELS + 1 + }, + [CSI2_CH2] = { + .name = "csi2_ch2", +- .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +- .cap = V4L2_CAP_META_CAPTURE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = CSI2_NUM_CHANNELS + 2 + }, + [CSI2_CH3] = { + .name = "csi2_ch3", +- .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +- .cap = V4L2_CAP_META_CAPTURE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = CSI2_NUM_CHANNELS + 3 + }, + [FE_OUT0] = { + .name = "fe_image0", +- .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +- .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = FE_OUTPUT0_PAD + }, + [FE_OUT1] = { + .name = "fe_image1", +- .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE, +- .cap = V4L2_CAP_VIDEO_CAPTURE, ++ .caps = V4L2_CAP_VIDEO_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = FE_OUTPUT1_PAD + }, + [FE_STATS] = { + .name = "fe_stats", +- .buf_type = V4L2_BUF_TYPE_META_CAPTURE, +- .cap = V4L2_CAP_META_CAPTURE, ++ .caps = V4L2_CAP_META_CAPTURE, + .pad_flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = FE_STATS_PAD + }, + [FE_CONFIG] = { + .name = "fe_config", +- .buf_type = V4L2_BUF_TYPE_META_OUTPUT, +- .cap = V4L2_CAP_META_OUTPUT, ++ .caps = V4L2_CAP_META_OUTPUT, + .pad_flags = MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT, + .link_pad = FE_CONFIG_PAD + }, +@@ -200,17 +196,29 @@ static const struct node_description nod + #define is_fe_node(node) (((node)->id) >= FE_OUT0) + #define is_csi2_node(node) (!is_fe_node(node)) + ++#define node_supports_image_output(node) \ ++ (!!(node_desc[(node)->id].caps & V4L2_CAP_VIDEO_CAPTURE)) ++#define node_supports_meta_output(node) \ ++ (!!(node_desc[(node)->id].caps & V4L2_CAP_META_CAPTURE)) ++#define node_supports_image_input(node) \ ++ (!!(node_desc[(node)->id].caps & V4L2_CAP_VIDEO_OUTPUT)) ++#define node_supports_meta_input(node) \ ++ (!!(node_desc[(node)->id].caps & V4L2_CAP_META_OUTPUT)) ++#define node_supports_image(node) \ ++ (node_supports_image_output(node) || node_supports_image_input(node)) ++#define node_supports_meta(node) \ ++ (node_supports_meta_output(node) || node_supports_meta_input(node)) ++ + #define is_image_output_node(node) \ +- (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ ((node)->buffer_queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + #define is_image_input_node(node) \ +- (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ ((node)->buffer_queue.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + #define is_image_node(node) \ + (is_image_output_node(node) || is_image_input_node(node)) +- + #define is_meta_output_node(node) \ +- (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_CAPTURE) ++ ((node)->buffer_queue.type == V4L2_BUF_TYPE_META_CAPTURE) + #define is_meta_input_node(node) \ +- (node_desc[(node)->id].buf_type == V4L2_BUF_TYPE_META_OUTPUT) ++ ((node)->buffer_queue.type == V4L2_BUF_TYPE_META_OUTPUT) + #define is_meta_node(node) \ + (is_meta_output_node(node) || is_meta_input_node(node)) + +@@ -250,7 +258,9 @@ struct cfe_node { + /* Pointer pointing to next v4l2_buffer */ + struct cfe_buffer *next_frm; + /* Used to store current pixel format */ +- struct v4l2_format fmt; ++ struct v4l2_format vid_fmt; ++ /* Used to store current meta format */ ++ struct v4l2_format meta_fmt; + /* Buffer queue used in video-buf */ + struct vb2_queue buffer_queue; + /* Queue of filled frames */ +@@ -433,20 +443,21 @@ static int format_show(struct seq_file * + seq_printf(s, "\nNode %u (%s) state: 0x%lx\n", i, + node_desc[i].name, state); + +- if (is_image_node(node)) ++ if (node_supports_image(node)) + seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\n" + "resolution: %ux%u\nbpl: %u\nsize: %u\n", +- V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat), +- node->fmt.fmt.pix.pixelformat, +- node->fmt.fmt.pix.width, +- node->fmt.fmt.pix.height, +- node->fmt.fmt.pix.bytesperline, +- node->fmt.fmt.pix.sizeimage); +- else ++ V4L2_FOURCC_CONV_ARGS(node->vid_fmt.fmt.pix.pixelformat), ++ node->vid_fmt.fmt.pix.pixelformat, ++ node->vid_fmt.fmt.pix.width, ++ node->vid_fmt.fmt.pix.height, ++ node->vid_fmt.fmt.pix.bytesperline, ++ node->vid_fmt.fmt.pix.sizeimage); ++ ++ if (node_supports_meta(node)) + seq_printf(s, "format: " V4L2_FOURCC_CONV " 0x%x\nsize: %u\n", +- V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat), +- node->fmt.fmt.meta.dataformat, +- node->fmt.fmt.meta.buffersize); ++ V4L2_FOURCC_CONV_ARGS(node->meta_fmt.fmt.meta.dataformat), ++ node->meta_fmt.fmt.meta.dataformat, ++ node->meta_fmt.fmt.meta.buffersize); + } + + return 0; +@@ -571,11 +582,11 @@ static void cfe_schedule_next_csi2_job(s + node_desc[node->id].name, &buf->vb.vb2_buf); + + if (is_meta_node(node)) { +- size = node->fmt.fmt.meta.buffersize; ++ size = node->meta_fmt.fmt.meta.buffersize; + stride = 0; + } else { +- size = node->fmt.fmt.pix.sizeimage; +- stride = node->fmt.fmt.pix.bytesperline; ++ size = node->vid_fmt.fmt.pix.sizeimage; ++ stride = node->vid_fmt.fmt.pix.bytesperline; + } + + addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); +@@ -867,10 +878,10 @@ static void cfe_start_channel(struct cfe + width = source_fmt->width; + height = source_fmt->height; + +- if (node->fmt.fmt.pix.pixelformat == ++ if (node->vid_fmt.fmt.pix.pixelformat == + fmt->remap[CFE_REMAP_16BIT]) + mode = CSI2_MODE_REMAP; +- else if (node->fmt.fmt.pix.pixelformat == ++ else if (node->vid_fmt.fmt.pix.pixelformat == + fmt->remap[CFE_REMAP_COMPRESSED]) { + mode = CSI2_MODE_COMPRESSED; + csi2_set_compression(&cfe->csi2, node->id, +@@ -884,7 +895,7 @@ static void cfe_start_channel(struct cfe + /* Auto arm */ + false, + /* Pack bytes */ +- node->id == CSI2_CH1_EMBEDDED ? true : false, ++ is_meta_node(node) ? true : false, + width, height); + } + +@@ -947,10 +958,11 @@ static int cfe_queue_setup(struct vb2_qu + { + struct cfe_node *node = vb2_get_drv_priv(vq); + struct cfe_device *cfe = node->cfe; +- unsigned int size = is_image_node(node) ? node->fmt.fmt.pix.sizeimage : +- node->fmt.fmt.meta.buffersize; ++ unsigned int size = is_image_node(node) ? node->vid_fmt.fmt.pix.sizeimage : ++ node->meta_fmt.fmt.meta.buffersize; + +- cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ cfe_dbg("%s: [%s] type:%u\n", __func__, node_desc[node->id].name, ++ node->buffer_queue.type); + + if (vq->num_buffers + *nbuffers < 3) + *nbuffers = 3 - vq->num_buffers; +@@ -979,8 +991,8 @@ static int cfe_buffer_prepare(struct vb2 + cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, + node_desc[node->id].name, vb); + +- size = is_image_node(node) ? node->fmt.fmt.pix.sizeimage : +- node->fmt.fmt.meta.buffersize; ++ size = is_image_node(node) ? node->vid_fmt.fmt.pix.sizeimage : ++ node->meta_fmt.fmt.meta.buffersize; + if (vb2_plane_size(vb, 0) < size) { + cfe_err("data will not fit into plane (%lu < %lu)\n", + vb2_plane_size(vb, 0), size); +@@ -995,8 +1007,8 @@ static int cfe_buffer_prepare(struct vb2 + + memcpy(&b->config, addr, sizeof(struct pisp_fe_config)); + return pisp_fe_validate_config(&cfe->fe, &b->config, +- &cfe->node[FE_OUT0].fmt, +- &cfe->node[FE_OUT1].fmt); ++ &cfe->node[FE_OUT0].vid_fmt, ++ &cfe->node[FE_OUT1].vid_fmt); + } + + return 0; +@@ -1256,7 +1268,7 @@ static int cfe_enum_fmt_vid_cap(struct f + struct cfe_device *cfe = node->cfe; + unsigned int i, j; + +- if (!is_image_output_node(node)) ++ if (!node_supports_image_output(node)) + return -EINVAL; + + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); +@@ -1292,10 +1304,10 @@ static int cfe_g_fmt(struct file *file, + + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); + +- if (f->type != node->buffer_queue.type) ++ if (!node_supports_image(node)) + return -EINVAL; + +- *f = node->fmt; ++ *f = node->vid_fmt; + + return 0; + } +@@ -1310,7 +1322,7 @@ static int try_fmt_vid_cap(struct cfe_no + f->fmt.pix.width, f->fmt.pix.height, + V4L2_FOURCC_CONV_ARGS(f->fmt.pix.pixelformat)); + +- if (!is_image_output_node(node)) ++ if (!node_supports_image_output(node)) + return -EINVAL; + + /* +@@ -1351,11 +1363,11 @@ static int cfe_s_fmt_vid_cap(struct file + if (ret) + return ret; + +- node->fmt = *f; ++ node->vid_fmt = *f; + + cfe_dbg("%s: Set %ux%u, V4L2 pix " V4L2_FOURCC_CONV "\n", __func__, +- node->fmt.fmt.pix.width, node->fmt.fmt.pix.height, +- V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.pix.pixelformat)); ++ node->vid_fmt.fmt.pix.width, node->vid_fmt.fmt.pix.height, ++ V4L2_FOURCC_CONV_ARGS(node->vid_fmt.fmt.pix.pixelformat)); + + return 0; + } +@@ -1379,11 +1391,11 @@ static int cfe_enum_fmt_meta(struct file + + cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); + +- if (!is_meta_node(node) || f->index != 0) ++ if (!node_supports_meta(node) || f->index != 0) + return -EINVAL; + + switch (node->id) { +- case CSI2_CH1_EMBEDDED: ++ case CSI2_CH0...CSI2_CH3: + f->pixelformat = V4L2_META_FMT_SENSOR_DATA; + return 0; + case FE_STATS: +@@ -1399,8 +1411,11 @@ static int cfe_enum_fmt_meta(struct file + + static int try_fmt_meta(struct cfe_node *node, struct v4l2_format *f) + { ++ if (!node_supports_meta(node)) ++ return -EINVAL; ++ + switch (node->id) { +- case CSI2_CH1_EMBEDDED: ++ case CSI2_CH0...CSI2_CH3: + f->fmt.meta.dataformat = V4L2_META_FMT_SENSOR_DATA; + if (!f->fmt.meta.buffersize) + f->fmt.meta.buffersize = DEFAULT_EMBEDDED_SIZE; +@@ -1422,6 +1437,21 @@ static int try_fmt_meta(struct cfe_node + return -EINVAL; + } + ++static int cfe_g_fmt_meta(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct cfe_node *node = video_drvdata(file); ++ struct cfe_device *cfe = node->cfe; ++ ++ cfe_dbg("%s: [%s]\n", __func__, node_desc[node->id].name); ++ ++ if (!node_supports_meta(node)) ++ return -EINVAL; ++ ++ *f = node->meta_fmt; ++ ++ return 0; ++} ++ + static int cfe_s_fmt_meta(struct file *file, void *priv, struct v4l2_format *f) + { + struct cfe_node *node = video_drvdata(file); +@@ -1434,17 +1464,17 @@ static int cfe_s_fmt_meta(struct file *f + if (vb2_is_busy(q)) + return -EBUSY; + +- if (f->type != node->buffer_queue.type) ++ if (!node_supports_meta(node)) + return -EINVAL; + + ret = try_fmt_meta(node, f); + if (ret) + return ret; + +- node->fmt = *f; ++ node->meta_fmt = *f; + + cfe_dbg("%s: Set " V4L2_FOURCC_CONV "\n", __func__, +- V4L2_FOURCC_CONV_ARGS(node->fmt.fmt.meta.dataformat)); ++ V4L2_FOURCC_CONV_ARGS(node->meta_fmt.fmt.meta.dataformat)); + + return 0; + } +@@ -1491,6 +1521,52 @@ static int cfe_enum_framesizes(struct fi + return 0; + } + ++static int cfe_vb2_ioctl_reqbufs(struct file *file, void *priv, ++ struct v4l2_requestbuffers *p) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct cfe_node *node = video_get_drvdata(vdev); ++ struct cfe_device *cfe = node->cfe; ++ int ret; ++ ++ cfe_dbg("%s: [%s] type:%u\n", __func__, node_desc[node->id].name, ++ p->type); ++ ++ if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && ++ p->type != V4L2_BUF_TYPE_META_CAPTURE && ++ p->type != V4L2_BUF_TYPE_META_OUTPUT) ++ return -EINVAL; ++ ++ ret = vb2_queue_change_type(vdev->queue, p->type); ++ if (ret) ++ return ret; ++ ++ return vb2_ioctl_reqbufs(file, priv, p); ++} ++ ++static int cfe_vb2_ioctl_create_bufs(struct file *file, void *priv, ++ struct v4l2_create_buffers *p) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct cfe_node *node = video_get_drvdata(vdev); ++ struct cfe_device *cfe = node->cfe; ++ int ret; ++ ++ cfe_dbg("%s: [%s] type:%u\n", __func__, node_desc[node->id].name, ++ p->format.type); ++ ++ if (p->format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE && ++ p->format.type != V4L2_BUF_TYPE_META_CAPTURE && ++ p->format.type != V4L2_BUF_TYPE_META_OUTPUT) ++ return -EINVAL; ++ ++ ret = vb2_queue_change_type(vdev->queue, p->format.type); ++ if (ret) ++ return ret; ++ ++ return vb2_ioctl_create_bufs(file, priv, p); ++} ++ + static int cfe_subscribe_event(struct v4l2_fh *fh, + const struct v4l2_event_subscription *sub) + { +@@ -1498,12 +1574,13 @@ static int cfe_subscribe_event(struct v4 + + switch (sub->type) { + case V4L2_EVENT_FRAME_SYNC: +- if (!is_image_output_node(node)) ++ if (!node_supports_image_output(node)) + break; + + return v4l2_event_subscribe(fh, sub, 2, NULL); + case V4L2_EVENT_SOURCE_CHANGE: +- if (is_meta_input_node(node)) ++ if (!node_supports_image_output(node) && ++ !node_supports_meta_output(node)) + break; + + return v4l2_event_subscribe(fh, sub, 4, NULL); +@@ -1520,19 +1597,19 @@ static const struct v4l2_ioctl_ops cfe_i + .vidioc_try_fmt_vid_cap = cfe_try_fmt_vid_cap, + + .vidioc_enum_fmt_meta_cap = cfe_enum_fmt_meta, +- .vidioc_g_fmt_meta_cap = cfe_g_fmt, ++ .vidioc_g_fmt_meta_cap = cfe_g_fmt_meta, + .vidioc_s_fmt_meta_cap = cfe_s_fmt_meta, + .vidioc_try_fmt_meta_cap = cfe_try_fmt_meta, + + .vidioc_enum_fmt_meta_out = cfe_enum_fmt_meta, +- .vidioc_g_fmt_meta_out = cfe_g_fmt, ++ .vidioc_g_fmt_meta_out = cfe_g_fmt_meta, + .vidioc_s_fmt_meta_out = cfe_s_fmt_meta, + .vidioc_try_fmt_meta_out = cfe_try_fmt_meta, + + .vidioc_enum_framesizes = cfe_enum_framesizes, + +- .vidioc_reqbufs = vb2_ioctl_reqbufs, +- .vidioc_create_bufs = vb2_ioctl_create_bufs, ++ .vidioc_reqbufs = cfe_vb2_ioctl_reqbufs, ++ .vidioc_create_bufs = cfe_vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, +@@ -1610,7 +1687,7 @@ static int cfe_video_link_validate(struc + } + + if (is_image_output_node(node)) { +- struct v4l2_pix_format *pix_fmt = &node->fmt.fmt.pix; ++ struct v4l2_pix_format *pix_fmt = &node->vid_fmt.fmt.pix; + const struct cfe_fmt *fmt = NULL; + unsigned int i; + +@@ -1636,8 +1713,8 @@ static int cfe_video_link_validate(struc + ret = -EINVAL; + goto out; + } +- } else if (node->id == CSI2_CH1_EMBEDDED) { +- struct v4l2_meta_format *meta_fmt = &node->fmt.fmt.meta; ++ } else if (is_csi2_node(node) && is_meta_output_node(node)) { ++ struct v4l2_meta_format *meta_fmt = &node->meta_fmt.fmt.meta; + + if (source_fmt->width * source_fmt->height != + meta_fmt->buffersize || +@@ -1698,15 +1775,17 @@ static int cfe_video_link_notify(struct + + if (link->source->entity != csi2) + return 0; +- if (link->sink->index != 0) ++ if (link->sink->entity != fe) + return 0; +- if (link->source->index == node_desc[CSI2_CH1_EMBEDDED].link_pad) ++ if (link->sink->index != 0) + return 0; + + cfe->fe_csi2_channel = -1; +- if (link->sink->entity == fe && (link->flags & MEDIA_LNK_FL_ENABLED)) { ++ if (link->flags & MEDIA_LNK_FL_ENABLED) { + if (link->source->index == node_desc[CSI2_CH0].link_pad) + cfe->fe_csi2_channel = CSI2_CH0; ++ else if (link->source->index == node_desc[CSI2_CH1].link_pad) ++ cfe->fe_csi2_channel = CSI2_CH1; + else if (link->source->index == node_desc[CSI2_CH2].link_pad) + cfe->fe_csi2_channel = CSI2_CH2; + else if (link->source->index == node_desc[CSI2_CH3].link_pad) +@@ -1763,30 +1842,42 @@ static int cfe_register_node(struct cfe_ + node->cfe = cfe; + node->id = id; + +- if (is_image_node(node)) { ++ if (node_supports_image(node)) { ++ if (node_supports_image_output(node)) ++ node->vid_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ else ++ node->vid_fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ + fmt = find_format_by_code(cfe_default_format.code); + if (!fmt) { + cfe_err("Failed to find format code\n"); + return -EINVAL; + } + +- node->fmt.fmt.pix.pixelformat = fmt->fourcc; +- v4l2_fill_pix_format(&node->fmt.fmt.pix, &cfe_default_format); ++ node->vid_fmt.fmt.pix.pixelformat = fmt->fourcc; ++ v4l2_fill_pix_format(&node->vid_fmt.fmt.pix, &cfe_default_format); + +- ret = try_fmt_vid_cap(node, &node->fmt); ++ ret = try_fmt_vid_cap(node, &node->vid_fmt); + if (ret) + return ret; +- } else { +- ret = try_fmt_meta(node, &node->fmt); ++ } ++ ++ if (node_supports_meta(node)) { ++ if (node_supports_meta_output(node)) ++ node->meta_fmt.type = V4L2_BUF_TYPE_META_CAPTURE; ++ else ++ node->meta_fmt.type = V4L2_BUF_TYPE_META_OUTPUT; ++ ++ ret = try_fmt_meta(node, &node->meta_fmt); + if (ret) + return ret; + } +- node->fmt.type = node_desc[id].buf_type; + + mutex_init(&node->lock); + + q = &node->buffer_queue; +- q->type = node_desc[id].buf_type; ++ q->type = node_supports_image(node) ? node->vid_fmt.type : ++ node->meta_fmt.type; + q->io_modes = VB2_MMAP | VB2_DMABUF; + q->drv_priv = node; + q->ops = &cfe_video_qops; +@@ -1812,11 +1903,13 @@ static int cfe_register_node(struct cfe_ + vdev->ioctl_ops = &cfe_ioctl_ops; + vdev->entity.ops = &cfe_media_entity_ops; + vdev->v4l2_dev = &cfe->v4l2_dev; +- vdev->vfl_dir = (is_image_output_node(node) || is_meta_output_node(node)) +- ? VFL_DIR_RX : VFL_DIR_TX; ++ vdev->vfl_dir = (node_supports_image_output(node) || ++ node_supports_meta_output(node)) ? ++ VFL_DIR_RX : ++ VFL_DIR_TX; + vdev->queue = q; + vdev->lock = &node->lock; +- vdev->device_caps = node_desc[id].cap; ++ vdev->device_caps = node_desc[id].caps; + vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_IO_MC; + + /* Define the device names */ +@@ -1829,7 +1922,7 @@ static int cfe_register_node(struct cfe_ + node->pad.flags = node_desc[id].pad_flags; + media_entity_pads_init(&vdev->entity, 1, &node->pad); + +- if (is_meta_node(node)) { ++ if (!node_supports_image(node)) { + v4l2_disable_ioctl(&node->video_dev, + VIDIOC_ENUM_FRAMEINTERVALS); + v4l2_disable_ioctl(&node->video_dev, +@@ -1907,7 +2000,7 @@ static int cfe_link_node_pads(struct cfe + if (ret) + return ret; + +- if (node->id != CSI2_CH1_EMBEDDED) { ++ if (node_supports_image(node)) { + /* CSI2 channel # -> FE Input */ + ret = media_create_pad_link(&cfe->csi2.sd.entity, + node_desc[i].link_pad, diff --git a/target/linux/bcm27xx/patches-6.1/950-1209-media-rp1-Drop-LE-handling.patch b/target/linux/bcm27xx/patches-6.1/950-1209-media-rp1-Drop-LE-handling.patch new file mode 100644 index 0000000000..1d6e396f1c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1209-media-rp1-Drop-LE-handling.patch @@ -0,0 +1,127 @@ +From dad296088dffbaf55c1e61cbdc3f7cb1eb504ca6 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Tue, 16 May 2023 15:51:54 +0300 +Subject: [PATCH] media: rp1: Drop LE handling + +The driver registers for line-end interrupts, but never uses them. This +just causes extra interrupt load, with more complexity in the driver. + +Drop the LE handling. It can easily be added back if later needed. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 6 ++-- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 28 ++++--------------- + .../media/platform/raspberrypi/rp1_cfe/csi2.h | 2 +- + 3 files changed, 10 insertions(+), 26 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -734,13 +734,13 @@ static irqreturn_t cfe_isr(int irq, void + { + struct cfe_device *cfe = dev; + unsigned int i; +- bool sof[NUM_NODES] = {0}, eof[NUM_NODES] = {0}, lci[NUM_NODES] = {0}; ++ bool sof[NUM_NODES] = {0}, eof[NUM_NODES] = {0}; + u32 sts; + + sts = cfg_reg_read(cfe, MIPICFG_INTS); + + if (sts & MIPICFG_INT_CSI_DMA) +- csi2_isr(&cfe->csi2, sof, eof, lci); ++ csi2_isr(&cfe->csi2, sof, eof); + + if (sts & MIPICFG_INT_PISP_FE) + pisp_fe_isr(&cfe->fe, sof + CSI2_NUM_CHANNELS, +@@ -757,7 +757,7 @@ static irqreturn_t cfe_isr(int irq, void + * generate interrupts even though the node is not streaming. + */ + if (!check_state(cfe, NODE_STREAMING, i) || +- !(sof[i] || eof[i] || lci[i])) ++ !(sof[i] || eof[i])) + continue; + + /* +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -258,7 +258,7 @@ static void csi2_isr_handle_errors(struc + spin_unlock(&csi2->errors_lock); + } + +-void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci) ++void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof) + { + unsigned int i; + u32 status; +@@ -290,7 +290,6 @@ void csi2_isr(struct csi2_device *csi2, + + sof[i] = !!(status & IRQ_FS(i)); + eof[i] = !!(status & IRQ_FE_ACK(i)); +- lci[i] = !!(status & IRQ_LE_ACK(i)); + } + + if (csi2_track_errors) +@@ -405,16 +404,12 @@ void csi2_start_channel(struct csi2_devi + + csi2_dbg("%s [%u]\n", __func__, channel); + +- /* +- * Disable the channel, but ensure N != 0! Otherwise we end up with a +- * spurious LE + LE_ACK interrupt when re-enabling the channel. +- */ +- csi2_reg_write(csi2, CSI2_CH_CTRL(channel), 0x100 << __ffs(LC_MASK)); ++ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), 0); + csi2_reg_write(csi2, CSI2_CH_DEBUG(channel), 0); + csi2_reg_write(csi2, CSI2_STATUS, IRQ_CH_MASK(channel)); + +- /* Enable channel and FS/FE/LE interrupts. */ +- ctrl = DMA_EN | IRQ_EN_FS | IRQ_EN_FE_ACK | IRQ_EN_LE_ACK | PACK_LINE; ++ /* Enable channel and FS/FE interrupts. */ ++ ctrl = DMA_EN | IRQ_EN_FS | IRQ_EN_FE_ACK | PACK_LINE; + /* PACK_BYTES ensures no striding for embedded data. */ + if (pack_bytes) + ctrl |= PACK_BYTES; +@@ -423,21 +418,11 @@ void csi2_start_channel(struct csi2_devi + ctrl |= AUTO_ARM; + + if (width && height) { +- int line_int_freq = height >> 2; +- +- line_int_freq = min(max(0x80, line_int_freq), 0x3ff); +- set_field(&ctrl, line_int_freq, LC_MASK); + set_field(&ctrl, mode, CH_MODE_MASK); + csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), + (height << 16) | width); + } else { +- /* +- * Do not disable line interrupts for the embedded data channel, +- * set it to the maximum value. This avoids spamming the ISR +- * with spurious line interrupts. +- */ +- set_field(&ctrl, 0x3ff, LC_MASK); +- set_field(&ctrl, 0x00, CH_MODE_MASK); ++ set_field(&ctrl, 0x0, CH_MODE_MASK); + csi2_reg_write(csi2, CSI2_CH_FRAME_SIZE(channel), 0); + } + +@@ -452,8 +437,7 @@ void csi2_stop_channel(struct csi2_devic + csi2_dbg("%s [%u]\n", __func__, channel); + + /* Channel disable. Use FORCE to allow stopping mid-frame. */ +- csi2_reg_write(csi2, CSI2_CH_CTRL(channel), +- (0x100 << __ffs(LC_MASK)) | FORCE); ++ csi2_reg_write(csi2, CSI2_CH_CTRL(channel), FORCE); + /* Latch the above change by writing to the ADDR0 register. */ + csi2_reg_write(csi2, CSI2_CH_ADDR0(channel), 0); + /* Write this again, the HW needs it! */ +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.h +@@ -71,7 +71,7 @@ struct csi2_device { + u32 discards_dt_table[DISCARDS_TABLE_NUM_ENTRIES]; + }; + +-void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof, bool *lci); ++void csi2_isr(struct csi2_device *csi2, bool *sof, bool *eof); + void csi2_set_buffer(struct csi2_device *csi2, unsigned int channel, + dma_addr_t dmaaddr, unsigned int stride, + unsigned int size); diff --git a/target/linux/bcm27xx/patches-6.1/950-1210-media-rp1-csi2-Use-standard-link_validate.patch b/target/linux/bcm27xx/patches-6.1/950-1210-media-rp1-csi2-Use-standard-link_validate.patch new file mode 100644 index 0000000000..a3836150dc --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1210-media-rp1-csi2-Use-standard-link_validate.patch @@ -0,0 +1,75 @@ +From b6316a8450d3cb99b7599175d59b1b7f710770f5 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Tue, 3 Oct 2023 13:59:02 +0300 +Subject: [PATCH] media: rp1: csi2: Use standard link_validate + +The current csi2_link_validate() skips some important checks. Let's +rather use the standard v4l2_subdev_link_validate_default() as the +link_validate hook. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/csi2.c | 41 +------------------ + 1 file changed, 1 insertion(+), 40 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/csi2.c +@@ -462,11 +462,6 @@ void csi2_close_rx(struct csi2_device *c + csi2_reg_write(csi2, CSI2_IRQ_MASK, 0); + } + +-static struct csi2_device *to_csi2_device(struct v4l2_subdev *subdev) +-{ +- return container_of(subdev, struct csi2_device, sd); +-} +- + static int csi2_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) + { +@@ -554,45 +549,11 @@ static int csi2_pad_set_fmt(struct v4l2_ + return 0; + } + +-static int csi2_link_validate(struct v4l2_subdev *sd, struct media_link *link, +- struct v4l2_subdev_format *source_fmt, +- struct v4l2_subdev_format *sink_fmt) +-{ +- struct csi2_device *csi2 = to_csi2_device(sd); +- +- csi2_dbg("%s: link \"%s\":%u -> \"%s\":%u\n", __func__, +- link->source->entity->name, link->source->index, +- link->sink->entity->name, link->sink->index); +- +- if ((link->source->entity == &csi2->sd.entity && +- link->source->index == 1) || +- (link->sink->entity == &csi2->sd.entity && +- link->sink->index == 1)) { +- csi2_dbg("Ignore metadata pad for now\n"); +- return 0; +- } +- +- /* The width, height and code must match. */ +- if (source_fmt->format.width != sink_fmt->format.width || +- source_fmt->format.width != sink_fmt->format.width || +- source_fmt->format.code != sink_fmt->format.code) { +- csi2_err("%s: format does not match (source %ux%u 0x%x, sink %ux%u 0x%x)\n", +- __func__, +- source_fmt->format.width, source_fmt->format.height, +- source_fmt->format.code, +- sink_fmt->format.width, sink_fmt->format.height, +- sink_fmt->format.code); +- return -EPIPE; +- } +- +- return 0; +-} +- + static const struct v4l2_subdev_pad_ops csi2_subdev_pad_ops = { + .init_cfg = csi2_init_cfg, + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = csi2_pad_set_fmt, +- .link_validate = csi2_link_validate, ++ .link_validate = v4l2_subdev_link_validate_default, + }; + + static const struct media_entity_operations csi2_entity_ops = { diff --git a/target/linux/bcm27xx/patches-6.1/950-1211-media-rp1-fe-Use-standard-link_validate.patch b/target/linux/bcm27xx/patches-6.1/950-1211-media-rp1-fe-Use-standard-link_validate.patch new file mode 100644 index 0000000000..d36ea5bd52 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1211-media-rp1-fe-Use-standard-link_validate.patch @@ -0,0 +1,70 @@ +From 0eeb351222adbc5b534c86f7815ee787babc3485 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Tue, 3 Oct 2023 14:34:43 +0300 +Subject: [PATCH] media: rp1: fe: Use standard link_validate + +The current pisp_fe_link_validate() skips some important checks. Let's +rather use the standard v4l2_subdev_link_validate_default() as the +link_validate hook. + +Signed-off-by: Tomi Valkeinen +--- + .../platform/raspberrypi/rp1_cfe/pisp_fe.c | 36 +------------------ + 1 file changed, 1 insertion(+), 35 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe.c +@@ -388,11 +388,6 @@ void pisp_fe_stop(struct pisp_fe_device + pisp_fe_reg_write(fe, FE_INT_STATUS, ~0); + } + +-static struct pisp_fe_device *to_pisp_fe_device(struct v4l2_subdev *subdev) +-{ +- return container_of(subdev, struct pisp_fe_device, sd); +-} +- + static int pisp_fe_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) + { +@@ -492,40 +487,11 @@ static int pisp_fe_pad_set_fmt(struct v4 + } + } + +-static int pisp_fe_link_validate(struct v4l2_subdev *sd, +- struct media_link *link, +- struct v4l2_subdev_format *source_fmt, +- struct v4l2_subdev_format *sink_fmt) +-{ +- struct pisp_fe_device *fe = to_pisp_fe_device(sd); +- +- pisp_fe_dbg("%s: link \"%s\":%u -> \"%s\":%u\n", __func__, +- link->source->entity->name, link->source->index, +- link->sink->entity->name, link->sink->index); +- +- /* The width, height and code must match. */ +- if (source_fmt->format.width != sink_fmt->format.width || +- source_fmt->format.width != sink_fmt->format.width || +- source_fmt->format.code != sink_fmt->format.code) { +- pisp_fe_err("%s: format does not match (source %ux%u 0x%x, sink %ux%u 0x%x)\n", +- __func__, +- source_fmt->format.width, +- source_fmt->format.height, +- source_fmt->format.code, +- sink_fmt->format.width, +- sink_fmt->format.height, +- sink_fmt->format.code); +- return -EPIPE; +- } +- +- return 0; +-} +- + static const struct v4l2_subdev_pad_ops pisp_fe_subdev_pad_ops = { + .init_cfg = pisp_fe_init_cfg, + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = pisp_fe_pad_set_fmt, +- .link_validate = pisp_fe_link_validate, ++ .link_validate = v4l2_subdev_link_validate_default, + }; + + static const struct media_entity_operations pisp_fe_entity_ops = { diff --git a/target/linux/bcm27xx/patches-6.1/950-1212-media-rp1-cfe-Improve-link-validation-for-metadata.patch b/target/linux/bcm27xx/patches-6.1/950-1212-media-rp1-cfe-Improve-link-validation-for-metadata.patch new file mode 100644 index 0000000000..d85a90aac1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1212-media-rp1-cfe-Improve-link-validation-for-metadata.patch @@ -0,0 +1,61 @@ +From e0f52ccfe1e383622fb30708acd38921e84fbff4 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Tue, 3 Oct 2023 14:29:44 +0300 +Subject: [PATCH] media: rp1: cfe: Improve link validation for metadata + +Improve the link validation for metadata by: +- Allowing capture buffers that are larger than the incoming frame + (instead of requiring exact match). + +- Instead of assuming that a metadata unit ("pixel") is 8 bits, use + find_format_by_code() to get the format and use the bit depth from + there. E.g. bit depth for RAW10 metadata will be 10 bits, when we + move to the upstream metadata formats. + +Signed-off-by: Tomi Valkeinen +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 32 +++++++++++++------ + 1 file changed, 22 insertions(+), 10 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -1715,17 +1715,29 @@ static int cfe_video_link_validate(struc + } + } else if (is_csi2_node(node) && is_meta_output_node(node)) { + struct v4l2_meta_format *meta_fmt = &node->meta_fmt.fmt.meta; ++ const struct cfe_fmt *fmt; ++ u32 source_size; + +- if (source_fmt->width * source_fmt->height != +- meta_fmt->buffersize || +- source_fmt->code != MEDIA_BUS_FMT_SENSOR_DATA) { +- cfe_err("WARNING: Wrong metadata width/height/code %ux%u %08x (remote pad set to %ux%u %08x)\n", +- meta_fmt->buffersize, 1, +- MEDIA_BUS_FMT_SENSOR_DATA, +- source_fmt->width, +- source_fmt->height, +- source_fmt->code); +- /* TODO: this should throw an error eventually */ ++ fmt = find_format_by_code(source_fmt->code); ++ if (!fmt || fmt->fourcc != meta_fmt->dataformat) { ++ cfe_err("Metadata format mismatch!\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ source_size = DIV_ROUND_UP(source_fmt->width * source_fmt->height * fmt->depth, 8); ++ ++ if (source_fmt->code != MEDIA_BUS_FMT_SENSOR_DATA) { ++ cfe_err("Bad metadata mbus format\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (source_size > meta_fmt->buffersize) { ++ cfe_err("Metadata buffer too small: %u < %u\n", ++ meta_fmt->buffersize, source_size); ++ ret = -EINVAL; ++ goto out; + } + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1214-drivers-pinctrl-bcm-Kconfig-Fix-BCM2712-help.patch b/target/linux/bcm27xx/patches-6.1/950-1214-drivers-pinctrl-bcm-Kconfig-Fix-BCM2712-help.patch new file mode 100644 index 0000000000..c3e4140fa2 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1214-drivers-pinctrl-bcm-Kconfig-Fix-BCM2712-help.patch @@ -0,0 +1,24 @@ +From 046d03c87ecce5db074eae6ffa2d5298c5f7d5a7 Mon Sep 17 00:00:00 2001 +From: Leon Anavi +Date: Tue, 12 Dec 2023 13:53:37 +0200 +Subject: [PATCH] drivers/pinctrl/bcm/Kconfig: Fix BCM2712 help + +Replace "Broadcom BCM2835 GPIO" with "Broadcom BCM2712 PINCONF" +in the help message. This work was sponsored by GOVCERT.LU. + +Signed-off-by: Leon Anavi +--- + drivers/pinctrl/bcm/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pinctrl/bcm/Kconfig ++++ b/drivers/pinctrl/bcm/Kconfig +@@ -10,7 +10,7 @@ config PINCTRL_BCM2712 + select PINCONF + select GENERIC_PINCONF + help +- Say Y here to enable the Broadcom BCM2835 GPIO driver. ++ Say Y here to enable the Broadcom BCM2712 PINCONF driver. + + config PINCTRL_BCM281XX + bool "Broadcom BCM281xx pinctrl driver" diff --git a/target/linux/bcm27xx/patches-6.1/950-1216-drivers-gpu-drm-panel-fix-waveshare-panel-software-r.patch b/target/linux/bcm27xx/patches-6.1/950-1216-drivers-gpu-drm-panel-fix-waveshare-panel-software-r.patch new file mode 100644 index 0000000000..aeb63589fc --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1216-drivers-gpu-drm-panel-fix-waveshare-panel-software-r.patch @@ -0,0 +1,41 @@ +From a6872b25f18fe46ef9979f9d4a3635a9c3966afd Mon Sep 17 00:00:00 2001 +From: eng33 +Date: Mon, 11 Dec 2023 15:06:45 +0800 +Subject: [PATCH] drivers/gpu/drm/panel:fix waveshare panel software + restart/shutdown display is abnormal Fixed the screen stays white when the + user restarts or shuts down + +Signed-off-by: eng33 +--- + drivers/gpu/drm/panel/panel-waveshare-dsi.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/gpu/drm/panel/panel-waveshare-dsi.c ++++ b/drivers/gpu/drm/panel/panel-waveshare-dsi.c +@@ -362,9 +362,18 @@ static void ws_panel_remove(struct i2c_c + { + struct ws_panel *ts = i2c_get_clientdata(i2c); + ++ ws_panel_disable(&ts->base); ++ + drm_panel_remove(&ts->base); + } + ++static void ws_panel_shutdown(struct i2c_client *i2c) ++{ ++ struct ws_panel *ts = i2c_get_clientdata(i2c); ++ ++ ws_panel_disable(&ts->base); ++} ++ + static const struct of_device_id ws_panel_of_ids[] = { + { + .compatible = "waveshare,2.8inch-panel", +@@ -403,6 +412,7 @@ static struct i2c_driver ws_panel_driver + }, + .probe = ws_panel_probe, + .remove = ws_panel_remove, ++ .shutdown = ws_panel_shutdown, + }; + module_i2c_driver(ws_panel_driver); + diff --git a/target/linux/bcm27xx/patches-6.1/950-1217-firmware-psci-Pass-given-partition-number-through.patch b/target/linux/bcm27xx/patches-6.1/950-1217-firmware-psci-Pass-given-partition-number-through.patch new file mode 100644 index 0000000000..7feeb224d1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1217-firmware-psci-Pass-given-partition-number-through.patch @@ -0,0 +1,33 @@ +From 6988ae7c909dc342322a82daaa3a95b78d038305 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 11 Dec 2023 16:58:07 +0000 +Subject: [PATCH] firmware/psci: Pass given partition number through + +Pi 5 uses BL31 as its armstub file, so the reset goes via PSCI. Parse +any "reboot" parameter as a partition number to reboot into. +N.B. This code path is only used if reboot mode has been set to warm +or soft. + +Signed-off-by: Phil Elwell +--- + drivers/firmware/psci/psci.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/firmware/psci/psci.c ++++ b/drivers/firmware/psci/psci.c +@@ -314,7 +314,14 @@ static int psci_sys_reset(struct notifie + * reset_type[30:0] = 0 (SYSTEM_WARM_RESET) + * cookie = 0 (ignored by the implementation) + */ +- invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), 0, 0, 0); ++ // Allow extra arguments separated by spaces after ++ // the partition number. ++ unsigned long val; ++ u8 partition = 0; ++ ++ if (data && sscanf(data, "%lu", &val) == 1 && val < 63) ++ partition = val; ++ invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), 0, partition, 0); + } else { + invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-1218-dts-bcm2712-rpi-5-b-Enable-warm-reboot-mode.patch b/target/linux/bcm27xx/patches-6.1/950-1218-dts-bcm2712-rpi-5-b-Enable-warm-reboot-mode.patch new file mode 100644 index 0000000000..8bcf587e6d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1218-dts-bcm2712-rpi-5-b-Enable-warm-reboot-mode.patch @@ -0,0 +1,23 @@ +From 5d87d7f91cb4f1d0f391f6fe9dd0524b363b78e3 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 11 Dec 2023 17:00:56 +0000 +Subject: [PATCH] dts: bcm2712-rpi-5-b: Enable warm reboot mode + +Switch to warm reboot mode so that the partition number is preserved. + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -428,7 +428,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_g + + / { + chosen: chosen { +- bootargs = "coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; ++ bootargs = "reboot=w coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1"; + stdout-path = "serial10:115200n8"; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1222-drivers-media-i2c-imx296-imx477-Configure-tigger_mod.patch b/target/linux/bcm27xx/patches-6.1/950-1222-drivers-media-i2c-imx296-imx477-Configure-tigger_mod.patch new file mode 100644 index 0000000000..be1eb5611e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1222-drivers-media-i2c-imx296-imx477-Configure-tigger_mod.patch @@ -0,0 +1,85 @@ +From 083f39e40d980b47ab12b451d40b9f935bb22a5b Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 6 Dec 2023 14:27:57 +0000 +Subject: [PATCH] drivers: media: i2c: imx296,imx477: Configure tigger_mode + every time + +Don't assume the camera has been reset each time we start streaming, +but always write registers relating to trigger_mode, even in mode 0. + +IMX477: Stop driving XVS on stop streaming, to avoid spurious pulses. + +Signed-off-by: Nick Hollinghurst +--- + drivers/media/i2c/imx296.c | 9 +++++---- + drivers/media/i2c/imx477.c | 29 ++++++++++++++--------------- + 2 files changed, 19 insertions(+), 19 deletions(-) + +--- a/drivers/media/i2c/imx296.c ++++ b/drivers/media/i2c/imx296.c +@@ -650,10 +650,11 @@ 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); +- } ++ /* external trigger mode: 0=normal, 1=triggered */ ++ imx296_write(sensor, IMX296_CTRL0B, ++ (trigger_mode == 1) ? IMX296_CTRL0B_TRIGEN : 0, &ret); ++ imx296_write(sensor, IMX296_LOWLAGTRG, ++ (trigger_mode == 1) ? IMX296_LOWLAGTRG_FAST : 0, &ret); + + imx296_write(sensor, IMX296_CTRL0A, 0, &ret); + +--- a/drivers/media/i2c/imx477.c ++++ b/drivers/media/i2c/imx477.c +@@ -1742,26 +1742,21 @@ static int imx477_start_streaming(struct + imx477_write_reg(imx477, 0x0b05, IMX477_REG_VALUE_08BIT, !!dpc_enable); + imx477_write_reg(imx477, 0x0b06, IMX477_REG_VALUE_08BIT, !!dpc_enable); + +- /* Set vsync trigger mode */ +- if (trigger_mode != 0) { +- /* trigger_mode == 1 for source, 2 for sink */ +- const u32 val = (trigger_mode == 1) ? 1 : 0; +- +- imx477_write_reg(imx477, IMX477_REG_MC_MODE, +- IMX477_REG_VALUE_08BIT, 1); +- imx477_write_reg(imx477, IMX477_REG_MS_SEL, +- IMX477_REG_VALUE_08BIT, val); +- imx477_write_reg(imx477, IMX477_REG_XVS_IO_CTRL, +- IMX477_REG_VALUE_08BIT, val); +- imx477_write_reg(imx477, IMX477_REG_EXTOUT_EN, +- IMX477_REG_VALUE_08BIT, val); +- } +- + /* Apply customized values from user */ + ret = __v4l2_ctrl_handler_setup(imx477->sd.ctrl_handler); + if (ret) + return ret; + ++ /* Set vsync trigger mode: 0=standalone, 1=source, 2=sink */ ++ imx477_write_reg(imx477, IMX477_REG_MC_MODE, ++ IMX477_REG_VALUE_08BIT, (trigger_mode > 0) ? 1 : 0); ++ imx477_write_reg(imx477, IMX477_REG_MS_SEL, ++ IMX477_REG_VALUE_08BIT, (trigger_mode <= 1) ? 1 : 0); ++ imx477_write_reg(imx477, IMX477_REG_XVS_IO_CTRL, ++ IMX477_REG_VALUE_08BIT, (trigger_mode == 1) ? 1 : 0); ++ imx477_write_reg(imx477, IMX477_REG_EXTOUT_EN, ++ IMX477_REG_VALUE_08BIT, (trigger_mode == 1) ? 1 : 0); ++ + /* set stream on register */ + return imx477_write_reg(imx477, IMX477_REG_MODE_SELECT, + IMX477_REG_VALUE_08BIT, IMX477_MODE_STREAMING); +@@ -1778,6 +1773,10 @@ static void imx477_stop_streaming(struct + IMX477_REG_VALUE_08BIT, IMX477_MODE_STANDBY); + if (ret) + dev_err(&client->dev, "%s failed to set stream\n", __func__); ++ ++ /* Stop driving XVS out (there is still a weak pull-up) */ ++ imx477_write_reg(imx477, IMX477_REG_EXTOUT_EN, ++ IMX477_REG_VALUE_08BIT, 0); + } + + static int imx477_set_stream(struct v4l2_subdev *sd, int enable) diff --git a/target/linux/bcm27xx/patches-6.1/950-1223-overlays-Add-always-on-parameter-to-imx477-and-imx29.patch b/target/linux/bcm27xx/patches-6.1/950-1223-overlays-Add-always-on-parameter-to-imx477-and-imx29.patch new file mode 100644 index 0000000000..d705df6f40 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1223-overlays-Add-always-on-parameter-to-imx477-and-imx29.patch @@ -0,0 +1,99 @@ +From 3ed57f25f3074f6abfe570fc11aa7d370fdc499a Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Wed, 6 Dec 2023 14:38:03 +0000 +Subject: [PATCH] overlays: Add "always-on" parameter to imx477 and imx296 + +Leave the camera's power supplies up, to prevent the camera +clamping its 1.8V digital I/Os to ground. This may be useful +when synchronizing multiple camera systems using XVS or XTRIG. + +Signed-off-by: Nick Hollinghurst +--- + arch/arm/boot/dts/overlays/README | 6 ++++++ + arch/arm/boot/dts/overlays/imx296-overlay.dts | 9 +++++++++ + arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi | 9 +++++++++ + 3 files changed, 24 insertions(+) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -2520,6 +2520,8 @@ Params: rotation Mounting + clock-frequency Sets the clock frequency to match that used on + the board, which should be one of 54000000 + (the default), 37125000 or 74250000. ++ always-on Leave the regulator powered up, to stop the ++ camera clamping I/Os such as XTRIG to 0V. + + + Name: imx327 +@@ -2558,6 +2560,8 @@ Params: rotation Mounting + configuring the sensor (default on) + cam0 Adopt the default configuration for CAM0 on a + Compute Module (CSI0, i2c_vc, and cam0_reg). ++ always-on Leave the regulator powered up, to stop the ++ camera clamping I/Os such as XVS to 0V. + + + Name: imx462 +@@ -2596,6 +2600,8 @@ Params: rotation Mounting + configuring the sensor (default on) + cam0 Adopt the default configuration for CAM0 on a + Compute Module (CSI0, i2c_vc, and cam0_reg). ++ always-on Leave the regulator powered up, to stop the ++ camera clamping I/Os such as XVS to 0V. + + + Name: imx519 +--- a/arch/arm/boot/dts/overlays/imx296-overlay.dts ++++ b/arch/arm/boot/dts/overlays/imx296-overlay.dts +@@ -37,6 +37,13 @@ + }; + }; + ++ reg_alwayson_frag: fragment@99 { ++ target = <&cam1_reg>; ++ __dormant__ { ++ regulator-always-on; ++ }; ++ }; ++ + i2c_frag: fragment@100 { + target = <&i2c_csi_dsi>; + __overlay__ { +@@ -98,8 +105,10 @@ + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <®_frag>, "target:0=",<&cam0_reg>, ++ <®_alwayson_frag>, "target:0=",<&cam0_reg>, + <&imx296>, "clocks:0=",<&cam0_clk>, + <&imx296>, "avdd-supply:0=",<&cam0_reg>; + clock-frequency = <&clk_over>, "clock-frequency:0"; ++ always-on = <0>, "+99"; + }; + }; +--- a/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi ++++ b/arch/arm/boot/dts/overlays/imx477_378-overlay.dtsi +@@ -33,6 +33,13 @@ + }; + }; + ++ reg_alwayson_frag: fragment@99 { ++ target = <&cam1_reg>; ++ __dormant__ { ++ regulator-always-on; ++ }; ++ }; ++ + i2c_frag: fragment@100 { + target = <&i2c_csi_dsi>; + __overlay__ { +@@ -69,8 +76,10 @@ + <&csi_frag>, "target:0=",<&csi0>, + <&clk_frag>, "target:0=",<&cam0_clk>, + <®_frag>, "target:0=",<&cam0_reg>, ++ <®_alwayson_frag>, "target:0=",<&cam0_reg>, + <&cam_node>, "clocks:0=",<&cam0_clk>, + <&cam_node>, "VANA-supply:0=",<&cam0_reg>; ++ always-on = <0>, "+99"; + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1224-input-edt-ft5x06-Correct-prefix-length-in-snprintf.patch b/target/linux/bcm27xx/patches-6.1/950-1224-input-edt-ft5x06-Correct-prefix-length-in-snprintf.patch new file mode 100644 index 0000000000..6fb8fc0b95 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1224-input-edt-ft5x06-Correct-prefix-length-in-snprintf.patch @@ -0,0 +1,29 @@ +From e0ecfaf1abfd5ef63ceec7606352020a80a2742b Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 18 Dec 2023 11:49:36 +0000 +Subject: [PATCH] input: edt-ft5x06: Correct prefix length in snprintf + +snprintf takes the length of the array that we can print into, +and has to fit the NULL terminator in there too. +Printing the prefix is generally "12-3456 " which is 8 desired +characters (the length of EDT_NAME_PREFIX_LEN) and the NULL. +The space is therefore being truncated to fit the NULL in. + +Increase the length snprintf is allowed to use. + +Signed-off-by: Dave Stevenson +--- + drivers/input/touchscreen/edt-ft5x06.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -966,7 +966,7 @@ static int edt_ft5x06_ts_identify(struct + char *model_name = tsdata->name; + char *fw_version = tsdata->fw_version; + +- snprintf(model_name, EDT_NAME_PREFIX_LEN, "%s ", dev_name(&client->dev)); ++ snprintf(model_name, EDT_NAME_PREFIX_LEN + 1, "%s ", dev_name(&client->dev)); + model_name += strlen(model_name); + + /* see what we find if we assume it is a M06 * diff --git a/target/linux/bcm27xx/patches-6.1/950-1225-ARM-dts-bcm2712-rpi-5-b-Allow-RTC-to-be-disabled.patch b/target/linux/bcm27xx/patches-6.1/950-1225-ARM-dts-bcm2712-rpi-5-b-Allow-RTC-to-be-disabled.patch new file mode 100644 index 0000000000..5a3e6df555 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1225-ARM-dts-bcm2712-rpi-5-b-Allow-RTC-to-be-disabled.patch @@ -0,0 +1,38 @@ +From da5fd98469edd797ed77d9a8690a608c6b54f9e6 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 19 Dec 2023 14:55:21 +0000 +Subject: [PATCH] ARM: dts: bcm2712-rpi-5-b: Allow RTC to be disabled + +Add a dtparam "rtc", so that "dtparam=rtc=off" can be used to disable +the Pi 5's onboard RTC. + +See: https://forums.raspberrypi.com/viewtopic.php?t=361813 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 1 + + arch/arm/boot/dts/overlays/README | 3 +++ + 2 files changed, 4 insertions(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -819,6 +819,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; + pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; + random = <&random>, "status"; ++ rtc = <&rpi_rtc>, "status"; + rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0"; + spi = <&spi0>, "status"; + suspend = <&pwr_key>, "linux,code:0=205"; +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -307,6 +307,9 @@ Params: + random Set to "on" to enable the hardware random + number generator (default "on") + ++ rtc Set to "off" to disable the onboard Real Time ++ Clock (2712 only, default "on") ++ + rtc_bbat_vchg Set the RTC backup battery charging voltage in + microvolts. If set to 0 or not specified, the + trickle charger is disabled. diff --git a/target/linux/bcm27xx/patches-6.1/950-1226-i2c-designware-Look-for-CNT-values-in-DT.patch b/target/linux/bcm27xx/patches-6.1/950-1226-i2c-designware-Look-for-CNT-values-in-DT.patch new file mode 100644 index 0000000000..ccba16ad8e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1226-i2c-designware-Look-for-CNT-values-in-DT.patch @@ -0,0 +1,57 @@ +From 0a09088e24c013ef608b1bb79501ef890cefc767 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 19 Dec 2023 11:16:25 +0000 +Subject: [PATCH] i2c: designware: Look for *CNT values in DT + +The i2c-designware driver supports reading precise timing values from +ACPI, but the Device Tree support relies on a combination of standard +rise and fall times and hard-coded minimum timings. The result of this +is that it is difficult to get optimum timings, particularly given that +the values are bus speed-specific and only one set can be stored in +DT at a time. + +Add support for initialisation from DT that is similar to that for +ACPI. + +Signed-off-by: Phil Elwell +--- + drivers/i2c/busses/i2c-designware-platdrv.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/drivers/i2c/busses/i2c-designware-platdrv.c ++++ b/drivers/i2c/busses/i2c-designware-platdrv.c +@@ -132,9 +132,18 @@ static int mscc_twi_set_sda_hold_time(st + return 0; + } + ++static void dw_i2c_read_of_cnt(struct device_node *np, const char *name, u16 *pval) ++{ ++ u32 val; ++ ++ if (!of_property_read_u32(np, name, &val)) ++ *pval = (u16)val; ++} ++ + static int dw_i2c_of_configure(struct platform_device *pdev) + { + struct dw_i2c_dev *dev = platform_get_drvdata(pdev); ++ struct device_node *np = pdev->dev.of_node; + + switch (dev->flags & MODEL_MASK) { + case MODEL_MSCC_OCELOT: +@@ -146,6 +155,15 @@ static int dw_i2c_of_configure(struct pl + break; + } + ++ dw_i2c_read_of_cnt(np, "snps,ss_hcnt", &dev->ss_hcnt); ++ dw_i2c_read_of_cnt(np, "snps,ss_lcnt", &dev->ss_lcnt); ++ dw_i2c_read_of_cnt(np, "snps,fs_hcnt", &dev->fs_hcnt); ++ dw_i2c_read_of_cnt(np, "snps,fs_lcnt", &dev->fs_lcnt); ++ dw_i2c_read_of_cnt(np, "snps,fp_hcnt", &dev->fp_hcnt); ++ dw_i2c_read_of_cnt(np, "snps,fp_lcnt", &dev->fp_lcnt); ++ dw_i2c_read_of_cnt(np, "snps,hs_hcnt", &dev->hs_hcnt); ++ dw_i2c_read_of_cnt(np, "snps,hs_lcnt", &dev->hs_lcnt); ++ + return 0; + } + diff --git a/target/linux/bcm27xx/patches-6.1/950-1227-dts-rp1-Add-I2C-timings.patch b/target/linux/bcm27xx/patches-6.1/950-1227-dts-rp1-Add-I2C-timings.patch new file mode 100644 index 0000000000..892f31ec9f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1227-dts-rp1-Add-I2C-timings.patch @@ -0,0 +1,103 @@ +From 660d569b1a623e4b64350e608bbf8bc2cc6332e9 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 19 Dec 2023 11:27:20 +0000 +Subject: [PATCH] dts: rp1: Add I2C timings + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/rp1.dtsi | 42 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +--- a/arch/arm/boot/dts/rp1.dtsi ++++ b/arch/arm/boot/dts/rp1.dtsi +@@ -305,6 +305,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -313,6 +319,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -321,6 +333,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -329,6 +347,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -337,6 +361,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -345,6 +375,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + +@@ -353,6 +389,12 @@ + compatible = "snps,designware-i2c"; + interrupts = ; + clocks = <&rp1_clocks RP1_CLK_SYS>; ++ snps,ss_hcnt = <978>; ++ snps,ss_lcnt = <990>; ++ snps,fs_hcnt = <200>; ++ snps,fs_lcnt = <268>; ++ snps,fp_hcnt = <60>; ++ snps,fp_lcnt = <107>; + status = "disabled"; + }; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1228-drivers-media-pisp_be-pisp_fe-Update-UAPI-header-lic.patch b/target/linux/bcm27xx/patches-6.1/950-1228-drivers-media-pisp_be-pisp_fe-Update-UAPI-header-lic.patch new file mode 100644 index 0000000000..fc77e4d1cf --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1228-drivers-media-pisp_be-pisp_fe-Update-UAPI-header-lic.patch @@ -0,0 +1,58 @@ +From 74c6c159c2b499bdf3c39961bd40eb9243624226 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Wed, 29 Nov 2023 13:09:05 +0000 +Subject: [PATCH] drivers: media: pisp_be: pisp_fe: Update UAPI header licenses + +Update the license tags on the pisp UAPI header files with the +"Linux-syscall-note" clause. Also replace the "GPL-2.0" tag with the +preferred "GPL-2.0-only" tag. + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h | 2 +- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h | 2 +- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h | 2 +- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h | 2 +- + drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h | 2 +- + 5 files changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0-only */ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* + * PiSP Back End configuration definitions. + * +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_common.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* + * RP1 PiSP common definitions. + * +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_fe_config.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* + * RP1 PiSP Front End Driver Configuration structures + * +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_statistics.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* + * RP1 PiSP Front End statistics definitions + * +--- a/drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/pisp_types.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ + /* + * RP1 PiSP Front End image definitions. + * diff --git a/target/linux/bcm27xx/patches-6.1/950-1229-drivers-media-cfe-Add-more-robust-ISR-handlers.patch b/target/linux/bcm27xx/patches-6.1/950-1229-drivers-media-cfe-Add-more-robust-ISR-handlers.patch new file mode 100644 index 0000000000..b79cad417f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1229-drivers-media-cfe-Add-more-robust-ISR-handlers.patch @@ -0,0 +1,207 @@ +From 6fb7a0b4c1dd6cf5b12ec2b2c197dcf8e58cd2b9 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Mon, 18 Dec 2023 09:52:45 +0000 +Subject: [PATCH] drivers: media: cfe: Add more robust ISR handlers + +Update the ISR logic to be more robust to sensors in problematic states +where interrupts may start arriving overlapped and/or missing. + +1) Test for cur_frame in the FE handler, and if present, dequeue it in +an error state so that it does not get orphaned. + +2) Move the sequence counter and timestamp variables to the node +structures. This allows the ISR to track channels running ahead when +interrupts arrive unordered. + +3) Add a test to ensure we don't have a spurios (but harmlesS) call to +the FE handler in some circumstances. + +Signed-off-by: Naushir Patuck +--- + .../media/platform/raspberrypi/rp1_cfe/cfe.c | 92 ++++++++++--------- + 1 file changed, 49 insertions(+), 43 deletions(-) + +--- a/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c ++++ b/drivers/media/platform/raspberrypi/rp1_cfe/cfe.c +@@ -272,6 +272,8 @@ struct cfe_node { + /* Pointer to the parent handle */ + struct cfe_device *cfe; + struct media_pad pad; ++ unsigned int fs_count; ++ u64 ts; + }; + + struct cfe_device { +@@ -311,9 +313,6 @@ struct cfe_device { + struct pisp_fe_device fe; + + int fe_csi2_channel; +- +- unsigned int sequence; +- u64 ts; + }; + + static inline bool is_fe_enabled(struct cfe_device *cfe) +@@ -393,17 +392,6 @@ static bool test_all_nodes(struct cfe_de + return true; + } + +-static void clear_all_nodes(struct cfe_device *cfe, unsigned long precond, +- unsigned long state) +-{ +- unsigned int i; +- +- for (i = 0; i < NUM_NODES; i++) { +- if (check_state(cfe, precond, i)) +- clear_state(cfe, state, i); +- } +-} +- + static int mipi_cfg_regs_show(struct seq_file *s, void *data) + { + struct cfe_device *cfe = s->private; +@@ -656,22 +644,22 @@ static void cfe_prepare_next_job(struct + } + + static void cfe_process_buffer_complete(struct cfe_node *node, +- unsigned int sequence) ++ enum vb2_buffer_state state) + { + struct cfe_device *cfe = node->cfe; + + cfe_dbg_verbose("%s: [%s] buffer:%p\n", __func__, + node_desc[node->id].name, &node->cur_frm->vb.vb2_buf); + +- node->cur_frm->vb.sequence = sequence; +- vb2_buffer_done(&node->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); ++ node->cur_frm->vb.sequence = node->fs_count - 1; ++ vb2_buffer_done(&node->cur_frm->vb.vb2_buf, state); + } + + static void cfe_queue_event_sof(struct cfe_node *node) + { + struct v4l2_event event = { + .type = V4L2_EVENT_FRAME_SYNC, +- .u.frame_sync.frame_sequence = node->cfe->sequence, ++ .u.frame_sync.frame_sequence = node->fs_count - 1, + }; + + v4l2_event_queue(&node->video_dev, &event); +@@ -680,28 +668,53 @@ static void cfe_queue_event_sof(struct c + static void cfe_sof_isr_handler(struct cfe_node *node) + { + struct cfe_device *cfe = node->cfe; ++ bool matching_fs = true; ++ unsigned int i; + + cfe_dbg_verbose("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, +- cfe->sequence); +- +- node->cur_frm = node->next_frm; +- node->next_frm = NULL; ++ node->fs_count); + + /* +- * If this is the first node to see a frame start, sample the +- * timestamp to use for all frames across all channels. ++ * If the sensor is producing unexpected frame event ordering over a ++ * sustained period of time, guard against the possibility of coming ++ * here and orphaning the cur_frm if it's not been dequeued already. ++ * Unfortunately, there is not enough hardware state to tell if this ++ * may have occurred. + */ +- if (!test_any_node(cfe, NODE_STREAMING | FS_INT)) +- cfe->ts = ktime_get_ns(); ++ if (WARN(node->cur_frm, "%s: [%s] Orphanded frame at seq %u\n", ++ __func__, node_desc[node->id].name, node->fs_count)) ++ cfe_process_buffer_complete(node, VB2_BUF_STATE_ERROR); + +- set_state(cfe, FS_INT, node->id); ++ node->cur_frm = node->next_frm; ++ node->next_frm = NULL; ++ node->fs_count++; + +- /* If all nodes have seen a frame start, we can queue another job. */ +- if (test_all_nodes(cfe, NODE_STREAMING, FS_INT)) ++ node->ts = ktime_get_ns(); ++ for (i = 0; i < NUM_NODES; i++) { ++ if (!check_state(cfe, NODE_STREAMING, i) || i == node->id) ++ continue; ++ /* ++ * This checks if any other node has seen a FS. If yes, use the ++ * same timestamp, eventually across all node buffers. ++ */ ++ if (cfe->node[i].fs_count >= node->fs_count) ++ node->ts = cfe->node[i].ts; ++ /* ++ * This checks if all other node have seen a matching FS. If ++ * yes, we can flag another job to be queued. ++ */ ++ if (matching_fs && cfe->node[i].fs_count != node->fs_count) ++ matching_fs = false; ++ } ++ ++ if (matching_fs) + cfe->job_queued = false; + + if (node->cur_frm) +- node->cur_frm->vb.vb2_buf.timestamp = cfe->ts; ++ node->cur_frm->vb.vb2_buf.timestamp = node->ts; ++ ++ set_state(cfe, FS_INT, node->id); ++ clear_state(cfe, FE_INT, node->id); + + if (is_image_output_node(node)) + cfe_queue_event_sof(node); +@@ -712,22 +725,14 @@ static void cfe_eof_isr_handler(struct c + struct cfe_device *cfe = node->cfe; + + cfe_dbg_verbose("%s: [%s] seq %u\n", __func__, node_desc[node->id].name, +- cfe->sequence); ++ node->fs_count - 1); + + if (node->cur_frm) +- cfe_process_buffer_complete(node, cfe->sequence); ++ cfe_process_buffer_complete(node, VB2_BUF_STATE_DONE); + + node->cur_frm = NULL; + set_state(cfe, FE_INT, node->id); +- +- /* +- * If all nodes have seen a frame end, we can increment +- * the sequence counter now. +- */ +- if (test_all_nodes(cfe, NODE_STREAMING, FE_INT)) { +- cfe->sequence++; +- clear_all_nodes(cfe, NODE_STREAMING, FE_INT | FS_INT); +- } ++ clear_state(cfe, FS_INT, node->id); + } + + static irqreturn_t cfe_isr(int irq, void *dev) +@@ -794,7 +799,8 @@ static irqreturn_t cfe_isr(int irq, void + * frame first before the FS handler for the current + * frame. + */ +- if (check_state(cfe, FS_INT, node->id)) { ++ if (check_state(cfe, FS_INT, node->id) && ++ !check_state(cfe, FE_INT, node->id)) { + cfe_dbg("%s: [%s] Handling missing previous FE interrupt\n", + __func__, node_desc[node->id].name); + cfe_eof_isr_handler(node); +@@ -1131,6 +1137,7 @@ static int cfe_start_streaming(struct vb + + clear_state(cfe, FS_INT | FE_INT, node->id); + set_state(cfe, NODE_STREAMING, node->id); ++ node->fs_count = 0; + cfe_start_channel(node); + + if (!test_all_nodes(cfe, NODE_ENABLED, NODE_STREAMING)) { +@@ -1166,7 +1173,6 @@ static int cfe_start_streaming(struct vb + csi2_open_rx(&cfe->csi2); + + cfe_dbg("Starting sensor streaming\n"); +- cfe->sequence = 0; + ret = v4l2_subdev_call(cfe->sensor, video, s_stream, 1); + if (ret < 0) { + cfe_err("stream on failed in subdev\n"); diff --git a/target/linux/bcm27xx/patches-6.1/950-1231-ASoC-dwc-Defer-bclk_ratio-handling-to-hw_params.patch b/target/linux/bcm27xx/patches-6.1/950-1231-ASoC-dwc-Defer-bclk_ratio-handling-to-hw_params.patch new file mode 100644 index 0000000000..c187507545 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1231-ASoC-dwc-Defer-bclk_ratio-handling-to-hw_params.patch @@ -0,0 +1,89 @@ +From dfc04900c40eb14f9364d56e96db2cc3340a1f21 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 3 Jan 2024 14:43:43 +0000 +Subject: [PATCH] ASoC: dwc: Defer bclk_ratio handling to hw_params + +bclk_ratio is only a factor in clock producer mode, and needs to +override the default value of num_channels * sample_size. +Move the bclk_ratio handling into the hw_params method, only latching +the value in set_bclk_ratio, to address both of those matters. + +See: https://github.com/raspberrypi/linux/issues/5817 + +Signed-off-by: Phil Elwell +--- + sound/soc/dwc/dwc-i2s.c | 38 +++++++++++++++++++++----------------- + sound/soc/dwc/local.h | 1 + + 2 files changed, 22 insertions(+), 17 deletions(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -263,6 +263,25 @@ static int dw_i2s_hw_params(struct snd_p + return -EINVAL; + } + ++ if ((dev->capability & DW_I2S_MASTER) && dev->bclk_ratio) { ++ switch (dev->bclk_ratio) { ++ case 32: ++ dev->ccr = 0x00; ++ break; ++ ++ case 48: ++ dev->ccr = 0x08; ++ break; ++ ++ case 64: ++ dev->ccr = 0x10; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ } ++ + config->chan_nr = params_channels(params); + + switch (config->chan_nr) { +@@ -436,23 +455,7 @@ static int dw_i2s_set_bclk_ratio(struct + + dev_dbg(dev->dev, "%s(%d)\n", __func__, ratio); + +- switch (ratio) { +- case 32: +- dev->ccr = 0x00; +- break; +- +- case 48: +- dev->ccr = 0x08; +- break; +- +- case 64: +- dev->ccr = 0x10; +- break; +- default: +- return -EINVAL; +- } +- +- i2s_write_reg(dev->i2s_base, CCR, dev->ccr); ++ dev->bclk_ratio = ratio; + + return 0; + } +@@ -746,6 +749,7 @@ static int dw_i2s_probe(struct platform_ + } + } + ++ dev->bclk_ratio = 0; + dev->i2s_reg_comp1 = I2S_COMP_PARAM_1; + dev->i2s_reg_comp2 = I2S_COMP_PARAM_2; + if (pdata) { +--- a/sound/soc/dwc/local.h ++++ b/sound/soc/dwc/local.h +@@ -107,6 +107,7 @@ struct dw_i2s_dev { + unsigned int quirks; + unsigned int i2s_reg_comp1; + unsigned int i2s_reg_comp2; ++ unsigned int bclk_ratio; + struct device *dev; + u32 ccr; + u32 xfer_resolution; diff --git a/target/linux/bcm27xx/patches-6.1/950-1232-drm-vc4-Fix-reading-of-frame-count-on-GEN5-Pi4.patch b/target/linux/bcm27xx/patches-6.1/950-1232-drm-vc4-Fix-reading-of-frame-count-on-GEN5-Pi4.patch new file mode 100644 index 0000000000..4374e24244 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1232-drm-vc4-Fix-reading-of-frame-count-on-GEN5-Pi4.patch @@ -0,0 +1,79 @@ +From d5066442e39dd9bf4ba6431ffb3f99e3d5085d3f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 4 Jan 2024 12:02:43 +0000 +Subject: [PATCH] drm/vc4: Fix reading of frame count on GEN5 / Pi4 + +The frame count values moved within registers DISPSTAT1 and +DISPSTAT2 with GEN5, so update the accessor function to +accommodate that. + +Fixes: b51cd7ad143d ("drm/vc4: hvs: Fix frame count register readout") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 23 +++++++++++++++++++++-- + drivers/gpu/drm/vc4/vc4_regs.h | 6 ++++++ + 2 files changed, 27 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -823,10 +823,28 @@ u8 vc4_hvs_get_fifo_frame_count(struct v + if (!drm_dev_enter(drm, &idx)) + return 0; + +- if (vc4->gen >= VC4_GEN_6) { ++ switch (vc4->gen) { ++ case VC4_GEN_6: + field = VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_STATUS(fifo)), + SCALER6_DISPX_STATUS_FRCNT); +- } else { ++ break; ++ case VC4_GEN_5: ++ switch (fifo) { ++ case 0: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), ++ SCALER5_DISPSTAT1_FRCNT0); ++ break; ++ case 1: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), ++ SCALER5_DISPSTAT1_FRCNT1); ++ break; ++ case 2: ++ field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT2), ++ SCALER5_DISPSTAT2_FRCNT2); ++ break; ++ } ++ break; ++ case VC4_GEN_4: + switch (fifo) { + case 0: + field = VC4_GET_FIELD(HVS_READ(SCALER_DISPSTAT1), +@@ -841,6 +859,7 @@ u8 vc4_hvs_get_fifo_frame_count(struct v + SCALER_DISPSTAT2_FRCNT2); + break; + } ++ break; + } + + drm_dev_exit(idx); +--- a/drivers/gpu/drm/vc4/vc4_regs.h ++++ b/drivers/gpu/drm/vc4/vc4_regs.h +@@ -424,6 +424,10 @@ + # define SCALER_DISPSTAT1_FRCNT0_SHIFT 18 + # define SCALER_DISPSTAT1_FRCNT1_MASK VC4_MASK(17, 12) + # define SCALER_DISPSTAT1_FRCNT1_SHIFT 12 ++# define SCALER5_DISPSTAT1_FRCNT0_MASK VC4_MASK(25, 20) ++# define SCALER5_DISPSTAT1_FRCNT0_SHIFT 20 ++# define SCALER5_DISPSTAT1_FRCNT1_MASK VC4_MASK(19, 14) ++# define SCALER5_DISPSTAT1_FRCNT1_SHIFT 14 + + #define SCALER_DISPSTATX(x) (SCALER_DISPSTAT0 + \ + (x) * (SCALER_DISPSTAT1 - \ +@@ -442,6 +446,8 @@ + #define SCALER_DISPSTAT2 0x00000068 + # define SCALER_DISPSTAT2_FRCNT2_MASK VC4_MASK(17, 12) + # define SCALER_DISPSTAT2_FRCNT2_SHIFT 12 ++# define SCALER5_DISPSTAT2_FRCNT2_MASK VC4_MASK(19, 14) ++# define SCALER5_DISPSTAT2_FRCNT2_SHIFT 14 + + #define SCALER_DISPBASE2 0x0000006c + #define SCALER_DISPALPHA2 0x00000070 diff --git a/target/linux/bcm27xx/patches-6.1/950-1233-ARM-dts-bcm2712-rpi-5-b-Add-eth_ledx-parameters.patch b/target/linux/bcm27xx/patches-6.1/950-1233-ARM-dts-bcm2712-rpi-5-b-Add-eth_ledx-parameters.patch new file mode 100644 index 0000000000..f0c6efa362 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1233-ARM-dts-bcm2712-rpi-5-b-Add-eth_ledx-parameters.patch @@ -0,0 +1,56 @@ +From eeb5969ae34df16024f39a77496a44ae94bfab13 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 4 Jan 2024 13:56:39 +0000 +Subject: [PATCH] ARM: dts: bcm2712-rpi-5-b: Add eth_ledx parameters + +Include the dtparams controlling the Ethernet jack LEDs, as used on +other Pis. + +See: https://github.com/raspberrypi/linux/issues/5825 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 2 ++ + arch/arm/boot/dts/overlays/README | 6 +++--- + 2 files changed, 5 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -830,6 +830,8 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + act_led_trigger = <&act_led>, "linux,default-trigger"; + pwr_led_activelow = <&pwr_led>, "gpios:8"; + pwr_led_trigger = <&pwr_led>, "linux,default-trigger"; ++ eth_led0 = <&phy1>,"led-modes:0"; ++ eth_led1 = <&phy1>,"led-modes:4"; + drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0; + drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1; + drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi; +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -207,7 +207,7 @@ Params: + 0 means never downshift (default 2). Pi3B+ only. + + eth_led0 Set mode of LED0 - amber on Pi3B+ (default "1"), +- green on Pi4 (default "0"). ++ green on Pi4/5 (default "0"). + The legal values are: + + Pi3B+ +@@ -217,7 +217,7 @@ Params: + 4=link100/1000/activity 5=link10/1000/activity + 6=link10/100/activity 14=off 15=on + +- Pi4 ++ Pi4/5 + + 0=Speed/Activity 1=Speed + 2=Flash activity 3=FDX +@@ -226,7 +226,7 @@ Params: + 8=Link 9=Activity + + eth_led1 Set mode of LED1 - green on Pi3B+ (default "6"), +- amber on Pi4 (default "8"). See eth_led0 for ++ amber on Pi4/5 (default "8"). See eth_led0 for + legal values. + + eth_max_speed Set the maximum speed a link is allowed diff --git a/target/linux/bcm27xx/patches-6.1/950-1234-ARM-dts-bcm2712-rpi-5-b-Add-fan-speed-dtparams.patch b/target/linux/bcm27xx/patches-6.1/950-1234-ARM-dts-bcm2712-rpi-5-b-Add-fan-speed-dtparams.patch new file mode 100644 index 0000000000..da2345fdf7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1234-ARM-dts-bcm2712-rpi-5-b-Add-fan-speed-dtparams.patch @@ -0,0 +1,71 @@ +From 2c085a1ff40521ab89d8f1894757aa83b59b4607 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 4 Jan 2024 12:09:10 +0000 +Subject: [PATCH] ARM: dts: bcm2712-rpi-5-b: Add fan speed dtparams + +Add dtparams for adjusting the Pi 5 cooling fan speeds and temperature +thresholds. + +See: https://github.com/raspberrypi/linux/issues/5820 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2712-rpi-5-b.dts | 13 +++++++++++++ + arch/arm/boot/dts/overlays/README | 25 +++++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +--- a/arch/arm/boot/dts/bcm2712-rpi-5-b.dts ++++ b/arch/arm/boot/dts/bcm2712-rpi-5-b.dts +@@ -844,5 +844,18 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1; + drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi; + drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4; ++ ++ fan_temp0 = <&cpu_tepid>,"temperature:0"; ++ fan_temp1 = <&cpu_warm>,"temperature:0"; ++ fan_temp2 = <&cpu_hot>,"temperature:0"; ++ fan_temp3 = <&cpu_vhot>,"temperature:0"; ++ fan_temp0_hyst = <&cpu_tepid>,"hysteresis:0"; ++ fan_temp1_hyst = <&cpu_warm>,"hysteresis:0"; ++ fan_temp2_hyst = <&cpu_hot>,"hysteresis:0"; ++ fan_temp3_hyst = <&cpu_vhot>,"hysteresis:0"; ++ fan_temp0_speed = <&fan>, "cooling-levels:4"; ++ fan_temp1_speed = <&fan>, "cooling-levels:8"; ++ fan_temp2_speed = <&fan>, "cooling-levels:12"; ++ fan_temp3_speed = <&fan>, "cooling-levels:16"; + }; + }; +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -233,6 +233,31 @@ Params: + to negotiate. Legal values are 10, 100 and + 1000 (default 1000). Pi3B+ only. + ++ fan_temp0 Temperature threshold (in millicelcius) for ++ 1st cooling level (default 50000). Pi5 only. ++ fan_temp0_hyst Temperature hysteresis (in millicelcius) for ++ 1st cooling level (default 5000). Pi5 only. ++ fan_temp0_speed Fan PWM setting for 1st cooling level (0-255, ++ default 75). Pi5 only. ++ fan_temp1 Temperature threshold (in millicelcius) for ++ 2nd cooling level (default 60000). Pi5 only. ++ fan_temp1_hyst Temperature hysteresis (in millicelcius) for ++ 2nd cooling level (default 5000). Pi5 only. ++ fan_temp1_speed Fan PWM setting for 2nd cooling level (0-255, ++ default 125). Pi5 only. ++ fan_temp2 Temperature threshold (in millicelcius) for ++ 3rd cooling level (default 67500). Pi5 only. ++ fan_temp2_hyst Temperature hysteresis (in millicelcius) for ++ 3rd cooling level (default 5000). Pi5 only. ++ fan_temp2_speed Fan PWM setting for 3rd cooling level (0-255, ++ default 175). Pi5 only. ++ fan_temp3 Temperature threshold (in millicelcius) for ++ 4th cooling level (default 75000). Pi5 only. ++ fan_temp3_hyst Temperature hysteresis (in millicelcius) for ++ 4th cooling level (default 5000). Pi5 only. ++ fan_temp3_speed Fan PWM setting for 4th cooling level (0-255, ++ default 250). Pi5 only. ++ + hdmi Set to "off" to disable the HDMI interface + (default "on") + diff --git a/target/linux/bcm27xx/patches-6.1/950-1235-drm-vc4-don-t-check-if-plane-state-fb-state-fb.patch b/target/linux/bcm27xx/patches-6.1/950-1235-drm-vc4-don-t-check-if-plane-state-fb-state-fb.patch new file mode 100644 index 0000000000..7c7c05c5ef --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1235-drm-vc4-don-t-check-if-plane-state-fb-state-fb.patch @@ -0,0 +1,93 @@ +From 146bbf9627f6c37816939de29538ec8ee9a7be1a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ma=C3=ADra=20Canal?= +Date: Fri, 5 Jan 2024 15:07:34 -0300 +Subject: [PATCH] drm/vc4: don't check if plane->state->fb == state->fb +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently, when using non-blocking commits, we can see the following +kernel warning: + +[ 110.908514] ------------[ cut here ]------------ +[ 110.908529] refcount_t: underflow; use-after-free. +[ 110.908620] WARNING: CPU: 0 PID: 1866 at lib/refcount.c:87 refcount_dec_not_one+0xb8/0xc0 +[ 110.908664] Modules linked in: rfcomm snd_seq_dummy snd_hrtimer snd_seq snd_seq_device cmac algif_hash aes_arm64 aes_generic algif_skcipher af_alg bnep hid_logitech_hidpp vc4 brcmfmac hci_uart btbcm brcmutil bluetooth snd_soc_hdmi_codec cfg80211 cec drm_display_helper drm_dma_helper drm_kms_helper snd_soc_core snd_compress snd_pcm_dmaengine fb_sys_fops sysimgblt syscopyarea sysfillrect raspberrypi_hwmon ecdh_generic ecc rfkill libaes i2c_bcm2835 binfmt_misc joydev snd_bcm2835(C) bcm2835_codec(C) bcm2835_isp(C) v4l2_mem2mem videobuf2_dma_contig snd_pcm bcm2835_v4l2(C) raspberrypi_gpiomem bcm2835_mmal_vchiq(C) videobuf2_v4l2 snd_timer videobuf2_vmalloc videobuf2_memops videobuf2_common snd videodev vc_sm_cma(C) mc hid_logitech_dj uio_pdrv_genirq uio i2c_dev drm fuse dm_mod drm_panel_orientation_quirks backlight ip_tables x_tables ipv6 +[ 110.909086] CPU: 0 PID: 1866 Comm: kodi.bin Tainted: G C 6.1.66-v8+ #32 +[ 110.909104] Hardware name: Raspberry Pi 3 Model B Rev 1.2 (DT) +[ 110.909114] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +[ 110.909132] pc : refcount_dec_not_one+0xb8/0xc0 +[ 110.909152] lr : refcount_dec_not_one+0xb4/0xc0 +[ 110.909170] sp : ffffffc00913b9c0 +[ 110.909177] x29: ffffffc00913b9c0 x28: 000000556969bbb0 x27: 000000556990df60 +[ 110.909205] x26: 0000000000000002 x25: 0000000000000004 x24: ffffff8004448480 +[ 110.909230] x23: ffffff800570b500 x22: ffffff802e03a7bc x21: ffffffecfca68c78 +[ 110.909257] x20: ffffff8002b42000 x19: ffffff802e03a600 x18: 0000000000000000 +[ 110.909283] x17: 0000000000000011 x16: ffffffffffffffff x15: 0000000000000004 +[ 110.909308] x14: 0000000000000fff x13: ffffffed577e47e0 x12: 0000000000000003 +[ 110.909333] x11: 0000000000000000 x10: 0000000000000027 x9 : c912d0d083728c00 +[ 110.909359] x8 : c912d0d083728c00 x7 : 65646e75203a745f x6 : 746e756f63666572 +[ 110.909384] x5 : ffffffed579f62ee x4 : ffffffed579eb01e x3 : 0000000000000000 +[ 110.909409] x2 : 0000000000000000 x1 : ffffffc00913b750 x0 : 0000000000000001 +[ 110.909434] Call trace: +[ 110.909441] refcount_dec_not_one+0xb8/0xc0 +[ 110.909461] vc4_bo_dec_usecnt+0x4c/0x1b0 [vc4] +[ 110.909903] vc4_cleanup_fb+0x44/0x50 [vc4] +[ 110.910315] drm_atomic_helper_cleanup_planes+0x88/0xa4 [drm_kms_helper] +[ 110.910669] vc4_atomic_commit_tail+0x390/0x9dc [vc4] +[ 110.911079] commit_tail+0xb0/0x164 [drm_kms_helper] +[ 110.911397] drm_atomic_helper_commit+0x1d0/0x1f0 [drm_kms_helper] +[ 110.911716] drm_atomic_commit+0xb0/0xdc [drm] +[ 110.912569] drm_mode_atomic_ioctl+0x348/0x4b8 [drm] +[ 110.913330] drm_ioctl_kernel+0xec/0x15c [drm] +[ 110.914091] drm_ioctl+0x24c/0x3b0 [drm] +[ 110.914850] __arm64_sys_ioctl+0x9c/0xd4 +[ 110.914873] invoke_syscall+0x4c/0x114 +[ 110.914897] el0_svc_common+0xd0/0x118 +[ 110.914917] do_el0_svc+0x38/0xd0 +[ 110.914936] el0_svc+0x30/0x8c +[ 110.914958] el0t_64_sync_handler+0x84/0xf0 +[ 110.914979] el0t_64_sync+0x18c/0x190 +[ 110.914996] ---[ end trace 0000000000000000 ]--- + +This happens because, although `prepare_fb` and `cleanup_fb` are +perfectly balanced, we cannot guarantee consistency in the check +plane->state->fb == state->fb. This means that sometimes we can increase +the refcount in `prepare_fb` and don't decrease it in `cleanup_fb`. The +opposite can also be true. + +In fact, the struct drm_plane .state shouldn't be accessed directly +but instead, the `drm_atomic_get_new_plane_state()` helper function should +be used. So, we could stick to this check, but using +`drm_atomic_get_new_plane_state()`. But actually, this check is not really +needed. We can increase and decrease the refcount symmetrically without +problems. + +This is going to make the code more simple and consistent. + +Signed-off-by: Maíra Canal +--- + drivers/gpu/drm/vc4/vc4_plane.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -2225,9 +2225,6 @@ static int vc4_prepare_fb(struct drm_pla + + drm_gem_plane_helper_prepare_fb(plane, state); + +- if (plane->state->fb == state->fb) +- return 0; +- + return vc4_bo_inc_usecnt(bo); + } + +@@ -2236,7 +2233,7 @@ static void vc4_cleanup_fb(struct drm_pl + { + struct vc4_bo *bo; + +- if (plane->state->fb == state->fb || !state->fb) ++ if (!state->fb) + return; + + bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base); diff --git a/target/linux/bcm27xx/patches-6.1/950-1236-spi-bcm2835-Support-spi0-0cs-and-SPI_NO_CS-mode.patch b/target/linux/bcm27xx/patches-6.1/950-1236-spi-bcm2835-Support-spi0-0cs-and-SPI_NO_CS-mode.patch new file mode 100644 index 0000000000..6039363a40 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1236-spi-bcm2835-Support-spi0-0cs-and-SPI_NO_CS-mode.patch @@ -0,0 +1,42 @@ +From 5d9075ed7e73dc6ccebf78710c78f39ddc2dd78e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 8 Jan 2024 11:42:57 +0000 +Subject: [PATCH] spi: bcm2835: Support spi0-0cs and SPI_NO_CS mode + +The forced conversion of native CS lines into software CS lines is done +whether or not the controller has been given any CS lines to use. This +breaks the use of the spi0-0cs overlay to prevent SPI from claiming any +CS lines, particularly with spidev which doesn't pass in the SPI_NO_CS +flag at creation. + +Use the presence of an empty cs-gpios property as an indication that no +CS lines should be used, bypassing the native CS conversion code. + +See: https://github.com/raspberrypi/linux/issues/5835 + +Signed-off-by: Phil Elwell +--- + drivers/spi/spi-bcm2835.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/spi/spi-bcm2835.c ++++ b/drivers/spi/spi-bcm2835.c +@@ -1222,6 +1222,7 @@ static int bcm2835_spi_setup(struct spi_ + struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); + struct bcm2835_spidev *slv = spi_get_ctldata(spi); + struct gpio_chip *chip; ++ int len; + int ret; + u32 cs; + +@@ -1287,6 +1288,10 @@ static int bcm2835_spi_setup(struct spi_ + goto err_cleanup; + } + ++ /* Skip forced CS conversion if controller has an empty cs-gpios property */ ++ if (of_find_property(ctlr->dev.of_node, "cs-gpios", &len) && len == 0) ++ return 0; ++ + /* + * Translate native CS to GPIO + * diff --git a/target/linux/bcm27xx/patches-6.1/950-1237-drivers-media-imx519-Add-V4L2_CID_LINK_FREQ-control.patch b/target/linux/bcm27xx/patches-6.1/950-1237-drivers-media-imx519-Add-V4L2_CID_LINK_FREQ-control.patch new file mode 100644 index 0000000000..889ddd77dc --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1237-drivers-media-imx519-Add-V4L2_CID_LINK_FREQ-control.patch @@ -0,0 +1,51 @@ +From 55ed8cded4af6530276b26f567601bed868ae8f5 Mon Sep 17 00:00:00 2001 +From: Lee Jackson +Date: Wed, 10 Jan 2024 08:52:54 +0800 +Subject: [PATCH] drivers: media: imx519: Add V4L2_CID_LINK_FREQ control + +Add V4L2_CID_LINK_FREQ as a read-only control with a value of 408 Mhz. +This will be used by the CFE driver to corretly setup the DPHY timing +parameters in the CSI-2 block. + +Signed-off-by: Lee Jackson +--- + drivers/media/i2c/imx519.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/media/i2c/imx519.c ++++ b/drivers/media/i2c/imx519.c +@@ -145,6 +145,10 @@ struct imx519_mode { + struct imx519_reg_list reg_list; + }; + ++static const s64 imx519_link_freq_menu[] = { ++ IMX519_DEFAULT_LINK_FREQ, ++}; ++ + static const struct imx519_reg mode_common_regs[] = { + {0x0100, 0x00}, + {0x0136, 0x18}, +@@ -1819,6 +1823,7 @@ static int imx519_init_controls(struct i + struct v4l2_ctrl_handler *ctrl_hdlr; + struct i2c_client *client = v4l2_get_subdevdata(&imx519->sd); + struct v4l2_fwnode_device_properties props; ++ struct v4l2_ctrl *link_freq; + unsigned int i; + int ret; + +@@ -1837,6 +1842,15 @@ static int imx519_init_controls(struct i + IMX519_PIXEL_RATE, 1, + IMX519_PIXEL_RATE); + ++ /* LINK_FREQ is also read only */ ++ link_freq = ++ v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx519_ctrl_ops, ++ V4L2_CID_LINK_FREQ, ++ ARRAY_SIZE(imx519_link_freq_menu) - 1, 0, ++ imx519_link_freq_menu); ++ if (link_freq) ++ link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ + /* + * Create the controls here, but mode specific limits are setup + * in the imx519_set_framing_limits() call below. diff --git a/target/linux/bcm27xx/patches-6.1/950-1238-drivers-media-arducam_64mp-Add-V4L2_CID_LINK_FREQ-co.patch b/target/linux/bcm27xx/patches-6.1/950-1238-drivers-media-arducam_64mp-Add-V4L2_CID_LINK_FREQ-co.patch new file mode 100644 index 0000000000..df353ffc31 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1238-drivers-media-arducam_64mp-Add-V4L2_CID_LINK_FREQ-co.patch @@ -0,0 +1,56 @@ +From 5e339e1502c9be0f624398cf774e5880a6d1a677 Mon Sep 17 00:00:00 2001 +From: Lee Jackson +Date: Wed, 10 Jan 2024 09:06:16 +0800 +Subject: [PATCH] drivers: media: arducam_64mp: Add V4L2_CID_LINK_FREQ control + +Add V4L2_CID_LINK_FREQ as a read-only control with a value of 456 Mhz. +This will be used by the CFE driver to corretly setup the DPHY timing +parameters in the CSI-2 block. + +Signed-off-by: Lee Jackson +--- + drivers/media/i2c/arducam_64mp.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/media/i2c/arducam_64mp.c ++++ b/drivers/media/i2c/arducam_64mp.c +@@ -143,6 +143,10 @@ struct arducam_64mp_mode { + struct arducam_64mp_reg_list reg_list; + }; + ++static const s64 arducam_64mp_link_freq_menu[] = { ++ ARDUCAM_64MP_DEFAULT_LINK_FREQ, ++}; ++ + static const struct arducam_64mp_reg mode_common_regs[] = { + {0x0100, 0x00}, + {0x0136, 0x18}, +@@ -2272,9 +2276,11 @@ static int arducam_64mp_init_controls(st + struct v4l2_ctrl_handler *ctrl_hdlr; + struct i2c_client *client = v4l2_get_subdevdata(&arducam_64mp->sd); + struct v4l2_fwnode_device_properties props; ++ struct v4l2_ctrl *link_freq; + unsigned int i; + int ret; + u8 test_pattern_max; ++ u8 link_freq_max; + + ctrl_hdlr = &arducam_64mp->ctrl_handler; + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 16); +@@ -2292,6 +2298,16 @@ static int arducam_64mp_init_controls(st + ARDUCAM_64MP_PIXEL_RATE, 1, + ARDUCAM_64MP_PIXEL_RATE); + ++ /* LINK_FREQ is also read only */ ++ link_freq_max = ARRAY_SIZE(arducam_64mp_link_freq_menu) - 1; ++ link_freq = ++ v4l2_ctrl_new_int_menu(ctrl_hdlr, &arducam_64mp_ctrl_ops, ++ V4L2_CID_LINK_FREQ, ++ link_freq_max, 0, ++ arducam_64mp_link_freq_menu); ++ if (link_freq) ++ link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ + /* + * Create the controls here, but mode specific limits are setup + * in the arducam_64mp_set_framing_limits() call below. diff --git a/target/linux/bcm27xx/patches-6.1/950-1239-drivers-gpu-drm-panel-Modify-the-DSI-mode-to-fix-the.patch b/target/linux/bcm27xx/patches-6.1/950-1239-drivers-gpu-drm-panel-Modify-the-DSI-mode-to-fix-the.patch new file mode 100644 index 0000000000..e106b0609a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1239-drivers-gpu-drm-panel-Modify-the-DSI-mode-to-fix-the.patch @@ -0,0 +1,25 @@ +From 7af1e18d2e90ec64f7cb78cdb5163b63b9fbb056 Mon Sep 17 00:00:00 2001 +From: eng33 +Date: Wed, 3 Jan 2024 11:45:04 +0800 +Subject: [PATCH] drivers/gpu/drm/panel:Modify the DSI mode to fix the problem + that 7.9inch cannot be displayed + +Signed-off-by: eng33 +--- + drivers/gpu/drm/panel/panel-waveshare-dsi.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/panel/panel-waveshare-dsi.c ++++ b/drivers/gpu/drm/panel/panel-waveshare-dsi.c +@@ -340,9 +340,8 @@ static int ws_panel_probe(struct i2c_cli + */ + drm_panel_add(&ts->base); + +- ts->dsi->mode_flags = (MIPI_DSI_MODE_VIDEO | +- MIPI_DSI_MODE_VIDEO_SYNC_PULSE | +- MIPI_DSI_MODE_LPM); ++ ts->dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | ++ MIPI_DSI_CLOCK_NON_CONTINUOUS; + ts->dsi->format = MIPI_DSI_FMT_RGB888; + ts->dsi->lanes = 2; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1240-drivers-gpu-drm-panel-Modified-the-timing-of-11.9inc.patch b/target/linux/bcm27xx/patches-6.1/950-1240-drivers-gpu-drm-panel-Modified-the-timing-of-11.9inc.patch new file mode 100644 index 0000000000..0f04b21137 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1240-drivers-gpu-drm-panel-Modified-the-timing-of-11.9inc.patch @@ -0,0 +1,22 @@ +From aec3f9b6058448c54b74349f16b21185148a8c6e Mon Sep 17 00:00:00 2001 +From: eng33 +Date: Wed, 3 Jan 2024 11:46:50 +0800 +Subject: [PATCH] drivers/gpu/drm/panel:Modified the timing of 11.9inch to fix + the issue that 11.9inch was displayed abnormally + +Signed-off-by: eng33 +--- + drivers/gpu/drm/panel/panel-waveshare-dsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/panel/panel-waveshare-dsi.c ++++ b/drivers/gpu/drm/panel/panel-waveshare-dsi.c +@@ -131,7 +131,7 @@ static const struct drm_display_mode ws_ + .hdisplay = 320, + .hsync_start = 320 + 60, + .hsync_end = 320 + 60 + 60, +- .htotal = 320 + 60 + 60 + 120, ++ .htotal = 320 + 60 + 60 + 60, + .vdisplay = 1480, + .vsync_start = 1480 + 60, + .vsync_end = 1480 + 60 + 60, diff --git a/target/linux/bcm27xx/patches-6.1/950-1241-drm-vc4-Add-2712-support-to-vc4_plane_async_set_fb.patch b/target/linux/bcm27xx/patches-6.1/950-1241-drm-vc4-Add-2712-support-to-vc4_plane_async_set_fb.patch new file mode 100644 index 0000000000..c13eb354fb --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1241-drm-vc4-Add-2712-support-to-vc4_plane_async_set_fb.patch @@ -0,0 +1,88 @@ +From a14da0fdb0e052a672c269df7f18c9de698bd827 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 4 Jan 2024 15:02:42 +0000 +Subject: [PATCH] drm/vc4: Add 2712 support to vc4_plane_async_set_fb + +vc4_plane_async_set_fb directly overwrites the plane address in +the dlist entry, but hadn't been updated for the GEN6 / 2712 +dlist format, corrupting the address in the process. + +Add support for the 2712 dlist format to the function. + +Fixes: 1ab1fbbb7e76 ("drm/vc4: hvs: Support BCM2712 HVS") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 46 +++++++++++++++++++++++---------- + 1 file changed, 33 insertions(+), 13 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -1865,7 +1865,7 @@ static int vc6_plane_mode_set(struct drm + * The UPM buffer will be allocated in + * vc6_plane_allocate_upm(). + */ +- VC4_SET_FIELD(upper_32_bits(paddr) & 0xf, ++ VC4_SET_FIELD(upper_32_bits(paddr) & 0xff, + SCALER6_PTR0_UPPER_ADDR)); + + /* Pointer Word 1 */ +@@ -2068,7 +2068,8 @@ void vc4_plane_async_set_fb(struct drm_p + { + struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); + struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, 0); +- uint32_t addr; ++ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); ++ dma_addr_t dma_addr = bo->dma_addr + fb->offsets[0]; + int idx; + + if (!drm_dev_enter(plane->dev, &idx)) +@@ -2078,19 +2079,38 @@ void vc4_plane_async_set_fb(struct drm_p + * because this is only called on the primary plane. + */ + WARN_ON_ONCE(plane->state->crtc_x < 0 || plane->state->crtc_y < 0); +- addr = bo->dma_addr + fb->offsets[0]; + +- /* Write the new address into the hardware immediately. The +- * scanout will start from this address as soon as the FIFO +- * needs to refill with pixels. +- */ +- writel(addr, &vc4_state->hw_dlist[vc4_state->ptr0_offset[0]]); ++ if (vc4->gen == VC4_GEN_6) { ++ u32 value; + +- /* Also update the CPU-side dlist copy, so that any later +- * atomic updates that don't do a new modeset on our plane +- * also use our updated address. +- */ +- vc4_state->dlist[vc4_state->ptr0_offset[0]] = addr; ++ value = vc4_state->dlist[vc4_state->ptr0_offset[0]] & ++ ~SCALER6_PTR0_UPPER_ADDR_MASK; ++ value |= VC4_SET_FIELD(upper_32_bits(dma_addr) & 0xff, ++ SCALER6_PTR0_UPPER_ADDR); ++ ++ writel(value, &vc4_state->hw_dlist[vc4_state->ptr0_offset[0]]); ++ vc4_state->dlist[vc4_state->ptr0_offset[0]] = value; ++ ++ value = lower_32_bits(dma_addr); ++ writel(value, &vc4_state->hw_dlist[vc4_state->ptr0_offset[0] + 1]); ++ vc4_state->dlist[vc4_state->ptr0_offset[0] + 1] = value; ++ } else { ++ u32 addr; ++ ++ addr = (u32)dma_addr; ++ ++ /* Write the new address into the hardware immediately. The ++ * scanout will start from this address as soon as the FIFO ++ * needs to refill with pixels. ++ */ ++ writel(addr, &vc4_state->hw_dlist[vc4_state->ptr0_offset[0]]); ++ ++ /* Also update the CPU-side dlist copy, so that any later ++ * atomic updates that don't do a new modeset on our plane ++ * also use our updated address. ++ */ ++ vc4_state->dlist[vc4_state->ptr0_offset[0]] = addr; ++ } + + drm_dev_exit(idx); + } diff --git a/target/linux/bcm27xx/patches-6.1/950-1242-drm-vc4-Fix-atomic_async_check-to-call-the-right-mod.patch b/target/linux/bcm27xx/patches-6.1/950-1242-drm-vc4-Fix-atomic_async_check-to-call-the-right-mod.patch new file mode 100644 index 0000000000..683c4a46ff --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1242-drm-vc4-Fix-atomic_async_check-to-call-the-right-mod.patch @@ -0,0 +1,38 @@ +From bfe927647253ab3a86be16320baa1579518c6786 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 17 Jan 2024 17:00:35 +0000 +Subject: [PATCH] drm/vc4: Fix atomic_async_check to call the right mode_set + function + +vc4_plane_atomic_async_check was always calling vc4_plane_mode_set +to validate and generate the dlist for the check. If async_check +decided it had to fall back to a sync commit, then this GEN4/5 +dlist could get used on GEN6. + +Call either vc4_plane_mode_set or vc6_plane_mode_set as appropriate. + +Fixes: 1ab1fbbb7e76 ("drm/vc4: hvs: Support BCM2712 HVS") +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_plane.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_plane.c ++++ b/drivers/gpu/drm/vc4/vc4_plane.c +@@ -2194,11 +2194,15 @@ static int vc4_plane_atomic_async_check( + { + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, + plane); ++ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); + struct vc4_plane_state *old_vc4_state, *new_vc4_state; + int ret; + u32 i; + +- ret = vc4_plane_mode_set(plane, new_plane_state); ++ if (vc4->gen >= VC4_GEN_6) ++ ret = vc6_plane_mode_set(plane, new_plane_state); ++ else ++ ret = vc4_plane_mode_set(plane, new_plane_state); + if (ret) + return ret; + diff --git a/target/linux/bcm27xx/patches-6.1/950-1244-drm-rp1-rp1-vec-Allow-non-standard-modes-with-variou.patch b/target/linux/bcm27xx/patches-6.1/950-1244-drm-rp1-rp1-vec-Allow-non-standard-modes-with-variou.patch new file mode 100644 index 0000000000..fb20dfe94d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1244-drm-rp1-rp1-vec-Allow-non-standard-modes-with-variou.patch @@ -0,0 +1,343 @@ +From 04b88e1a8b867b045bc90d997e8e0260b00dbb15 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Thu, 11 Jan 2024 12:13:03 +0000 +Subject: [PATCH] drm: rp1: rp1-vec: Allow non-standard modes with various + crops + +Tweak sync timings in the advertised modelines. + +Accept other, custom modes, provided they fit within the active +area of one of the existing hardware-supported TV modes. + +Instead of always padding symmetrically, try to respect the user's +[hv]sync_start values, allowing the image to be shifted around +the screen (to fine-tune overscan correction). + +Signed-off-by: Nick Hollinghurst +--- + drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c | 66 ++++++++++++--------- + drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c | 74 ++++++++++++++++++------ + 2 files changed, 96 insertions(+), 44 deletions(-) + +--- a/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -208,26 +207,26 @@ static void rp1vec_connector_destroy(str + static const struct drm_display_mode rp1vec_modes[4] = { + { /* Full size 525/60i with Rec.601 pixel rate */ + DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500, +- 720, 720 + 14, 720 + 14 + 64, 858, 0, +- 480, 480 + 7, 480 + 7 + 6, 525, 0, ++ 720, 720 + 16, 720 + 16 + 64, 858, 0, ++ 480, 480 + 6, 480 + 6 + 6, 525, 0, + DRM_MODE_FLAG_INTERLACE) + }, + { /* Cropped and horizontally squashed to be TV-safe */ + DRM_MODE("704x432i", DRM_MODE_TYPE_DRIVER, 15429, +- 704, 704 + 72, 704 + 72 + 72, 980, 0, +- 432, 432 + 31, 432 + 31 + 6, 525, 0, ++ 704, 704 + 76, 704 + 76 + 72, 980, 0, ++ 432, 432 + 30, 432 + 30 + 6, 525, 0, + DRM_MODE_FLAG_INTERLACE) + }, + { /* Full size 625/50i with Rec.601 pixel rate */ + DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, + 720, 720 + 20, 720 + 20 + 64, 864, 0, +- 576, 576 + 4, 576 + 4 + 6, 625, 0, ++ 576, 576 + 5, 576 + 5 + 5, 625, 0, + DRM_MODE_FLAG_INTERLACE) + }, + { /* Cropped and squashed, for square(ish) pixels */ + DRM_MODE("704x512i", DRM_MODE_TYPE_DRIVER, 15429, + 704, 704 + 80, 704 + 80 + 72, 987, 0, +- 512, 512 + 36, 512 + 36 + 6, 625, 0, ++ 512, 512 + 37, 512 + 37 + 5, 625, 0, + DRM_MODE_FLAG_INTERLACE) + } + }; +@@ -298,27 +297,42 @@ static enum drm_mode_status rp1vec_mode_ + const struct drm_display_mode *mode) + { + /* +- * Check the mode roughly matches one of our standard modes +- * (optionally half-height and progressive). Ignore H/V sync +- * timings which for interlaced TV are approximate at best. ++ * Check the mode roughly matches something we can generate. ++ * The hardware driver is very prescriptive about pixel clocks, ++ * line and frame durations, but we'll tolerate rounding errors. ++ * Within each hardware mode, allow image size and position to vary ++ * (to fine-tune overscan correction or emulate retro devices). ++ * Don't check sync timings here: the HW driver will sanitize them. + */ +- int i, prog; + +- prog = !(mode->flags & DRM_MODE_FLAG_INTERLACE); +- +- for (i = 0; i < ARRAY_SIZE(rp1vec_modes); i++) { +- const struct drm_display_mode *ref = rp1vec_modes + i; ++ int prog = !(mode->flags & DRM_MODE_FLAG_INTERLACE); ++ int vtotal_full = mode->vtotal << prog; ++ int vdisplay_full = mode->vdisplay << prog; ++ ++ /* Reject very small frames */ ++ if (vtotal_full < 256 || mode->hdisplay < 256) ++ return MODE_BAD; ++ ++ /* Check lines, frame period (ms) and vertical size limit */ ++ if (vtotal_full >= 524 && vtotal_full <= 526 && ++ mode->htotal * vtotal_full > 33 * mode->clock && ++ mode->htotal * vtotal_full < 34 * mode->clock && ++ vdisplay_full <= 480) ++ goto vgood; ++ if (vtotal_full >= 624 && vtotal_full <= 626 && ++ mode->htotal * vtotal_full > 39 * mode->clock && ++ mode->htotal * vtotal_full < 41 * mode->clock && ++ vdisplay_full <= 576) ++ goto vgood; ++ return MODE_BAD; + +- if (mode->hdisplay == ref->hdisplay && +- mode->vdisplay == (ref->vdisplay >> prog) && +- mode->clock + 2 >= ref->clock && +- mode->clock <= ref->clock + 2 && +- mode->htotal + 2 >= ref->htotal && +- mode->htotal <= ref->htotal + 2 && +- mode->vtotal + 2 >= (ref->vtotal >> prog) && +- mode->vtotal <= (ref->vtotal >> prog) + 2) +- return MODE_OK; +- } ++vgood: ++ /* Check pixel rate (kHz) and horizontal size limit */ ++ if (mode->clock == 13500 && mode->hdisplay <= 720) ++ return MODE_OK; ++ if (mode->clock >= 15428 && mode->clock <= 15429 && ++ mode->hdisplay <= 800) ++ return MODE_OK; + return MODE_BAD; + } + +@@ -440,7 +454,7 @@ static int rp1vec_platform_probe(struct + ret = drmm_mode_config_init(drm); + if (ret) + goto err_free_drm; +- drm->mode_config.max_width = 768; ++ drm->mode_config.max_width = 800; + drm->mode_config.max_height = 576; + drm->mode_config.fb_base = 0; + drm->mode_config.preferred_depth = 32; +--- a/drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c ++++ b/drivers/gpu/drm/rp1/rp1-vec/rp1_vec_hw.c +@@ -11,7 +11,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -82,13 +81,13 @@ static const struct rp1vec_ipixfmt my_fo + /* + * Hardware mode descriptions (@ 108 MHz clock rate). + * These rely largely on "canned" register settings. +- * TODO: Port the generating software from FP to integer, +- * or better factorize the differences between modes. + */ + + struct rp1vec_hwmode { +- u16 total_cols; /* active columns, plus padding for filter context */ ++ u16 total_cols; /* max active columns incl. padding and windowing */ + u16 rows_per_field; /* active lines per field (including partial ones) */ ++ u16 ref_hfp; /* nominal (hsync_start - hdisplay) when max width */ ++ u16 ref_vfp; /* nominal (vsync_start - vdisplay) when max height */ + bool interlaced; /* set for interlaced */ + bool first_field_odd; /* set for interlaced and 30fps */ + u32 yuv_scaling; /* three 10-bit fields {Y, U, V} in 2.8 format */ +@@ -103,6 +102,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 240, ++ .ref_hfp = 12, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x1071d0cf, +@@ -118,6 +119,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 815, + .rows_per_field = 240, ++ .ref_hfp = 16, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x1c131962, +@@ -135,6 +138,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 243, ++ .ref_hfp = 12, ++ .ref_vfp = 3, + .interlaced = true, + .first_field_odd = true, + .yuv_scaling = 0x1071d0cf, +@@ -150,6 +155,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 815, + .rows_per_field = 243, ++ .ref_hfp = 16, ++ .ref_vfp = 3, + .interlaced = true, + .first_field_odd = true, + .yuv_scaling = 0x1c131962, +@@ -170,6 +177,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 288, ++ .ref_hfp = 16, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x11c1f8e0, +@@ -185,6 +194,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 804, + .rows_per_field = 288, ++ .ref_hfp = 24, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x1e635d7f, +@@ -202,6 +213,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 288, ++ .ref_hfp = 16, ++ .ref_vfp = 5, + .interlaced = true, + .first_field_odd = false, + .yuv_scaling = 0x11c1f8e0, +@@ -217,6 +230,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 804, + .rows_per_field = 288, ++ .ref_hfp = 24, ++ .ref_vfp = 5, + .interlaced = true, + .first_field_odd = false, + .yuv_scaling = 0x1e635d7f, +@@ -237,6 +252,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 240, ++ .ref_hfp = 12, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x11c1f8e0, +@@ -252,6 +269,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 815, + .rows_per_field = 240, ++ .ref_hfp = 16, ++ .ref_vfp = 2, + .interlaced = false, + .first_field_odd = false, + .yuv_scaling = 0x1e635d7f, +@@ -269,6 +288,8 @@ static const struct rp1vec_hwmode rp1vec + { + .total_cols = 724, + .rows_per_field = 243, ++ .ref_hfp = 12, ++ .ref_vfp = 3, + .interlaced = true, + .first_field_odd = true, + .yuv_scaling = 0x11c1f8e0, +@@ -284,6 +305,8 @@ static const struct rp1vec_hwmode rp1vec + }, { + .total_cols = 815, + .rows_per_field = 243, ++ .ref_hfp = 16, ++ .ref_vfp = 3, + .interlaced = true, + .first_field_odd = true, + .yuv_scaling = 0x1e635d7f, +@@ -308,11 +331,11 @@ void rp1vec_hw_setup(struct rp1_vec *vec + { + unsigned int i, mode_family, mode_ilaced, mode_narrow; + const struct rp1vec_hwmode *hwm; +- unsigned int w, h; ++ int w, h, hpad, vpad; + + /* Pick the appropriate "base" mode, which we may modify */ + mode_ilaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); +- if (mode->vtotal > 263 * (1 + mode_ilaced)) ++ if (mode->vtotal >= 272 * (1 + mode_ilaced)) + mode_family = 1; + else + mode_family = (tvstd == RP1VEC_TVSTD_PAL_M || tvstd == RP1VEC_TVSTD_PAL60) ? 2 : 0; +@@ -326,13 +349,28 @@ void rp1vec_hw_setup(struct rp1_vec *vec + tvstd, rp1vec_tvstd_names[tvstd]); + + w = mode->hdisplay; +- h = mode->vdisplay; +- if (mode_ilaced) +- h >>= 1; ++ h = mode->vdisplay >> mode_ilaced; + if (w > hwm->total_cols) + w = hwm->total_cols; + if (h > hwm->rows_per_field) +- w = hwm->rows_per_field; ++ h = hwm->rows_per_field; ++ ++ /* ++ * Add padding so a framebuffer with the given dimensions and ++ * [hv]sync_start can be displayed in the chosen hardware mode. ++ * ++ * |<----- mode->hsync_start ----->| ++ * |<------ w ------>| | ++ * | | >|--|< ref_hfp ++ * |<- hpad ->| ++ * |<------------ total_cols ----------->| ++ * ________FRAMEBUFFERCONTENTS__________ ++ * ' `--\____/-<\/\/\>-' ++ */ ++ hpad = max(0, mode->hsync_start - hwm->ref_hfp - w); ++ hpad = min(hpad, hwm->total_cols - w); ++ vpad = max(0, ((mode->vsync_start - hwm->ref_vfp) >> mode_ilaced) - h); ++ vpad = min(vpad, hwm->rows_per_field - h); + + /* Configure the hardware */ + VEC_WRITE(VEC_APB_TIMEOUT, 0x38); +@@ -347,18 +385,18 @@ void rp1vec_hw_setup(struct rp1_vec *vec + BITS(VEC_DMA_AREA_ROWS_PER_FIELD_MINUS1, h - 1)); + VEC_WRITE(VEC_YUV_SCALING, hwm->yuv_scaling); + VEC_WRITE(VEC_BACK_PORCH, +- BITS(VEC_BACK_PORCH_HBP_MINUS1, (hwm->total_cols - w - 1) >> 1) | +- BITS(VEC_BACK_PORCH_VBP_MINUS1, (hwm->rows_per_field - h - 1) >> 1)); ++ BITS(VEC_BACK_PORCH_HBP_MINUS1, hwm->total_cols - w - hpad - 1) | ++ BITS(VEC_BACK_PORCH_VBP_MINUS1, hwm->rows_per_field - h - vpad - 1)); + VEC_WRITE(VEC_FRONT_PORCH, +- BITS(VEC_FRONT_PORCH_HFP_MINUS1, (hwm->total_cols - w - 2) >> 1) | +- BITS(VEC_FRONT_PORCH_VFP_MINUS1, (hwm->rows_per_field - h - 2) >> 1)); ++ BITS(VEC_FRONT_PORCH_HFP_MINUS1, hpad - 1) | ++ BITS(VEC_FRONT_PORCH_VFP_MINUS1, vpad - 1)); + VEC_WRITE(VEC_MODE, + BITS(VEC_MODE_HIGH_WATER, 0xE0) | + BITS(VEC_MODE_ALIGN16, !((w | mode->hdisplay) & 15)) | +- BITS(VEC_MODE_VFP_EN, (hwm->rows_per_field > h + 1)) | +- BITS(VEC_MODE_VBP_EN, (hwm->rows_per_field > h)) | +- BITS(VEC_MODE_HFP_EN, (hwm->total_cols > w + 1)) | +- BITS(VEC_MODE_HBP_EN, (hwm->total_cols > w)) | ++ BITS(VEC_MODE_VFP_EN, (vpad > 0)) | ++ BITS(VEC_MODE_VBP_EN, (hwm->rows_per_field > h + vpad)) | ++ BITS(VEC_MODE_HFP_EN, (hpad > 0)) | ++ BITS(VEC_MODE_HBP_EN, (hwm->total_cols > w + hpad)) | + BITS(VEC_MODE_FIELDS_PER_FRAME_MINUS1, hwm->interlaced) | + BITS(VEC_MODE_FIRST_FIELD_ODD, hwm->first_field_odd)); + for (i = 0; i < ARRAY_SIZE(hwm->back_end_regs); ++i) { diff --git a/target/linux/bcm27xx/patches-6.1/950-1245-ARM-pl011-Add-rs485-to-the-RP1-support.patch b/target/linux/bcm27xx/patches-6.1/950-1245-ARM-pl011-Add-rs485-to-the-RP1-support.patch new file mode 100644 index 0000000000..c94619c914 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1245-ARM-pl011-Add-rs485-to-the-RP1-support.patch @@ -0,0 +1,24 @@ +From ab8ba584f91576c41d921076221ceb48e2930ae0 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 18 Jan 2024 11:08:03 +0000 +Subject: [PATCH] ARM: pl011: Add rs485 to the RP1 support + +pl011_axi_probe, added for RP1 support, lacks the rs485 additions that +appeared during its development. + +Signed-off-by: Phil Elwell +--- + drivers/tty/serial/amba-pl011.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -3026,6 +3026,8 @@ static int pl011_axi_probe(struct platfo + uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM; + uap->port.irq = irq; + uap->port.ops = &amba_pl011_pops; ++ uap->port.rs485_config = pl011_rs485_config; ++ uap->port.rs485_supported = pl011_rs485_supported; + + snprintf(uap->type, sizeof(uap->type), "PL011 AXI"); + diff --git a/target/linux/bcm27xx/patches-6.1/950-1246-fixup-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch b/target/linux/bcm27xx/patches-6.1/950-1246-fixup-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch new file mode 100644 index 0000000000..8fc8d0c768 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.1/950-1246-fixup-irqchip-irq-bcm2712-mip-Support-for-2712-s-MIP.patch @@ -0,0 +1,38 @@ +From 3bb5880ab3dd31f75c07c3c33bf29c5d469b28f3 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 18 Jan 2024 15:41:21 +0000 +Subject: [PATCH] fixup! irqchip: irq-bcm2712-mip: Support for 2712's MIP + +Use irq_domain_add_hierarchy so that the root pointer is initialised +correctly. Failure to do so leads to (at least) lockdep warnings when +they are enabled. + +See: https://github.com/raspberrypi/linux/issues/5866 + +Signed-off-by: Phil Elwell +--- + drivers/irqchip/irq-bcm2712-mip.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/irqchip/irq-bcm2712-mip.c ++++ b/drivers/irqchip/irq-bcm2712-mip.c +@@ -209,16 +209,14 @@ static int mip_init_domains(struct mip_p + return -ENXIO; + } + +- middle_domain = irq_domain_add_tree(NULL, +- &mip_irq_domain_ops, +- priv); ++ middle_domain = irq_domain_add_hierarchy(gic_domain, 0, 0, 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); diff --git a/target/linux/bcm27xx/patches-6.1/960-hwrng-iproc-set-quality-to-1000.patch b/target/linux/bcm27xx/patches-6.1/960-hwrng-iproc-set-quality-to-1000.patch index c1b4879a7c..cabe36ba71 100644 --- a/target/linux/bcm27xx/patches-6.1/960-hwrng-iproc-set-quality-to-1000.patch +++ b/target/linux/bcm27xx/patches-6.1/960-hwrng-iproc-set-quality-to-1000.patch @@ -15,7 +15,7 @@ Signed-off-by: Álvaro Fernández Rojas --- a/drivers/char/hw_random/iproc-rng200.c +++ b/drivers/char/hw_random/iproc-rng200.c -@@ -252,6 +252,7 @@ static int iproc_rng200_probe(struct pla +@@ -253,6 +253,7 @@ static int iproc_rng200_probe(struct pla priv->rng.name = pdev->name; priv->rng.cleanup = iproc_rng200_cleanup; diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index d11c946dbc..c6301662f7 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -605,6 +605,7 @@ CONFIG_BASE_SMALL=0 # CONFIG_BAYCOM_SER_FDX is not set # CONFIG_BAYCOM_SER_HDX is not set # CONFIG_BCACHE is not set +# CONFIG_BCM2712_MIP is not set # CONFIG_BCM47XX is not set # CONFIG_BCM54140_PHY is not set # CONFIG_BCM63XX is not set @@ -1036,6 +1037,8 @@ CONFIG_CMDLINE="" # CONFIG_COMMON_CLK_PWM is not set # CONFIG_COMMON_CLK_PXA is not set # CONFIG_COMMON_CLK_QCOM is not set +# CONFIG_COMMON_CLK_RP1 is not set +# CONFIG_COMMON_CLK_RP1_SDIO is not set # CONFIG_COMMON_CLK_RS9_PCIE is not set # CONFIG_COMMON_CLK_SI514 is not set # CONFIG_COMMON_CLK_SI5341 is not set @@ -1725,6 +1728,9 @@ CONFIG_DQL=y # CONFIG_DRM_RCAR_USE_LVDS is not set # CONFIG_DRM_RCAR_USE_MIPI_DSI is not set # CONFIG_DRM_ROCKCHIP is not set +# CONFIG_DRM_RP1_DPI is not set +# CONFIG_DRM_RP1_DSI is not set +# CONFIG_DRM_RP1_VEC is not set # CONFIG_DRM_SII902X is not set # CONFIG_DRM_SII9234 is not set # CONFIG_DRM_SIL_SII8620 is not set @@ -2083,6 +2089,7 @@ CONFIG_FB_NOTIFY=y # CONFIG_FB_PXA is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_RIVA is not set +# CONFIG_FB_RPISENSE is not set # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_S3 is not set # CONFIG_FB_SAVAGE is not set @@ -2283,6 +2290,7 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512 # CONFIG_GPIO_AMDPT is not set # CONFIG_GPIO_AMD_FCH is not set # CONFIG_GPIO_BCM_KONA is not set +# CONFIG_GPIO_BRCMSTB is not set # CONFIG_GPIO_BT8XX is not set # CONFIG_GPIO_CADENCE is not set # CONFIG_GPIO_CASCADE is not set @@ -2853,6 +2861,7 @@ CONFIG_INPUT_MISC=y # CONFIG_INPUT_POWERMATE is not set # CONFIG_INPUT_PWM_BEEPER is not set # CONFIG_INPUT_PWM_VIBRA is not set +# CONFIG_INPUT_RASPBERRYPI_BUTTON is not set # CONFIG_INPUT_REGULATOR_HAPTIC is not set # CONFIG_INPUT_SOC_BUTTON_ARRAY is not set # CONFIG_INPUT_SPARSEKMAP is not set @@ -3609,6 +3618,7 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_PM8921_CORE is not set # CONFIG_MFD_PM8XXX is not set # CONFIG_MFD_QCOM_PM8008 is not set +# CONFIG_MFD_RASPBERRYPI_POE_HAT is not set # CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_RDC321X is not set # CONFIG_MFD_RETU is not set @@ -3618,6 +3628,8 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_MFD_ROHM_BD71828 is not set # CONFIG_MFD_ROHM_BD718XX is not set # CONFIG_MFD_ROHM_BD957XMUF is not set +# CONFIG_MFD_RP1 is not set +# CONFIG_MFD_RPISENSE_CORE is not set # CONFIG_MFD_RSMU_I2C is not set # CONFIG_MFD_RSMU_SPI is not set # CONFIG_MFD_RT4831 is not set @@ -4839,6 +4851,7 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PHYLIB is not set # CONFIG_PHYLIB_LEDS is not set # CONFIG_PHYS_ADDR_T_64BIT is not set +# CONFIG_PHY_BRCM_USB is not set # CONFIG_PHY_CADENCE_DP is not set # CONFIG_PHY_CADENCE_DPHY is not set # CONFIG_PHY_CADENCE_DPHY_RX is not set @@ -4875,6 +4888,7 @@ CONFIG_PINCONF=y # CONFIG_PINCTRL is not set # CONFIG_PINCTRL_AMD is not set # CONFIG_PINCTRL_AXP209 is not set +# CONFIG_PINCTRL_BCM2712 is not set # CONFIG_PINCTRL_CEDARFORK is not set # CONFIG_PINCTRL_CY8C95X0 is not set # CONFIG_PINCTRL_EXYNOS is not set @@ -4895,6 +4909,7 @@ CONFIG_PINCONF=y # CONFIG_PINCTRL_MTK_V2 is not set # CONFIG_PINCTRL_OCELOT is not set # CONFIG_PINCTRL_PISTACHIO is not set +# CONFIG_PINCTRL_RP1 is not set # CONFIG_PINCTRL_SC7280 is not set # CONFIG_PINCTRL_SC8180X is not set # CONFIG_PINCTRL_SDX55 is not set @@ -5053,6 +5068,7 @@ CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 # CONFIG_PWM_MEDIATEK is not set # CONFIG_PWM_PCA9685 is not set # CONFIG_PWM_RASPBERRYPI_POE is not set +# CONFIG_PWM_RP1 is not set # CONFIG_PWM_XILINX is not set CONFIG_PWRSEQ_EMMC=y # CONFIG_PWRSEQ_SD8787 is not set @@ -5127,6 +5143,7 @@ CONFIG_RANDOM_TRUST_CPU=y # CONFIG_RANDSTRUCT_NONE is not set # CONFIG_RAPIDIO is not set # CONFIG_RAS is not set +# CONFIG_RASPBERRYPI_GPIOMEM is not set # CONFIG_RBTREE_TEST is not set # CONFIG_RCU_BOOST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 @@ -5251,6 +5268,7 @@ CONFIG_REISERFS_FS_XATTR=y # CONFIG_RENESAS_PHY is not set # CONFIG_RESET_ATH79 is not set # CONFIG_RESET_BERLIN is not set +# CONFIG_RESET_BRCMSTB is not set # CONFIG_RESET_BRCMSTB_RESCAL is not set # CONFIG_RESET_CONTROLLER is not set # CONFIG_RESET_IMX7 is not set @@ -5779,6 +5797,7 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_SENSORS_Q54SJ108A2 is not set # CONFIG_SENSORS_RM3100_I2C is not set # CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SENSORS_RP1_ADC is not set # CONFIG_SENSORS_SBRMI is not set # CONFIG_SENSORS_SBTSI is not set # CONFIG_SENSORS_SCH5627 is not set @@ -6593,6 +6612,7 @@ CONFIG_STDBINUTILS=y # CONFIG_STMMAC_PCI is not set # CONFIG_STMMAC_PLATFORM is not set # CONFIG_STMMAC_SELFTESTS is not set +# CONFIG_STMPE_ADC is not set # CONFIG_STM_DUMMY is not set # CONFIG_STM_SOURCE_CONSOLE is not set CONFIG_STP=y @@ -7510,6 +7530,7 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_BT856 is not set # CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_BU64754 is not set # CONFIG_VIDEO_CADENCE is not set # CONFIG_VIDEO_CADENCE_CSI2RX is not set # CONFIG_VIDEO_CADENCE_CSI2TX is not set @@ -7603,6 +7624,7 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_OV5675 is not set # CONFIG_VIDEO_OV5693 is not set # CONFIG_VIDEO_OV5695 is not set +# CONFIG_VIDEO_OV64A40 is not set # CONFIG_VIDEO_OV6650 is not set # CONFIG_VIDEO_OV7251 is not set # CONFIG_VIDEO_OV7640 is not set From beccf65a93a3a54d4af7cbdbff4b7d51ce52a58c Mon Sep 17 00:00:00 2001 From: Marty Jones Date: Mon, 6 Nov 2023 22:21:44 -0500 Subject: [PATCH 204/222] linux-firmware: add Raspberry Pi 5 NVRAM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RPi 5 expects the same NVRAM as the one from RPi 4 on a different file. Signed-off-by: Marty Jones [Reword commit description, add missing PKG_RELEASE bump] Signed-off-by: Álvaro Fernández Rojas --- package/firmware/linux-firmware/Makefile | 2 +- package/firmware/linux-firmware/broadcom.mk | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/package/firmware/linux-firmware/Makefile b/package/firmware/linux-firmware/Makefile index 79341c30cb..f7f1f978e3 100644 --- a/package/firmware/linux-firmware/Makefile +++ b/package/firmware/linux-firmware/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=linux-firmware PKG_VERSION:=20231211 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_URL:=@KERNEL/linux/kernel/firmware PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz diff --git a/package/firmware/linux-firmware/broadcom.mk b/package/firmware/linux-firmware/broadcom.mk index 4f64b423eb..088a2665cc 100644 --- a/package/firmware/linux-firmware/broadcom.mk +++ b/package/firmware/linux-firmware/broadcom.mk @@ -125,9 +125,15 @@ define Package/brcmfmac-nvram-43455-sdio/install $(LN) \ brcmfmac43455-sdio.raspberrypi,4-model-b.txt \ $(1)/lib/firmware/brcm/brcmfmac43455-sdio.Raspberry\ Pi\ Foundation-Raspberry\ Pi\ 4\ Model\ B.txt + $(LN) \ + brcmfmac43455-sdio.raspberrypi,4-model-b.txt \ + $(1)/lib/firmware/brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.txt $(LN) \ brcmfmac43455-sdio.raspberrypi,4-model-b.txt \ $(1)/lib/firmware/brcm/brcmfmac43455-sdio.Raspberry\ Pi\ Foundation-Raspberry\ Pi\ Compute\ Module\ 4.txt + $(LN) \ + brcmfmac43455-sdio.raspberrypi,4-model-b.txt \ + $(1)/lib/firmware/brcm/brcmfmac43455-sdio.Raspberry\ Pi\ Foundation-Raspberry\ Pi\ 5\ Model\ B.txt $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/brcm/brcmfmac43455-sdio.MINIX-NEO\ Z83-4.txt \ $(1)/lib/firmware/brcm/ From 8b63d9ac4ae9bd9a83a656825fb0c74fe0f4f25f Mon Sep 17 00:00:00 2001 From: Marty Jones Date: Thu, 18 Jan 2024 09:52:22 -0500 Subject: [PATCH 205/222] bcm27xx: add new bcm2712 subtarget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for Raspberry Pi 5. Instead of using 16K pages like Raspberry Pi OS, OpenWrt uses 4K pages due to incompatibilities with F2FS and other applications. There are multiple RPi forum posts with different cases and users are forcing kernel8.img to workaround them, which is the 64 bit kernel of the RPi 4. However, this isn't possible in OpenWrt because we only ship one kernel and we would have to add RPi 5 support to bcm2711 subtarget (RPi 4) for that workaround to work in OpenWrt. Specification: - Processor Broadcom BCM2712 2.4GHz quad-core 64-bit Arm Cortex-A76 CPU, with cryptographic extension, 512KB L2 caches per core, 2048KB L3 cache Features: - VideoCore VII GPU, supports OpenGL ES 3.1, Vulkan 1.2 - Dual 4Kp60 HDMI display output with HDR support 4Kp60 HEVC decoder - LPDDR4X-4267 SDRAM 4GB and 8GB - Dual-band 802.11ac Wi-Fi - Bluetooth 5.0 / Bluetooth Low Energy - microSD card slot, with support for SDR104 high-speed mode - 2 x USB 3.0 ports - 2 x USB 2.0 ports - Gigabit Ethernet - 2 x 4 lane MIPI camera/display - PCIe 2.0 x1 - 5V/5A power via USB-C - Raspberry Pi standard 40-pin header - Real-time clock RTC - Power button Build system: x86_64 Build-tested: bcm2712 Run-tested: bcm2712/RPi5 Signed-off-by: Marty Jones [Remove device variant, improve description] Signed-off-by: Álvaro Fernández Rojas --- target/linux/bcm27xx/Makefile | 2 +- .../bcm27xx/base-files/etc/board.d/02_network | 1 + target/linux/bcm27xx/base-files/etc/diag.sh | 1 + target/linux/bcm27xx/bcm2712/config-6.1 | 600 ++++++++++++++++++ target/linux/bcm27xx/bcm2712/target.mk | 12 + target/linux/bcm27xx/image/Makefile | 18 + 6 files changed, 633 insertions(+), 1 deletion(-) create mode 100644 target/linux/bcm27xx/bcm2712/config-6.1 create mode 100644 target/linux/bcm27xx/bcm2712/target.mk diff --git a/target/linux/bcm27xx/Makefile b/target/linux/bcm27xx/Makefile index 99c5fa75aa..702a59ecb8 100644 --- a/target/linux/bcm27xx/Makefile +++ b/target/linux/bcm27xx/Makefile @@ -9,7 +9,7 @@ ARCH:=arm BOARD:=bcm27xx BOARDNAME:=Broadcom BCM27xx FEATURES:=audio boot-part display ext4 fpu gpio rootfs-part rtc squashfs usb usbgadget -SUBTARGETS:=bcm2708 bcm2709 bcm2710 bcm2711 +SUBTARGETS:=bcm2708 bcm2709 bcm2710 bcm2711 bcm2712 KERNEL_PATCHVER:=6.1 diff --git a/target/linux/bcm27xx/base-files/etc/board.d/02_network b/target/linux/bcm27xx/base-files/etc/board.d/02_network index 23bc9afdb9..f246139c38 100644 --- a/target/linux/bcm27xx/base-files/etc/board.d/02_network +++ b/target/linux/bcm27xx/base-files/etc/board.d/02_network @@ -17,6 +17,7 @@ raspberrypi,3-model-b-plus |\ raspberrypi,400 |\ raspberrypi,4-compute-module |\ raspberrypi,4-model-b |\ +raspberrypi,5-model-b |\ raspberrypi,model-b |\ raspberrypi,model-b-plus |\ raspberrypi,model-b-rev2) diff --git a/target/linux/bcm27xx/base-files/etc/diag.sh b/target/linux/bcm27xx/base-files/etc/diag.sh index 180b31ec95..92d72bea11 100644 --- a/target/linux/bcm27xx/base-files/etc/diag.sh +++ b/target/linux/bcm27xx/base-files/etc/diag.sh @@ -14,6 +14,7 @@ set_state() { raspberrypi,400 |\ raspberrypi,4-compute-module |\ raspberrypi,4-model-b |\ + raspberrypi,5-model-b |\ raspberrypi,model-b-plus) status_led="led1" ;; diff --git a/target/linux/bcm27xx/bcm2712/config-6.1 b/target/linux/bcm27xx/bcm2712/config-6.1 new file mode 100644 index 0000000000..08445ffee2 --- /dev/null +++ b/target/linux/bcm27xx/bcm2712/config-6.1 @@ -0,0 +1,600 @@ +CONFIG_64BIT=y +# CONFIG_AIO is not set +CONFIG_APERTURE_HELPERS=y +CONFIG_ARCH_BCM=y +CONFIG_ARCH_BCM2835=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_BRCMSTB=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_CNP=y +CONFIG_ARM64_EPAN=y +CONFIG_ARM64_ERRATUM_1165522=y +CONFIG_ARM64_ERRATUM_1286807=y +CONFIG_ARM64_ERRATUM_1463225=y +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PAN=y +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PTR_AUTH=y +CONFIG_ARM64_PTR_AUTH_KERNEL=y +CONFIG_ARM64_SVE=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y +CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_ARM_BRCMSTB_AVS_CPUFREQ=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +# CONFIG_ARM_MHU_V2 is not set +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_RASPBERRYPI_CPUFREQ=y +# CONFIG_ARM_SMMU is not set +# CONFIG_ARM_SMMU_V3 is not set +CONFIG_ARM_TIMER_SP804=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BCM2708_VCMEM=y +CONFIG_BCM2711_THERMAL=y +CONFIG_BCM2712_IOMMU=y +CONFIG_BCM2712_MIP=y +CONFIG_BCM2835_MBOX=y +CONFIG_BCM2835_POWER=y +CONFIG_BCM2835_SMI=y +CONFIG_BCM2835_SMI_DEV=m +CONFIG_BCM2835_THERMAL=y +CONFIG_BCM2835_VCHIQ=y +# CONFIG_BCM2835_VCHIQ_MMAL is not set +CONFIG_BCM2835_WDT=y +CONFIG_BCM7038_L1_IRQ=y +CONFIG_BCM7120_L2_IRQ=y +CONFIG_BCM7XXX_PHY=y +CONFIG_BCMA=y +CONFIG_BCMA_BLOCKIO=y +# CONFIG_BCMA_DEBUG is not set +# CONFIG_BCMA_DRIVER_GMAC_CMN is not set +CONFIG_BCMA_DRIVER_PCI=y +CONFIG_BCMA_FALLBACK_SPROM=y +CONFIG_BCMA_HOST_PCI=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +# CONFIG_BCMA_HOST_SOC is not set +CONFIG_BCMGENET=y +CONFIG_BCM_NET_PHYLIB=y +CONFIG_BCM_VCIO=y +# CONFIG_BCM_VC_SM_CMA is not set +CONFIG_BCM_VIDEOCORE=y +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_NVME=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BRCMSTB_DPFE=y +CONFIG_BRCMSTB_L2_IRQ=y +CONFIG_BRCMSTB_MEMC=y +CONFIG_BRCMSTB_PM=y +# CONFIG_BRCMSTB_THERMAL is not set +CONFIG_BRCM_CHAR_DRIVERS=y +CONFIG_BRCM_USB_PINMAP=y +CONFIG_BROADCOM_PHY=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_CC_NO_ARRAY_BOUNDS=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLK_BCM2711_DVP=y +CONFIG_CLK_BCM2835=y +CONFIG_CLK_RASPBERRYPI=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMA=y +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 +# CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_SIZE_MBYTES=5 +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SYSFS is not set +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_RP1=y +# CONFIG_COMMON_CLK_RP1_SDIO is not set +CONFIG_COMMON_CLK_XGENE=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_COMPAT_32BIT_TIME is not set +CONFIG_CONFIGFS_FS=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CONTIG_ALLOC=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CRC16=y +CONFIG_CRYPTO_AES_ARM64=y +CONFIG_CRYPTO_AES_ARM64_BS=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA256_ARM64=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_SHA3=y +CONFIG_CRYPTO_SHA3_ARM64=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SHA512_ARM64=y +CONFIG_CRYPTO_SHA512_ARM64_CE=y +CONFIG_CRYPTO_SM3=y +CONFIG_CRYPTO_SM3_ARM64_CE=y +CONFIG_CRYPTO_SM4=y +CONFIG_CRYPTO_SM4_ARM64_CE=y +CONFIG_CRYPTO_SM4_ARM64_CE_BLK=y +CONFIG_CRYPTO_XTS=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DIMLIB=y +CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_HEAPS_CMA=y +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DMADEVICES=y +CONFIG_DMA_BCM2708=y +CONFIG_DMA_BCM2835=y +CONFIG_DMA_CMA=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DNOTIFY=y +CONFIG_DTC=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXTCON=y +CONFIG_F2FS_FS=y +CONFIG_FB=y +CONFIG_FB_BCM2708=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_CMDLINE=y +CONFIG_FB_SIMPLE=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FONT_8x16=y +CONFIG_FONT_8x8=y +CONFIG_FONT_SUPPORT=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_FRAME_POINTER=y +CONFIG_FREEZER=y +CONFIG_FSL_ERRATUM_A008585=y +CONFIG_FS_ENCRYPTION=y +CONFIG_FS_ENCRYPTION_ALGS=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_CACHE=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GCC11_NO_ARRAY_BOUNDS=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_INJECTION=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GLOB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_BCM_VIRT=y +CONFIG_GPIO_BRCMSTB=y +CONFIG_GPIO_CDEV=y +# CONFIG_GPIO_FSM is not set +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_RASPBERRYPI_EXP=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_PCIE is not set +CONFIG_HOTPLUG_PCI_SHPC=y +CONFIG_HWMON=y +CONFIG_HW_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_IPROC_RNG200=y +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_BCM2708 is not set +CONFIG_I2C_BCM2835=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_BRCMSTB=y +CONFIG_I2C_DESIGNWARE_CORE=y +CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INPUT=y +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_RASPBERRYPI_BUTTON=y +CONFIG_IOMMU_API=y +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set +CONFIG_IOMMU_DEFAULT_DMA_STRICT=y +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set +CONFIG_IOMMU_DMA=y +CONFIG_IOMMU_IOVA=y +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +# CONFIG_IOMMU_IO_PGTABLE_DART is not set +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_IOMMU_SUPPORT=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MSI_IOMMU=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_KEYS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGER_ACTPWR=y +CONFIG_LEDS_TRIGGER_INPUT=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_MACB=y +CONFIG_MACB_PCI=y +CONFIG_MACB_USE_HWSTAMP=y +CONFIG_MAC_PARTITION=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAILBOX=y +# CONFIG_MAILBOX_TEST is not set +CONFIG_MDIO_BCM_UNIMAC=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MEMFD_CREATE=y +CONFIG_MEMORY=y +CONFIG_MEMORY_ISOLATION=y +CONFIG_MFD_CORE=y +CONFIG_MFD_RP1=y +CONFIG_MFD_SYSCON=y +CONFIG_MICROCHIP_PHY=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +# CONFIG_MMC_BCM2835 is not set +CONFIG_MMC_BCM2835_DMA=y +CONFIG_MMC_BCM2835_MMC=y +CONFIG_MMC_BCM2835_PIO_DMA_BARRIER=2 +CONFIG_MMC_BCM2835_SDHOST=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_CQHCI=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_BRCMSTB=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_IPROC=y +CONFIG_MMC_SDHCI_OF_DWCMSHC=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NET_SELFTESTS=y +CONFIG_NLS=y +CONFIG_NLS_ASCII=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_NO_HZ=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVME_CORE=y +# CONFIG_NVME_HWMON is not set +# CONFIG_NVME_MULTIPATH is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_CONFIGFS=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IOMMU=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_RESOLVE=y +CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEAER_INJECT=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEFAULT is not set +# CONFIG_PCIEASPM_PERFORMANCE is not set +# CONFIG_PCIEASPM_POWERSAVE is not set +CONFIG_PCIEASPM_POWER_SUPERSAVE=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_BRCMSTB=y +CONFIG_PCIE_DPC=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_DW_PLAT=y +CONFIG_PCIE_DW_PLAT_HOST=y +CONFIG_PCIE_MICROCHIP_HOST=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_ECAM=y +CONFIG_PCI_HOST_COMMON=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCI_STUB=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_PHY_BRCM_SATA is not set +CONFIG_PHY_BRCM_USB=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_BCM2712=y +CONFIG_PINCTRL_BCM2835=y +CONFIG_PINCTRL_RP1=y +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_OPP=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_SUPPLY=y +CONFIG_PPS=y +CONFIG_PREEMPT_NONE_BUILD=y +CONFIG_PRINTK_TIME=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_BCM2835=y +CONFIG_PWM_BRCMSTB=y +CONFIG_PWM_RP1=y +CONFIG_PWM_SYSFS=y +CONFIG_QUEUED_RWLOCKS=y +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 +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_GPIO=y +CONFIG_RESET_BRCMSTB=y +CONFIG_RESET_BRCMSTB_RESCAL=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_RASPBERRYPI=y +CONFIG_RESET_SIMPLE=y +CONFIG_RFS_ACCEL=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +# CONFIG_RPIVID_MEM is not set +# CONFIG_RPI_POE_POWER is not set +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_BRCMSTB=y +CONFIG_RTC_DRV_RPI=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_PROC_FS is not set +CONFIG_SENSORS_RASPBERRYPI_HWMON=y +CONFIG_SENSORS_RP1_ADC=y +CONFIG_SERIAL_8250_BCM2835AUX=y +CONFIG_SERIAL_8250_BCM7271=y +# CONFIG_SERIAL_8250_DMA is not set +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=0 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +# CONFIG_SERIAL_DEV_CTRL_TTYPORT is not set +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SMSC_PHY=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_BRCMSTB=y +CONFIG_SOC_BUS=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SRCU=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +# CONFIG_TEXTSEARCH is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +# CONFIG_UACCE is not set +# CONFIG_UCLAMP_TASK is not set +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +# CONFIG_USB_BRCMSTB is not set +CONFIG_USB_COMMON=y +CONFIG_USB_DWCOTG=y +CONFIG_USB_GADGET=y +# CONFIG_USB_HCD_BCMA is not set +CONFIG_USB_PCI=y +CONFIG_USB_PHY=y +CONFIG_USB_STORAGE=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_UAS=y +# CONFIG_USB_UHCI_HCD is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_VCHIQ_CDEV=y +CONFIG_VMAP_STACK=y +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZONE_DMA32=y diff --git a/target/linux/bcm27xx/bcm2712/target.mk b/target/linux/bcm27xx/bcm2712/target.mk new file mode 100644 index 0000000000..4fe9910351 --- /dev/null +++ b/target/linux/bcm27xx/bcm2712/target.mk @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ARCH:=aarch64 +SUBTARGET:=bcm2712 +BOARDNAME:=BCM2712 boards (64 bit) +CPU_TYPE:=cortex-a76 +FEATURES+=pci pcie + +define Target/Description + Build firmware image for BCM2712 devices. + This firmware features a 64 bit kernel. +endef diff --git a/target/linux/bcm27xx/image/Makefile b/target/linux/bcm27xx/image/Makefile index ad79ac7d0c..e55a7b17b5 100644 --- a/target/linux/bcm27xx/image/Makefile +++ b/target/linux/bcm27xx/image/Makefile @@ -172,4 +172,22 @@ ifeq ($(SUBTARGET),bcm2711) TARGET_DEVICES += rpi-4 endif +define Device/rpi-5 + DEVICE_MODEL := 5 + KERNEL_IMG := kernel_2712.img + DEVICE_DTS := broadcom/bcm2712-rpi-5-b + SUPPORTED_DEVICES := raspberrypi,5-model-b + DEVICE_PACKAGES := \ + cypress-firmware-43455-sdio \ + brcmfmac-nvram-43455-sdio \ + kmod-brcmfmac wpad-basic-mbedtls \ + kmod-hwmon-pwmfan kmod-thermal \ + kmod-usb-dwc3 kmod-usb3 + IMAGE/sysupgrade.img.gz := boot-common | boot-2711 | sdcard-img | gzip | append-metadata + IMAGE/factory.img.gz := boot-common | boot-2711 | sdcard-img | gzip +endef +ifeq ($(SUBTARGET),bcm2712) + TARGET_DEVICES += rpi-5 +endif + $(eval $(call BuildImage)) From 7441c2bef60cb5c110e3049c381bea6c65647f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Fri, 26 Jan 2024 10:19:40 +0100 Subject: [PATCH 206/222] qualcommax: refresh 6.1 patches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refresh patches for Linux 6.1 which no longer apply cleanly after adding ipq4019 MDIO MDC rate fix pending patches. Fixes: 53f338be43e0 ("generic: 6.1: add pending patch for ipq4019 MDIO MDC rate fix") Signed-off-by: Álvaro Fernández Rojas --- ...64-dts-qcom-ipq8074-add-A53-PLL-node.patch | 2 +- ...4-dts-qcom-ipq8074-add-thermal-nodes.patch | 4 ++-- ...-dts-qcom-ipq8074-add-clocks-to-APCS.patch | 2 +- ...pq8074-pass-XO-and-sleep-clocks-to-G.patch | 2 +- ...pq8074-align-TLMM-pin-configuration-.patch | 2 +- ...pq8074-set-Gen2-PCIe-pcie-max-link-s.patch | 2 +- ...m-ipq8074-add-critical-thermal-trips.patch | 24 +++++++++---------- ...pq8074-include-the-GPLL0-as-clock-pr.patch | 2 +- ...pq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch | 2 +- ...qcom-ipq8074-use-msi-parent-for-PCIe.patch | 6 ++--- ...com-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch | 4 ++-- ...0121-arm64-dts-ipq8074-Add-WLAN-node.patch | 2 +- ...64-dts-qcom-ipq8074-add-QFPROM-fuses.patch | 2 +- 13 files changed, 28 insertions(+), 28 deletions(-) diff --git a/target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch b/target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch index dd57eae360..5a4b1bbc99 100644 --- a/target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch +++ b/target/linux/qualcommax/patches-6.1/0001-v6.2-arm64-dts-qcom-ipq8074-add-A53-PLL-node.patch @@ -15,7 +15,7 @@ Link: https://lore.kernel.org/r/20220818220628.339366-9-robimarko@gmail.com --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -675,6 +675,14 @@ +@@ -677,6 +677,14 @@ #mbox-cells = <1>; }; diff --git a/target/linux/qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch b/target/linux/qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch index bad75e4597..f5abd27965 100644 --- a/target/linux/qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch +++ b/target/linux/qualcommax/patches-6.1/0005-v6.2-arm64-dts-qcom-ipq8074-add-thermal-nodes.patch @@ -20,7 +20,7 @@ Link: https://lore.kernel.org/r/20220818220245.338396-5-robimarko@gmail.com --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -274,6 +274,16 @@ +@@ -276,6 +276,16 @@ status = "disabled"; }; @@ -37,7 +37,7 @@ Link: https://lore.kernel.org/r/20220818220245.338396-5-robimarko@gmail.com cryptobam: dma-controller@704000 { compatible = "qcom,bam-v1.7.0"; reg = <0x00704000 0x20000>; -@@ -874,4 +884,90 @@ +@@ -876,4 +886,90 @@ , ; }; diff --git a/target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch b/target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch index e229851649..96b49e60bf 100644 --- a/target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch +++ b/target/linux/qualcommax/patches-6.1/0006-v6.2-arm64-dts-qcom-ipq8074-add-clocks-to-APCS.patch @@ -18,7 +18,7 @@ Link: https://lore.kernel.org/r/20220818220849.339732-4-robimarko@gmail.com --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -680,6 +680,8 @@ +@@ -682,6 +682,8 @@ apcs_glb: mailbox@b111000 { compatible = "qcom,ipq8074-apcs-apps-global"; reg = <0x0b111000 0x1000>; diff --git a/target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch b/target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch index 1f99de002b..0f3fdfe4d4 100644 --- a/target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch +++ b/target/linux/qualcommax/patches-6.1/0012-v6.2-arm64-dts-qcom-ipq8074-pass-XO-and-sleep-clocks-to-G.patch @@ -20,7 +20,7 @@ Link: https://lore.kernel.org/r/20221030175703.1103224-3-robimarko@gmail.com --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -361,9 +361,11 @@ +@@ -363,9 +363,11 @@ gcc: gcc@1800000 { compatible = "qcom,gcc-ipq8074"; reg = <0x01800000 0x80000>; diff --git a/target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch b/target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch index 1ce1140682..c9fef2cab4 100644 --- a/target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch +++ b/target/linux/qualcommax/patches-6.1/0017-v6.2-arm64-dts-qcom-ipq8074-align-TLMM-pin-configuration-.patch @@ -17,7 +17,7 @@ Link: https://lore.kernel.org/r/20221108142357.67202-2-krzysztof.kozlowski@linar --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -318,35 +318,35 @@ +@@ -320,35 +320,35 @@ interrupt-controller; #interrupt-cells = <0x2>; diff --git a/target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch b/target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch index 8719bf74c4..2578aa9343 100644 --- a/target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch +++ b/target/linux/qualcommax/patches-6.1/0019-v6.3-arm64-dts-qcom-ipq8074-set-Gen2-PCIe-pcie-max-link-s.patch @@ -14,7 +14,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -766,6 +766,7 @@ +@@ -768,6 +768,7 @@ linux,pci-domain = <1>; bus-range = <0x00 0xff>; num-lanes = <1>; diff --git a/target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch b/target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch index e720eb2b85..98e0a08a27 100644 --- a/target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch +++ b/target/linux/qualcommax/patches-6.1/0023-v6.5-arm64-dts-qcom-ipq8074-add-critical-thermal-trips.patch @@ -17,7 +17,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -896,6 +896,14 @@ +@@ -898,6 +898,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 4>; @@ -32,7 +32,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; nss0-thermal { -@@ -903,6 +911,14 @@ +@@ -905,6 +913,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 5>; @@ -47,7 +47,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; nss1-thermal { -@@ -910,6 +926,14 @@ +@@ -912,6 +928,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 6>; @@ -62,7 +62,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; wcss-phya0-thermal { -@@ -917,6 +941,14 @@ +@@ -919,6 +943,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 7>; @@ -77,7 +77,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; wcss-phya1-thermal { -@@ -924,6 +956,14 @@ +@@ -926,6 +958,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 8>; @@ -92,7 +92,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; cpu0_thermal: cpu0-thermal { -@@ -931,6 +971,14 @@ +@@ -933,6 +973,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 9>; @@ -107,7 +107,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; cpu1_thermal: cpu1-thermal { -@@ -938,6 +986,14 @@ +@@ -940,6 +988,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 10>; @@ -122,7 +122,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; cpu2_thermal: cpu2-thermal { -@@ -945,6 +1001,14 @@ +@@ -947,6 +1003,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 11>; @@ -137,7 +137,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; cpu3_thermal: cpu3-thermal { -@@ -952,6 +1016,14 @@ +@@ -954,6 +1018,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 12>; @@ -152,7 +152,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; cluster_thermal: cluster-thermal { -@@ -959,6 +1031,14 @@ +@@ -961,6 +1033,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 13>; @@ -167,7 +167,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; wcss-phyb0-thermal { -@@ -966,6 +1046,14 @@ +@@ -968,6 +1048,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 14>; @@ -182,7 +182,7 @@ Link: https://lore.kernel.org/r/20230607184448.2512179-1-robimarko@gmail.com }; wcss-phyb1-thermal { -@@ -973,6 +1061,14 @@ +@@ -975,6 +1063,14 @@ polling-delay = <1000>; thermal-sensors = <&tsens 15>; diff --git a/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch b/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch index 5ae4fb5671..dee770e4cd 100644 --- a/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch +++ b/target/linux/qualcommax/patches-6.1/0028-v6.7-arm64-dts-qcom-ipq8074-include-the-GPLL0-as-clock-pr.patch @@ -19,7 +19,7 @@ Reviewed-by: Konrad Dybcio --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -682,8 +682,8 @@ +@@ -684,8 +684,8 @@ apcs_glb: mailbox@b111000 { compatible = "qcom,ipq8074-apcs-apps-global"; reg = <0x0b111000 0x1000>; diff --git a/target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch b/target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch index 69d4126f76..4bd0d9298f 100644 --- a/target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch +++ b/target/linux/qualcommax/patches-6.1/0110-arm64-dts-qcom-ipq8074-pass-QMP-PCI-PHY-PIPE-clocks-.patch @@ -17,7 +17,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -396,8 +396,8 @@ +@@ -398,8 +398,8 @@ gcc: gcc@1800000 { compatible = "qcom,gcc-ipq8074"; reg = <0x01800000 0x80000>; diff --git a/target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch b/target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch index 9fefd8852a..2aedbd7028 100644 --- a/target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch +++ b/target/linux/qualcommax/patches-6.1/0111-arm64-dts-qcom-ipq8074-use-msi-parent-for-PCIe.patch @@ -12,7 +12,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -699,7 +699,7 @@ +@@ -701,7 +701,7 @@ reg = <0x0b000000 0x1000>, <0x0b002000 0x1000>; ranges = <0 0xb00a000 0xffd>; @@ -21,7 +21,7 @@ Signed-off-by: Robert Marko compatible = "arm,gic-v2m-frame"; msi-controller; reg = <0x0 0xffd>; -@@ -811,8 +811,7 @@ +@@ -813,8 +813,7 @@ ranges = <0x81000000 0x0 0x00000000 0x10200000 0x0 0x10000>, /* I/O */ <0x82000000 0x0 0x10220000 0x10220000 0x0 0xfde0000>; /* MEM */ @@ -31,7 +31,7 @@ Signed-off-by: Robert Marko #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; interrupt-map = <0 0 0 1 &intc 0 142 -@@ -873,8 +872,7 @@ +@@ -875,8 +874,7 @@ ranges = <0x81000000 0x0 0x00000000 0x20200000 0x0 0x10000>, /* I/O */ <0x82000000 0x0 0x20220000 0x20220000 0x0 0xfde0000>; /* MEM */ diff --git a/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch b/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch index e37ba37e96..f5f93d389e 100644 --- a/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch +++ b/target/linux/qualcommax/patches-6.1/0120-arm64-dts-qcom-Enable-Q6v5-WCSS-for-ipq8074-SoC.patch @@ -49,7 +49,7 @@ Signed-off-by: Robert Marko soc: soc { #address-cells = <0x1>; #size-cells = <0x1>; -@@ -409,6 +435,11 @@ +@@ -411,6 +437,11 @@ #hwlock-cells = <1>; }; @@ -61,7 +61,7 @@ Signed-off-by: Robert Marko spmi_bus: spmi@200f000 { compatible = "qcom,spmi-pmic-arb"; reg = <0x0200f000 0x001000>, -@@ -913,6 +944,56 @@ +@@ -915,6 +946,56 @@ "axi_s_sticky"; status = "disabled"; }; diff --git a/target/linux/qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch b/target/linux/qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch index bd5410c934..1aaa187d8a 100644 --- a/target/linux/qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch +++ b/target/linux/qualcommax/patches-6.1/0121-arm64-dts-ipq8074-Add-WLAN-node.patch @@ -15,7 +15,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -994,6 +994,117 @@ +@@ -996,6 +996,117 @@ }; }; }; diff --git a/target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch b/target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch index 3a6f4e9c87..5776ab1af7 100644 --- a/target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch +++ b/target/linux/qualcommax/patches-6.1/0129-arm64-dts-qcom-ipq8074-add-QFPROM-fuses.patch @@ -12,7 +12,7 @@ Signed-off-by: Robert Marko --- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi -@@ -340,6 +340,113 @@ +@@ -342,6 +342,113 @@ status = "disabled"; }; From 2df8a0ccb0b0461836e3ab88c7d4dc848664def4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 26 Jan 2024 06:35:27 +0100 Subject: [PATCH 207/222] kernel: 5.15: backport v6.1 PHY changes required for Aquantia MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki --- ...1-net-phy-Introduce-QUSGMII-PHY-mode.patch | 99 ++++++ ...er-to-derive-the-number-of-ports-fro.patch | 93 ++++++ ...t-phy-Add-1000BASE-KX-interface-mode.patch | 96 ++++++ ...et-phy-Add-support-for-rate-matching.patch | 294 ++++++++++++++++++ ...ble-PCS-polling-over-major-configura.patch | 10 +- ...NULL-pl-pcs-dereference-during-phyli.patch | 2 +- ...k-add-pcs_enable-pcs_disable-methods.patch | 14 +- ...5-net-phy-Add-a-binding-for-PHY-LEDs.patch | 6 +- ...ce-Call-into-the-PHY-driver-to-set-L.patch | 4 +- ...ce-Call-into-the-PHY-driver-to-set-L.patch | 2 +- ...8-net-ethtool-implement-ethtool_puts.patch | 2 +- .../795-backport-phylink_pcs-helpers.patch | 6 +- ...detach-callback-to-struct-phy_driver.patch | 2 +- ...02-phy-Add-2.5G-SGMII-interface-mode.patch | 16 +- ...y-simplify-phy_link_change-arguments.patch | 12 +- .../721-NET-no-auto-carrier-off-support.patch | 6 +- ...nclude-linux-add-phy-ops-for-rtl838x.patch | 2 +- ...vers-net-phy-eee-support-for-rtl838x.patch | 6 +- ...04-include-linux-add-phy-hsgmii-mode.patch | 8 +- ...rease-phy-address-number-for-rtl839x.patch | 2 +- ...rt-hardware-assisted-indirect-access.patch | 18 +- 21 files changed, 641 insertions(+), 59 deletions(-) create mode 100644 target/linux/generic/backport-5.15/731-v6.1-0001-net-phy-Introduce-QUSGMII-PHY-mode.patch create mode 100644 target/linux/generic/backport-5.15/731-v6.1-0002-net-phy-Add-helper-to-derive-the-number-of-ports-fro.patch create mode 100644 target/linux/generic/backport-5.15/731-v6.1-0003-net-phy-Add-1000BASE-KX-interface-mode.patch create mode 100644 target/linux/generic/backport-5.15/731-v6.1-0004-net-phy-Add-support-for-rate-matching.patch diff --git a/target/linux/generic/backport-5.15/731-v6.1-0001-net-phy-Introduce-QUSGMII-PHY-mode.patch b/target/linux/generic/backport-5.15/731-v6.1-0001-net-phy-Introduce-QUSGMII-PHY-mode.patch new file mode 100644 index 0000000000..40b14fc36a --- /dev/null +++ b/target/linux/generic/backport-5.15/731-v6.1-0001-net-phy-Introduce-QUSGMII-PHY-mode.patch @@ -0,0 +1,99 @@ +From 5e61fe157a27afc7c0d4f7bcbceefdca536c015f Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Wed, 17 Aug 2022 14:32:52 +0200 +Subject: [PATCH] net: phy: Introduce QUSGMII PHY mode + +The QUSGMII mode is a derivative of Cisco's USXGMII standard. This +standard is pretty similar to SGMII, but allows for faster speeds, and +has the build-in bits for Quad and Octa variants (like QSGMII). + +The main difference with SGMII/QSGMII is that USXGMII/QUSGMII re-uses +the preamble to carry various information, named 'Extensions'. + +As of today, the USXGMII standard only mentions the "PCH" extension, +which is used to convey timestamps, allowing in-band signaling of PTP +timestamps without having to modify the frame itself. + +This commit adds support for that mode. When no extension is in use, it +behaves exactly like QSGMII, although it's not compatible with QSGMII. + +Signed-off-by: Maxime Chevallier +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + Documentation/networking/phy.rst | 9 +++++++++ + drivers/net/phy/phylink.c | 3 +++ + include/linux/phy.h | 4 ++++ + 3 files changed, 16 insertions(+) + +--- a/Documentation/networking/phy.rst ++++ b/Documentation/networking/phy.rst +@@ -303,6 +303,15 @@ Some of the interface modes are describe + rate of 125Mpbs using a 4B/5B encoding scheme, resulting in an underlying + data rate of 100Mpbs. + ++``PHY_INTERFACE_MODE_QUSGMII`` ++ This defines the Cisco the Quad USGMII mode, which is the Quad variant of ++ the USGMII (Universal SGMII) link. It's very similar to QSGMII, but uses ++ a Packet Control Header (PCH) instead of the 7 bytes preamble to carry not ++ only the port id, but also so-called "extensions". The only documented ++ extension so-far in the specification is the inclusion of timestamps, for ++ PTP-enabled PHYs. This mode isn't compatible with QSGMII, but offers the ++ same capabilities in terms of link speed and negociation. ++ + Pause frames / flow control + =========================== + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -367,6 +367,7 @@ void phylink_get_linkmodes(unsigned long + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_GMII: + caps |= MAC_1000HD | MAC_1000FD; +@@ -630,6 +631,7 @@ static int phylink_parse_mode(struct phy + switch (pl->link_config.interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: + phylink_set(pl->supported, 10baseT_Half); + phylink_set(pl->supported, 10baseT_Full); + phylink_set(pl->supported, 100baseT_Half); +@@ -2956,6 +2958,7 @@ void phylink_mii_c22_pcs_get_state(struc + + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: + phylink_decode_sgmii_word(state, lpa); + break; + +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -115,6 +115,7 @@ extern const int phy_10gbit_features_arr + * @PHY_INTERFACE_MODE_25GBASER: 25G BaseR + * @PHY_INTERFACE_MODE_USXGMII: Universal Serial 10GE MII + * @PHY_INTERFACE_MODE_10GKR: 10GBASE-KR - with Clause 73 AN ++ * @PHY_INTERFACE_MODE_QUSGMII: Quad Universal SGMII + * @PHY_INTERFACE_MODE_MAX: Book keeping + * + * Describes the interface between the MAC and PHY. +@@ -152,6 +153,7 @@ typedef enum { + PHY_INTERFACE_MODE_USXGMII, + /* 10GBASE-KR - with Clause 73 AN */ + PHY_INTERFACE_MODE_10GKR, ++ PHY_INTERFACE_MODE_QUSGMII, + PHY_INTERFACE_MODE_MAX, + } phy_interface_t; + +@@ -267,6 +269,8 @@ static inline const char *phy_modes(phy_ + return "10gbase-kr"; + case PHY_INTERFACE_MODE_100BASEX: + return "100base-x"; ++ case PHY_INTERFACE_MODE_QUSGMII: ++ return "qusgmii"; + default: + return "unknown"; + } diff --git a/target/linux/generic/backport-5.15/731-v6.1-0002-net-phy-Add-helper-to-derive-the-number-of-ports-fro.patch b/target/linux/generic/backport-5.15/731-v6.1-0002-net-phy-Add-helper-to-derive-the-number-of-ports-fro.patch new file mode 100644 index 0000000000..a9706af893 --- /dev/null +++ b/target/linux/generic/backport-5.15/731-v6.1-0002-net-phy-Add-helper-to-derive-the-number-of-ports-fro.patch @@ -0,0 +1,93 @@ +From c04ade27cb7b952b6b9b9a0efa0a6129cc63f2ae Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Wed, 17 Aug 2022 14:32:54 +0200 +Subject: [PATCH] net: phy: Add helper to derive the number of ports from a phy + mode + +Some phy modes such as QSGMII multiplex several MAC<->PHY links on one +single physical interface. QSGMII used to be the only one supported, but +other modes such as QUSGMII also carry multiple links. + +This helper allows getting the number of links that are multiplexed +on a given interface. + +Signed-off-by: Maxime Chevallier +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy-core.c | 52 ++++++++++++++++++++++++++++++++++++++ + include/linux/phy.h | 2 ++ + 2 files changed, 54 insertions(+) + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -74,6 +74,58 @@ const char *phy_duplex_to_str(unsigned i + } + EXPORT_SYMBOL_GPL(phy_duplex_to_str); + ++/** ++ * phy_interface_num_ports - Return the number of links that can be carried by ++ * a given MAC-PHY physical link. Returns 0 if this is ++ * unknown, the number of links else. ++ * ++ * @interface: The interface mode we want to get the number of ports ++ */ ++int phy_interface_num_ports(phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_NA: ++ return 0; ++ case PHY_INTERFACE_MODE_INTERNAL: ++ case PHY_INTERFACE_MODE_MII: ++ case PHY_INTERFACE_MODE_GMII: ++ case PHY_INTERFACE_MODE_TBI: ++ case PHY_INTERFACE_MODE_REVMII: ++ case PHY_INTERFACE_MODE_RMII: ++ case PHY_INTERFACE_MODE_REVRMII: ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ case PHY_INTERFACE_MODE_RTBI: ++ case PHY_INTERFACE_MODE_XGMII: ++ case PHY_INTERFACE_MODE_XLGMII: ++ case PHY_INTERFACE_MODE_MOCA: ++ case PHY_INTERFACE_MODE_TRGMII: ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_SMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ case PHY_INTERFACE_MODE_5GBASER: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_25GBASER: ++ case PHY_INTERFACE_MODE_10GKR: ++ case PHY_INTERFACE_MODE_100BASEX: ++ case PHY_INTERFACE_MODE_RXAUI: ++ case PHY_INTERFACE_MODE_XAUI: ++ return 1; ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: ++ return 4; ++ case PHY_INTERFACE_MODE_MAX: ++ WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode"); ++ return 0; ++ } ++ return 0; ++} ++EXPORT_SYMBOL_GPL(phy_interface_num_ports); ++ + /* A mapping of all SUPPORTED settings to speed/duplex. This table + * must be grouped by speed and sorted in descending match priority + * - iow, descending speed. +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -964,6 +964,8 @@ struct phy_fixup { + const char *phy_speed_to_str(int speed); + const char *phy_duplex_to_str(unsigned int duplex); + ++int phy_interface_num_ports(phy_interface_t interface); ++ + /* A structure for mapping a particular speed and duplex + * combination to a particular SUPPORTED and ADVERTISED value + */ diff --git a/target/linux/generic/backport-5.15/731-v6.1-0003-net-phy-Add-1000BASE-KX-interface-mode.patch b/target/linux/generic/backport-5.15/731-v6.1-0003-net-phy-Add-1000BASE-KX-interface-mode.patch new file mode 100644 index 0000000000..70669dde3a --- /dev/null +++ b/target/linux/generic/backport-5.15/731-v6.1-0003-net-phy-Add-1000BASE-KX-interface-mode.patch @@ -0,0 +1,96 @@ +From 05ad5d4581c3c1cc724fe50d4652833fb9f3037b Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Fri, 2 Sep 2022 18:02:39 -0400 +Subject: [PATCH] net: phy: Add 1000BASE-KX interface mode + +Add 1000BASE-KX interface mode. This 1G backplane ethernet as described in +clause 70. Clause 73 autonegotiation is mandatory, and only full duplex +operation is supported. + +Although at the PMA level this interface mode is identical to +1000BASE-X, it uses a different form of in-band autonegation. This +justifies a separate interface mode, since the interface mode (along +with the MLO_AN_* autonegotiation mode) sets the type of autonegotiation +which will be used on a link. This results in more than just electrical +differences between the link modes. + +With regard to 1000BASE-X, 1000BASE-KX holds a similar position to +SGMII: same signaling, but different autonegotiation. PCS drivers +(which typically handle in-band autonegotiation) may only support +1000BASE-X, and not 1000BASE-KX. Similarly, the phy mode is used to +configure serdes phys with phy_set_mode_ext. Due to the different +electrical standards (SFI or XFI vs Clause 70), they will likely want to +use different configuration. Adding a phy interface mode for +1000BASE-KX helps simplify configuration in these areas. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + Documentation/networking/phy.rst | 6 ++++++ + drivers/net/phy/phy-core.c | 1 + + drivers/net/phy/phylink.c | 1 + + include/linux/phy.h | 4 ++++ + 4 files changed, 12 insertions(+) + +--- a/Documentation/networking/phy.rst ++++ b/Documentation/networking/phy.rst +@@ -312,6 +312,12 @@ Some of the interface modes are describe + PTP-enabled PHYs. This mode isn't compatible with QSGMII, but offers the + same capabilities in terms of link speed and negociation. + ++``PHY_INTERFACE_MODE_1000BASEKX`` ++ This is 1000BASE-X as defined by IEEE 802.3 Clause 36 with Clause 73 ++ autonegotiation. Generally, it will be used with a Clause 70 PMD. To ++ contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this ++ interface mode has different autonegotiation and only supports full duplex. ++ + Pause frames / flow control + =========================== + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -114,6 +114,7 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_100BASEX: + case PHY_INTERFACE_MODE_RXAUI: + case PHY_INTERFACE_MODE_XAUI: ++ case PHY_INTERFACE_MODE_1000BASEKX: + return 1; + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -390,6 +390,7 @@ void phylink_get_linkmodes(unsigned long + case PHY_INTERFACE_MODE_1000BASEX: + caps |= MAC_1000HD; + fallthrough; ++ case PHY_INTERFACE_MODE_1000BASEKX: + case PHY_INTERFACE_MODE_TRGMII: + caps |= MAC_1000FD; + break; +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -116,6 +116,7 @@ extern const int phy_10gbit_features_arr + * @PHY_INTERFACE_MODE_USXGMII: Universal Serial 10GE MII + * @PHY_INTERFACE_MODE_10GKR: 10GBASE-KR - with Clause 73 AN + * @PHY_INTERFACE_MODE_QUSGMII: Quad Universal SGMII ++ * @PHY_INTERFACE_MODE_1000BASEKX: 1000Base-KX - with Clause 73 AN + * @PHY_INTERFACE_MODE_MAX: Book keeping + * + * Describes the interface between the MAC and PHY. +@@ -154,6 +155,7 @@ typedef enum { + /* 10GBASE-KR - with Clause 73 AN */ + PHY_INTERFACE_MODE_10GKR, + PHY_INTERFACE_MODE_QUSGMII, ++ PHY_INTERFACE_MODE_1000BASEKX, + PHY_INTERFACE_MODE_MAX, + } phy_interface_t; + +@@ -251,6 +253,8 @@ static inline const char *phy_modes(phy_ + return "trgmii"; + case PHY_INTERFACE_MODE_1000BASEX: + return "1000base-x"; ++ case PHY_INTERFACE_MODE_1000BASEKX: ++ return "1000base-kx"; + case PHY_INTERFACE_MODE_2500BASEX: + return "2500base-x"; + case PHY_INTERFACE_MODE_5GBASER: diff --git a/target/linux/generic/backport-5.15/731-v6.1-0004-net-phy-Add-support-for-rate-matching.patch b/target/linux/generic/backport-5.15/731-v6.1-0004-net-phy-Add-support-for-rate-matching.patch new file mode 100644 index 0000000000..fc02d7a4ea --- /dev/null +++ b/target/linux/generic/backport-5.15/731-v6.1-0004-net-phy-Add-support-for-rate-matching.patch @@ -0,0 +1,294 @@ +From 0c3e10cb44232833a50cb8e3e784c432906a60c1 Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Tue, 20 Sep 2022 18:12:31 -0400 +Subject: [PATCH] net: phy: Add support for rate matching + +This adds support for rate matching (also known as rate adaptation) to +the phy subsystem. The general idea is that the phy interface runs at +one speed, and the MAC throttles the rate at which it sends packets to +the link speed. There's a good overview of several techniques for +achieving this at [1]. This patch adds support for three: pause-frame +based (such as in Aquantia phys), CRS-based (such as in 10PASS-TS and +2BASE-TL), and open-loop-based (such as in 10GBASE-W). + +This patch makes a few assumptions and a few non assumptions about the +types of rate matching available. First, it assumes that different phys +may use different forms of rate matching. Second, it assumes that phys +can use rate matching for any of their supported link speeds (e.g. if a +phy supports 10BASE-T and XGMII, then it can adapt XGMII to 10BASE-T). +Third, it does not assume that all interface modes will use the same +form of rate matching. Fourth, it does not assume that all phy devices +will support rate matching (even if some do). Relaxing or strengthening +these (non-)assumptions could result in a different API. For example, if +all interface modes were assumed to use the same form of rate matching, +then a bitmask of interface modes supportting rate matching would +suffice. + +For some better visibility into the process, the current rate matching +mode is exposed as part of the ethtool ksettings. For the moment, only +read access is supported. I'm not sure what userspace might want to +configure yet (disable it altogether, disable just one mode, specify the +mode to use, etc.). For the moment, since only pause-based rate +adaptation support is added in the next few commits, rate matching can +be disabled altogether by adjusting the advertisement. + +802.3 calls this feature "rate adaptation" in clause 49 (10GBASE-R) and +"rate matching" in clause 61 (10PASS-TL and 2BASE-TS). Aquantia also calls +this feature "rate adaptation". I chose "rate matching" because it is +shorter, and because Russell doesn't think "adaptation" is correct in this +context. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + Documentation/networking/ethtool-netlink.rst | 2 ++ + drivers/net/phy/phy-core.c | 21 +++++++++++++++ + drivers/net/phy/phy.c | 28 ++++++++++++++++++++ + include/linux/phy.h | 22 ++++++++++++++- + include/uapi/linux/ethtool.h | 18 +++++++++++-- + include/uapi/linux/ethtool_netlink.h | 1 + + net/ethtool/ioctl.c | 1 + + net/ethtool/linkmodes.c | 5 ++++ + 8 files changed, 95 insertions(+), 3 deletions(-) + +--- a/Documentation/networking/ethtool-netlink.rst ++++ b/Documentation/networking/ethtool-netlink.rst +@@ -418,6 +418,7 @@ Kernel response contents: + ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode + ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG`` u8 Master/slave port mode + ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE`` u8 Master/slave port state ++ ``ETHTOOL_A_LINKMODES_RATE_MATCHING`` u8 PHY rate matching + ========================================== ====== ========================== + + For ``ETHTOOL_A_LINKMODES_OURS``, value represents advertised modes and mask +@@ -441,6 +442,7 @@ Request contents: + ``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s) + ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode + ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG`` u8 Master/slave port mode ++ ``ETHTOOL_A_LINKMODES_RATE_MATCHING`` u8 PHY rate matching + ``ETHTOOL_A_LINKMODES_LANES`` u32 lanes + ========================================== ====== ========================== + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -75,6 +75,27 @@ const char *phy_duplex_to_str(unsigned i + EXPORT_SYMBOL_GPL(phy_duplex_to_str); + + /** ++ * phy_rate_matching_to_str - Return a string describing the rate matching ++ * ++ * @rate_matching: Type of rate matching to describe ++ */ ++const char *phy_rate_matching_to_str(int rate_matching) ++{ ++ switch (rate_matching) { ++ case RATE_MATCH_NONE: ++ return "none"; ++ case RATE_MATCH_PAUSE: ++ return "pause"; ++ case RATE_MATCH_CRS: ++ return "crs"; ++ case RATE_MATCH_OPEN_LOOP: ++ return "open-loop"; ++ } ++ return "Unsupported (update phy-core.c)"; ++} ++EXPORT_SYMBOL_GPL(phy_rate_matching_to_str); ++ ++/** + * phy_interface_num_ports - Return the number of links that can be carried by + * a given MAC-PHY physical link. Returns 0 if this is + * unknown, the number of links else. +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -127,6 +127,33 @@ void phy_print_status(struct phy_device + EXPORT_SYMBOL(phy_print_status); + + /** ++ * phy_get_rate_matching - determine if rate matching is supported ++ * @phydev: The phy device to return rate matching for ++ * @iface: The interface mode to use ++ * ++ * This determines the type of rate matching (if any) that @phy supports ++ * using @iface. @iface may be %PHY_INTERFACE_MODE_NA to determine if any ++ * interface supports rate matching. ++ * ++ * Return: The type of rate matching @phy supports for @iface, or ++ * %RATE_MATCH_NONE. ++ */ ++int phy_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ int ret = RATE_MATCH_NONE; ++ ++ if (phydev->drv->get_rate_matching) { ++ mutex_lock(&phydev->lock); ++ ret = phydev->drv->get_rate_matching(phydev, iface); ++ mutex_unlock(&phydev->lock); ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(phy_get_rate_matching); ++ ++/** + * phy_config_interrupt - configure the PHY device for the requested interrupts + * @phydev: the phy_device struct + * @interrupts: interrupt flags to configure for this @phydev +@@ -268,6 +295,7 @@ void phy_ethtool_ksettings_get(struct ph + cmd->base.duplex = phydev->duplex; + cmd->base.master_slave_cfg = phydev->master_slave_get; + cmd->base.master_slave_state = phydev->master_slave_state; ++ cmd->base.rate_matching = phydev->rate_matching; + if (phydev->interface == PHY_INTERFACE_MODE_MOCA) + cmd->base.port = PORT_BNC; + else +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -280,7 +280,6 @@ static inline const char *phy_modes(phy_ + } + } + +- + #define PHY_INIT_TIMEOUT 100000 + #define PHY_FORCE_TIMEOUT 10 + +@@ -573,6 +572,7 @@ struct macsec_ops; + * @lp_advertising: Current link partner advertised linkmodes + * @eee_broken_modes: Energy efficient ethernet modes which should be prohibited + * @autoneg: Flag autoneg being used ++ * @rate_matching: Current rate matching mode + * @link: Current link state + * @autoneg_complete: Flag auto negotiation of the link has completed + * @mdix: Current crossover +@@ -639,6 +639,8 @@ struct phy_device { + unsigned irq_suspended:1; + unsigned irq_rerun:1; + ++ int rate_matching; ++ + enum phy_state state; + + u32 dev_flags; +@@ -801,6 +803,21 @@ struct phy_driver { + */ + int (*get_features)(struct phy_device *phydev); + ++ /** ++ * @get_rate_matching: Get the supported type of rate matching for a ++ * particular phy interface. This is used by phy consumers to determine ++ * whether to advertise lower-speed modes for that interface. It is ++ * assumed that if a rate matching mode is supported on an interface, ++ * then that interface's rate can be adapted to all slower link speeds ++ * supported by the phy. If iface is %PHY_INTERFACE_MODE_NA, and the phy ++ * supports any kind of rate matching for any interface, then it must ++ * return that rate matching mode (preferring %RATE_MATCH_PAUSE to ++ * %RATE_MATCH_CRS). If the interface is not supported, this should ++ * return %RATE_MATCH_NONE. ++ */ ++ int (*get_rate_matching)(struct phy_device *phydev, ++ phy_interface_t iface); ++ + /* PHY Power Management */ + /** @suspend: Suspend the hardware, saving state if needed */ + int (*suspend)(struct phy_device *phydev); +@@ -967,6 +984,7 @@ struct phy_fixup { + + const char *phy_speed_to_str(int speed); + const char *phy_duplex_to_str(unsigned int duplex); ++const char *phy_rate_matching_to_str(int rate_matching); + + int phy_interface_num_ports(phy_interface_t interface); + +@@ -1675,6 +1693,8 @@ int phy_disable_interrupts(struct phy_de + void phy_request_interrupt(struct phy_device *phydev); + void phy_free_interrupt(struct phy_device *phydev); + void phy_print_status(struct phy_device *phydev); ++int phy_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface); + int phy_set_max_speed(struct phy_device *phydev, u32 max_speed); + void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode); + void phy_advertise_supported(struct phy_device *phydev); +--- a/include/uapi/linux/ethtool.h ++++ b/include/uapi/linux/ethtool.h +@@ -1809,6 +1809,20 @@ static inline int ethtool_validate_duple + #define MASTER_SLAVE_STATE_SLAVE 3 + #define MASTER_SLAVE_STATE_ERR 4 + ++/* These are used to throttle the rate of data on the phy interface when the ++ * native speed of the interface is higher than the link speed. These should ++ * not be used for phy interfaces which natively support multiple speeds (e.g. ++ * MII or SGMII). ++ */ ++/* No rate matching performed. */ ++#define RATE_MATCH_NONE 0 ++/* The phy sends pause frames to throttle the MAC. */ ++#define RATE_MATCH_PAUSE 1 ++/* The phy asserts CRS to prevent the MAC from transmitting. */ ++#define RATE_MATCH_CRS 2 ++/* The MAC is programmed with a sufficiently-large IPG. */ ++#define RATE_MATCH_OPEN_LOOP 3 ++ + /* Which connector port. */ + #define PORT_TP 0x00 + #define PORT_AUI 0x01 +@@ -2002,8 +2016,8 @@ enum ethtool_reset_flags { + * reported consistently by PHYLIB. Read-only. + * @master_slave_cfg: Master/slave port mode. + * @master_slave_state: Master/slave port state. ++ * @rate_matching: Rate adaptation performed by the PHY + * @reserved: Reserved for future use; see the note on reserved space. +- * @reserved1: Reserved for future use; see the note on reserved space. + * @link_mode_masks: Variable length bitmaps. + * + * If autonegotiation is disabled, the speed and @duplex represent the +@@ -2054,7 +2068,7 @@ struct ethtool_link_settings { + __u8 transceiver; + __u8 master_slave_cfg; + __u8 master_slave_state; +- __u8 reserved1[1]; ++ __u8 rate_matching; + __u32 reserved[7]; + __u32 link_mode_masks[0]; + /* layout of link_mode_masks fields: +--- a/include/uapi/linux/ethtool_netlink.h ++++ b/include/uapi/linux/ethtool_netlink.h +@@ -238,6 +238,7 @@ enum { + ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG, /* u8 */ + ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE, /* u8 */ + ETHTOOL_A_LINKMODES_LANES, /* u32 */ ++ ETHTOOL_A_LINKMODES_RATE_MATCHING, /* u8 */ + + /* add new constants above here */ + __ETHTOOL_A_LINKMODES_CNT, +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -559,6 +559,7 @@ static int ethtool_get_link_ksettings(st + = __ETHTOOL_LINK_MODE_MASK_NU32; + link_ksettings.base.master_slave_cfg = MASTER_SLAVE_CFG_UNSUPPORTED; + link_ksettings.base.master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; ++ link_ksettings.base.rate_matching = RATE_MATCH_NONE; + + return store_link_ksettings_for_user(useraddr, &link_ksettings); + } +--- a/net/ethtool/linkmodes.c ++++ b/net/ethtool/linkmodes.c +@@ -70,6 +70,7 @@ static int linkmodes_reply_size(const st + + nla_total_size(sizeof(u32)) /* LINKMODES_SPEED */ + + nla_total_size(sizeof(u32)) /* LINKMODES_LANES */ + + nla_total_size(sizeof(u8)) /* LINKMODES_DUPLEX */ ++ + nla_total_size(sizeof(u8)) /* LINKMODES_RATE_MATCHING */ + + 0; + ret = ethnl_bitset_size(ksettings->link_modes.advertising, + ksettings->link_modes.supported, +@@ -143,6 +144,10 @@ static int linkmodes_fill_reply(struct s + lsettings->master_slave_state)) + return -EMSGSIZE; + ++ if (nla_put_u8(skb, ETHTOOL_A_LINKMODES_RATE_MATCHING, ++ lsettings->rate_matching)) ++ return -EMSGSIZE; ++ + return 0; + } + diff --git a/target/linux/generic/backport-5.15/792-01-v6.0-net-phylink-disable-PCS-polling-over-major-configura.patch b/target/linux/generic/backport-5.15/792-01-v6.0-net-phylink-disable-PCS-polling-over-major-configura.patch index cda77e3e2d..a0cb367ba7 100644 --- a/target/linux/generic/backport-5.15/792-01-v6.0-net-phylink-disable-PCS-polling-over-major-configura.patch +++ b/target/linux/generic/backport-5.15/792-01-v6.0-net-phylink-disable-PCS-polling-over-major-configura.patch @@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -756,6 +756,18 @@ static void phylink_resolve_flow(struct +@@ -759,6 +759,18 @@ static void phylink_resolve_flow(struct } } @@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski static void phylink_mac_config(struct phylink *pl, const struct phylink_link_state *state) { -@@ -787,6 +799,7 @@ static void phylink_major_config(struct +@@ -790,6 +802,7 @@ static void phylink_major_config(struct const struct phylink_link_state *state) { struct phylink_pcs *pcs = NULL; @@ -44,7 +44,7 @@ Signed-off-by: Jakub Kicinski int err; phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); -@@ -799,8 +812,12 @@ static void phylink_major_config(struct +@@ -802,8 +815,12 @@ static void phylink_major_config(struct pcs); return; } @@ -57,7 +57,7 @@ Signed-off-by: Jakub Kicinski if (pl->mac_ops->mac_prepare) { err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode, state->interface); -@@ -814,8 +831,10 @@ static void phylink_major_config(struct +@@ -817,8 +834,10 @@ static void phylink_major_config(struct /* If we have a new PCS, switch to the new PCS after preparing the MAC * for the change. */ @@ -70,7 +70,7 @@ Signed-off-by: Jakub Kicinski phylink_mac_config(pl, state); -@@ -841,6 +860,8 @@ static void phylink_major_config(struct +@@ -844,6 +863,8 @@ static void phylink_major_config(struct phylink_err(pl, "mac_finish failed: %pe\n", ERR_PTR(err)); } diff --git a/target/linux/generic/backport-5.15/792-02-v6.0-net-phylink-fix-NULL-pl-pcs-dereference-during-phyli.patch b/target/linux/generic/backport-5.15/792-02-v6.0-net-phylink-fix-NULL-pl-pcs-dereference-during-phyli.patch index f1f359bad7..fec2fddfda 100644 --- a/target/linux/generic/backport-5.15/792-02-v6.0-net-phylink-fix-NULL-pl-pcs-dereference-during-phyli.patch +++ b/target/linux/generic/backport-5.15/792-02-v6.0-net-phylink-fix-NULL-pl-pcs-dereference-during-phyli.patch @@ -27,7 +27,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -764,7 +764,7 @@ static void phylink_pcs_poll_stop(struct +@@ -767,7 +767,7 @@ static void phylink_pcs_poll_stop(struct static void phylink_pcs_poll_start(struct phylink *pl) { diff --git a/target/linux/generic/backport-5.15/792-03-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch b/target/linux/generic/backport-5.15/792-03-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch index c8176c90f5..71b09cbe75 100644 --- a/target/linux/generic/backport-5.15/792-03-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch +++ b/target/linux/generic/backport-5.15/792-03-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch @@ -35,7 +35,7 @@ Signed-off-by: David S. Miller bool mac_link_dropped; bool using_mac_select_pcs; -@@ -795,6 +800,22 @@ static void phylink_mac_pcs_an_restart(s +@@ -798,6 +803,22 @@ static void phylink_mac_pcs_an_restart(s } } @@ -58,7 +58,7 @@ Signed-off-by: David S. Miller static void phylink_major_config(struct phylink *pl, bool restart, const struct phylink_link_state *state) { -@@ -832,12 +853,16 @@ static void phylink_major_config(struct +@@ -835,12 +856,16 @@ static void phylink_major_config(struct * for the change. */ if (pcs_changed) { @@ -75,7 +75,7 @@ Signed-off-by: David S. Miller if (pl->pcs_ops) { err = pl->pcs_ops->pcs_config(pl->pcs, pl->cur_link_an_mode, state->interface, -@@ -1261,6 +1286,7 @@ struct phylink *phylink_create(struct ph +@@ -1264,6 +1289,7 @@ struct phylink *phylink_create(struct ph pl->link_config.speed = SPEED_UNKNOWN; pl->link_config.duplex = DUPLEX_UNKNOWN; pl->link_config.an_enabled = true; @@ -83,7 +83,7 @@ Signed-off-by: David S. Miller pl->mac_ops = mac_ops; __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); timer_setup(&pl->link_poll, phylink_fixed_poll, 0); -@@ -1652,6 +1678,8 @@ void phylink_start(struct phylink *pl) +@@ -1655,6 +1681,8 @@ void phylink_start(struct phylink *pl) if (pl->netdev) netif_carrier_off(pl->netdev); @@ -92,7 +92,7 @@ Signed-off-by: David S. Miller /* Apply the link configuration to the MAC when starting. This allows * a fixed-link to start with the correct parameters, and also * ensures that we set the appropriate advertisement for Serdes links. -@@ -1662,6 +1690,8 @@ void phylink_start(struct phylink *pl) +@@ -1665,6 +1693,8 @@ void phylink_start(struct phylink *pl) */ phylink_mac_initial_config(pl, true); @@ -101,7 +101,7 @@ Signed-off-by: David S. Miller clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); phylink_run_resolve(pl); -@@ -1681,16 +1711,9 @@ void phylink_start(struct phylink *pl) +@@ -1684,16 +1714,9 @@ void phylink_start(struct phylink *pl) poll = true; } @@ -120,7 +120,7 @@ Signed-off-by: David S. Miller if (poll) mod_timer(&pl->link_poll, jiffies + HZ); if (pl->phydev) -@@ -1727,6 +1750,10 @@ void phylink_stop(struct phylink *pl) +@@ -1730,6 +1753,10 @@ void phylink_stop(struct phylink *pl) } phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED); diff --git a/target/linux/generic/backport-5.15/815-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch b/target/linux/generic/backport-5.15/815-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch index 3e60f91a2a..6e5ac8b249 100644 --- a/target/linux/generic/backport-5.15/815-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch +++ b/target/linux/generic/backport-5.15/815-v6.4-05-net-phy-Add-a-binding-for-PHY-LEDs.patch @@ -153,7 +153,7 @@ Signed-off-by: David S. Miller #include #include #include -@@ -582,6 +583,7 @@ struct macsec_ops; +@@ -590,6 +591,7 @@ struct macsec_ops; * @phy_num_led_triggers: Number of triggers in @phy_led_triggers * @led_link_trigger: LED trigger for link up/down * @last_triggered: last LED trigger for link speed @@ -161,7 +161,7 @@ Signed-off-by: David S. Miller * @master_slave_set: User requested master/slave configuration * @master_slave_get: Current master/slave advertisement * @master_slave_state: Current master/slave configuration -@@ -668,6 +670,7 @@ struct phy_device { +@@ -678,6 +680,7 @@ struct phy_device { struct phy_led_trigger *led_link_trigger; #endif @@ -169,7 +169,7 @@ Signed-off-by: David S. Miller /* * Interrupt number for this PHY -@@ -739,6 +742,19 @@ struct phy_tdr_config { +@@ -749,6 +752,19 @@ struct phy_tdr_config { #define PHY_PAIR_ALL -1 /** diff --git a/target/linux/generic/backport-5.15/815-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-5.15/815-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index f990557cc7..3968a884b8 100644 --- a/target/linux/generic/backport-5.15/815-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/target/linux/generic/backport-5.15/815-v6.4-06-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -59,7 +59,7 @@ Signed-off-by: David S. Miller init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -745,15 +745,19 @@ struct phy_tdr_config { +@@ -755,15 +755,19 @@ struct phy_tdr_config { * struct phy_led: An LED driven by the PHY * * @list: List of LEDs @@ -79,7 +79,7 @@ Signed-off-by: David S. Miller /** * struct phy_driver - Driver structure for a particular PHY type * -@@ -953,6 +957,15 @@ struct phy_driver { +@@ -978,6 +982,15 @@ struct phy_driver { int (*get_sqi)(struct phy_device *dev); /** @get_sqi_max: Get the maximum signal quality indication */ int (*get_sqi_max)(struct phy_device *dev); diff --git a/target/linux/generic/backport-5.15/815-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch b/target/linux/generic/backport-5.15/815-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch index 4814688de4..35e1a1c723 100644 --- a/target/linux/generic/backport-5.15/815-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch +++ b/target/linux/generic/backport-5.15/815-v6.4-08-net-phy-phy_device-Call-into-the-PHY-driver-to-set-L.patch @@ -52,7 +52,7 @@ Signed-off-by: David S. Miller init_data.fwnode = of_fwnode_handle(led); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -966,6 +966,18 @@ struct phy_driver { +@@ -991,6 +991,18 @@ struct phy_driver { */ int (*led_brightness_set)(struct phy_device *dev, u8 index, enum led_brightness value); diff --git a/target/linux/generic/backport-5.15/894-v6.8-net-ethtool-implement-ethtool_puts.patch b/target/linux/generic/backport-5.15/894-v6.8-net-ethtool-implement-ethtool_puts.patch index ef9e706cb4..283e226d16 100644 --- a/target/linux/generic/backport-5.15/894-v6.8-net-ethtool-implement-ethtool_puts.patch +++ b/target/linux/generic/backport-5.15/894-v6.8-net-ethtool-implement-ethtool_puts.patch @@ -123,7 +123,7 @@ Signed-off-by: Justin Stitt #endif /* _LINUX_ETHTOOL_H */ --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c -@@ -1953,6 +1953,13 @@ __printf(2, 3) void ethtool_sprintf(u8 * +@@ -1954,6 +1954,13 @@ __printf(2, 3) void ethtool_sprintf(u8 * } EXPORT_SYMBOL(ethtool_sprintf); diff --git a/target/linux/generic/hack-5.15/795-backport-phylink_pcs-helpers.patch b/target/linux/generic/hack-5.15/795-backport-phylink_pcs-helpers.patch index a463bf7c4e..f93d84c6a4 100644 --- a/target/linux/generic/hack-5.15/795-backport-phylink_pcs-helpers.patch +++ b/target/linux/generic/hack-5.15/795-backport-phylink_pcs-helpers.patch @@ -57,7 +57,7 @@ Signed-off-by: Daniel Golle const unsigned long *advertising); --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -931,7 +931,6 @@ static int phylink_change_inband_advert( +@@ -934,7 +934,6 @@ static int phylink_change_inband_advert( return 0; } @@ -65,7 +65,7 @@ Signed-off-by: Daniel Golle static void phylink_mac_pcs_get_state(struct phylink *pl, struct phylink_link_state *state) { -@@ -3015,6 +3014,52 @@ void phylink_mii_c22_pcs_get_state(struc +@@ -3019,6 +3018,52 @@ void phylink_mii_c22_pcs_get_state(struc EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_get_state); /** @@ -118,7 +118,7 @@ Signed-off-by: Daniel Golle * phylink_mii_c22_pcs_set_advertisement() - configure the clause 37 PCS * advertisement * @pcs: a pointer to a &struct mdio_device. -@@ -3086,6 +3131,46 @@ int phylink_mii_c22_pcs_set_advertisemen +@@ -3090,6 +3135,46 @@ int phylink_mii_c22_pcs_set_advertisemen EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_set_advertisement); /** diff --git a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch index 83587b5c93..f93dca6814 100644 --- a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos sysfs_remove_link(&dev->dev.kobj, "phydev"); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -843,6 +843,12 @@ struct phy_driver { +@@ -868,6 +868,12 @@ struct phy_driver { /** @handle_interrupt: Override default interrupt handling */ irqreturn_t (*handle_interrupt)(struct phy_device *phydev); diff --git a/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch index 46c304032d..daf6cf3ce7 100644 --- a/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch +++ b/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch @@ -13,7 +13,7 @@ Signed-off-by: Bhaskar Upadhaya --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -398,6 +398,7 @@ void phylink_get_linkmodes(unsigned long +@@ -400,6 +400,7 @@ void phylink_get_linkmodes(unsigned long caps |= MAC_1000FD; break; @@ -21,7 +21,7 @@ Signed-off-by: Bhaskar Upadhaya case PHY_INTERFACE_MODE_2500BASEX: caps |= MAC_2500FD; break; -@@ -651,6 +652,10 @@ static int phylink_parse_mode(struct phy +@@ -654,6 +655,10 @@ static int phylink_parse_mode(struct phy phylink_set(pl->supported, 2500baseX_Full); break; @@ -34,18 +34,18 @@ Signed-off-by: Bhaskar Upadhaya break; --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -153,6 +153,7 @@ typedef enum { - PHY_INTERFACE_MODE_USXGMII, - /* 10GBASE-KR - with Clause 73 AN */ +@@ -157,6 +157,7 @@ typedef enum { PHY_INTERFACE_MODE_10GKR, + PHY_INTERFACE_MODE_QUSGMII, + PHY_INTERFACE_MODE_1000BASEKX, + PHY_INTERFACE_MODE_2500SGMII, PHY_INTERFACE_MODE_MAX, } phy_interface_t; -@@ -268,6 +269,8 @@ static inline const char *phy_modes(phy_ - return "10gbase-kr"; - case PHY_INTERFACE_MODE_100BASEX: +@@ -276,6 +277,8 @@ static inline const char *phy_modes(phy_ return "100base-x"; + case PHY_INTERFACE_MODE_QUSGMII: + return "qusgmii"; + case PHY_INTERFACE_MODE_2500SGMII: + return "sgmii-2500"; default: diff --git a/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch b/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch index 437c761132..1262e9498d 100644 --- a/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch +++ b/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch @@ -33,7 +33,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c phy_led_trigger_change_speed(phydev); } -@@ -563,7 +563,7 @@ int phy_start_cable_test(struct phy_devi +@@ -591,7 +591,7 @@ int phy_start_cable_test(struct phy_devi goto out; /* Mark the carrier down until the test is complete */ @@ -42,7 +42,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c netif_testing_on(dev); err = phydev->drv->cable_test_start(phydev); -@@ -634,7 +634,7 @@ int phy_start_cable_test_tdr(struct phy_ +@@ -662,7 +662,7 @@ int phy_start_cable_test_tdr(struct phy_ goto out; /* Mark the carrier down until the test is complete */ @@ -51,7 +51,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c netif_testing_on(dev); err = phydev->drv->cable_test_tdr_start(phydev, config); -@@ -706,7 +706,7 @@ static int phy_check_link_status(struct +@@ -734,7 +734,7 @@ static int phy_check_link_status(struct phy_link_up(phydev); } else if (!phydev->link && phydev->state != PHY_NOLINK) { phydev->state = PHY_NOLINK; @@ -60,7 +60,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c } return 0; -@@ -1192,7 +1192,7 @@ void phy_state_machine(struct work_struc +@@ -1220,7 +1220,7 @@ void phy_state_machine(struct work_struc case PHY_HALTED: if (phydev->link) { phydev->link = 0; @@ -95,7 +95,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c phydev->mii_ts->link_state(phydev->mii_ts, phydev); --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -1370,7 +1370,8 @@ void phylink_destroy(struct phylink *pl) +@@ -1373,7 +1373,8 @@ void phylink_destroy(struct phylink *pl) } EXPORT_SYMBOL_GPL(phylink_destroy); @@ -107,7 +107,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c bool tx_pause, rx_pause; --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -706,7 +706,7 @@ struct phy_device { +@@ -716,7 +716,7 @@ struct phy_device { u8 mdix; u8 mdix_ctrl; diff --git a/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch b/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch index 5205a8f936..fc7873a01b 100644 --- a/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch +++ b/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch @@ -11,7 +11,7 @@ Signed-off-by: John Crispin --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c -@@ -706,7 +706,10 @@ static int phy_check_link_status(struct +@@ -734,7 +734,10 @@ static int phy_check_link_status(struct phy_link_up(phydev); } else if (!phydev->link && phydev->state != PHY_NOLINK) { phydev->state = PHY_NOLINK; @@ -23,7 +23,7 @@ Signed-off-by: John Crispin } return 0; -@@ -1192,7 +1195,10 @@ void phy_state_machine(struct work_struc +@@ -1220,7 +1223,10 @@ void phy_state_machine(struct work_struc case PHY_HALTED: if (phydev->link) { phydev->link = 0; @@ -37,7 +37,7 @@ Signed-off-by: John Crispin break; --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -622,6 +622,7 @@ struct phy_device { +@@ -630,6 +630,7 @@ struct phy_device { unsigned downshifted_rate:1; unsigned is_on_sfp_module:1; unsigned mac_managed_pm:1; diff --git a/target/linux/realtek/patches-5.15/703-include-linux-add-phy-ops-for-rtl838x.patch b/target/linux/realtek/patches-5.15/703-include-linux-add-phy-ops-for-rtl838x.patch index 04a110a233..bf4d35764e 100644 --- a/target/linux/realtek/patches-5.15/703-include-linux-add-phy-ops-for-rtl838x.patch +++ b/target/linux/realtek/patches-5.15/703-include-linux-add-phy-ops-for-rtl838x.patch @@ -21,7 +21,7 @@ Submitted-by: John Crispin --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -984,6 +984,10 @@ struct phy_driver { +@@ -1009,6 +1009,10 @@ struct phy_driver { int (*led_blink_set)(struct phy_device *dev, u8 index, unsigned long *delay_on, unsigned long *delay_off); diff --git a/target/linux/realtek/patches-5.15/704-drivers-net-phy-eee-support-for-rtl838x.patch b/target/linux/realtek/patches-5.15/704-drivers-net-phy-eee-support-for-rtl838x.patch index 6b24df4674..bf6e517cfb 100644 --- a/target/linux/realtek/patches-5.15/704-drivers-net-phy-eee-support-for-rtl838x.patch +++ b/target/linux/realtek/patches-5.15/704-drivers-net-phy-eee-support-for-rtl838x.patch @@ -21,7 +21,7 @@ Submitted-by: John Crispin --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -1991,6 +1991,11 @@ int phylink_ethtool_ksettings_set(struct +@@ -1994,6 +1994,11 @@ int phylink_ethtool_ksettings_set(struct * the presence of a PHY, this should not be changed as that * should be determined from the media side advertisement. */ @@ -33,7 +33,7 @@ Submitted-by: John Crispin return phy_ethtool_ksettings_set(pl->phydev, kset); } -@@ -2294,8 +2299,11 @@ int phylink_ethtool_get_eee(struct phyli +@@ -2297,8 +2302,11 @@ int phylink_ethtool_get_eee(struct phyli ASSERT_RTNL(); @@ -46,7 +46,7 @@ Submitted-by: John Crispin return ret; } -@@ -2312,8 +2320,11 @@ int phylink_ethtool_set_eee(struct phyli +@@ -2315,8 +2323,11 @@ int phylink_ethtool_set_eee(struct phyli ASSERT_RTNL(); diff --git a/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch b/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch index 2048e22f2e..4c573e2bb0 100644 --- a/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch +++ b/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch @@ -15,7 +15,7 @@ Submitted-by: Birger Koblitz --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -408,6 +408,7 @@ void phylink_get_linkmodes(unsigned long +@@ -410,6 +410,7 @@ void phylink_get_linkmodes(unsigned long case PHY_INTERFACE_MODE_XGMII: case PHY_INTERFACE_MODE_RXAUI: @@ -23,7 +23,7 @@ Submitted-by: Birger Koblitz case PHY_INTERFACE_MODE_XAUI: case PHY_INTERFACE_MODE_10GBASER: case PHY_INTERFACE_MODE_10GKR: -@@ -662,6 +663,7 @@ static int phylink_parse_mode(struct phy +@@ -665,6 +666,7 @@ static int phylink_parse_mode(struct phy fallthrough; case PHY_INTERFACE_MODE_USXGMII: case PHY_INTERFACE_MODE_10GKR: @@ -33,7 +33,7 @@ Submitted-by: Birger Koblitz phylink_set(pl->supported, 10baseT_Full); --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -139,6 +139,7 @@ typedef enum { +@@ -141,6 +141,7 @@ typedef enum { PHY_INTERFACE_MODE_XGMII, PHY_INTERFACE_MODE_XLGMII, PHY_INTERFACE_MODE_MOCA, @@ -41,7 +41,7 @@ Submitted-by: Birger Koblitz PHY_INTERFACE_MODE_QSGMII, PHY_INTERFACE_MODE_TRGMII, PHY_INTERFACE_MODE_100BASEX, -@@ -244,6 +245,8 @@ static inline const char *phy_modes(phy_ +@@ -248,6 +249,8 @@ static inline const char *phy_modes(phy_ return "xlgmii"; case PHY_INTERFACE_MODE_MOCA: return "moca"; diff --git a/target/linux/realtek/patches-5.15/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch b/target/linux/realtek/patches-5.15/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch index 56ce80bb20..9a6b00d7c0 100644 --- a/target/linux/realtek/patches-5.15/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch +++ b/target/linux/realtek/patches-5.15/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch @@ -21,7 +21,7 @@ Submitted-by: John Crispin --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -280,7 +280,7 @@ static inline const char *phy_modes(phy_ +@@ -287,7 +287,7 @@ static inline const char *phy_modes(phy_ #define PHY_INIT_TIMEOUT 100000 #define PHY_FORCE_TIMEOUT 10 diff --git a/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch b/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch index b0a8fadb5f..937e5d3161 100644 --- a/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch +++ b/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch @@ -443,7 +443,7 @@ Signed-off-by: Daniel Golle * @dev: target MDIO device --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c -@@ -482,10 +482,16 @@ int __phy_read_mmd(struct phy_device *ph +@@ -556,10 +556,16 @@ int __phy_read_mmd(struct phy_device *ph struct mii_bus *bus = phydev->mdio.bus; int phy_addr = phydev->mdio.addr; @@ -464,7 +464,7 @@ Signed-off-by: Daniel Golle } return val; } -@@ -538,12 +544,18 @@ int __phy_write_mmd(struct phy_device *p +@@ -612,12 +618,18 @@ int __phy_write_mmd(struct phy_device *p struct mii_bus *bus = phydev->mdio.bus; int phy_addr = phydev->mdio.addr; @@ -487,7 +487,7 @@ Signed-off-by: Daniel Golle } return ret; } -@@ -749,6 +761,13 @@ EXPORT_SYMBOL_GPL(phy_modify_mmd); +@@ -823,6 +835,13 @@ EXPORT_SYMBOL_GPL(phy_modify_mmd); static int __phy_read_page(struct phy_device *phydev) { @@ -501,7 +501,7 @@ Signed-off-by: Daniel Golle if (WARN_ONCE(!phydev->drv->read_page, "read_page callback not available, PHY driver not loaded?\n")) return -EOPNOTSUPP; -@@ -757,6 +776,13 @@ static int __phy_read_page(struct phy_de +@@ -831,6 +850,13 @@ static int __phy_read_page(struct phy_de static int __phy_write_page(struct phy_device *phydev, int page) { @@ -515,7 +515,7 @@ Signed-off-by: Daniel Golle if (WARN_ONCE(!phydev->drv->write_page, "write_page callback not available, PHY driver not loaded?\n")) return -EOPNOTSUPP; -@@ -858,6 +884,18 @@ int phy_read_paged(struct phy_device *ph +@@ -932,6 +958,18 @@ int phy_read_paged(struct phy_device *ph { int ret = 0, oldpage; @@ -534,7 +534,7 @@ Signed-off-by: Daniel Golle oldpage = phy_select_page(phydev, page); if (oldpage >= 0) ret = __phy_read(phydev, regnum); -@@ -879,6 +917,18 @@ int phy_write_paged(struct phy_device *p +@@ -953,6 +991,18 @@ int phy_write_paged(struct phy_device *p { int ret = 0, oldpage; @@ -665,7 +665,7 @@ Signed-off-by: Daniel Golle #define MDIO_DEVICE_IS_PHY 0x80000000 /** -@@ -421,6 +422,22 @@ struct mii_bus { +@@ -428,6 +429,22 @@ struct mii_bus { /** @shared: shared state across different PHYs */ struct phy_package_shared *shared[PHY_MAX_ADDR]; @@ -688,7 +688,7 @@ Signed-off-by: Daniel Golle }; #define to_mii_bus(d) container_of(d, struct mii_bus, dev) -@@ -1795,6 +1812,66 @@ static inline int __phy_package_read(str +@@ -1825,6 +1842,66 @@ static inline int __phy_package_read(str return __mdiobus_read(phydev->mdio.bus, shared->addr, regnum); } @@ -755,7 +755,7 @@ Signed-off-by: Daniel Golle static inline int phy_package_write(struct phy_device *phydev, u32 regnum, u16 val) { -@@ -1817,6 +1894,72 @@ static inline int __phy_package_write(st +@@ -1847,6 +1924,72 @@ static inline int __phy_package_write(st return __mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val); } From 418aadaec9dd9c67b2a4fffb51dfa1fb5fdf5098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 26 Jan 2024 06:19:42 +0100 Subject: [PATCH 208/222] kernel: 5.15: update Aquantia PHY driver to v6.1 code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backport few upstream changes included between v5.15 and v6.1. Signed-off-by: Rafał Miłecki --- ...net-phy-Add-support-for-AQR113C-EPHY.patch | 58 +++++++ ...a-Add-some-additional-phy-interfaces.patch | 71 +++++++++ ...uantia-Add-support-for-rate-matching.patch | 148 ++++++++++++++++++ .../hack-5.15/720-net-phy-add-aqr-phys.patch | 56 ++----- ...hy-aquantia-enable-AQR112-and-AQR412.patch | 32 ++-- ...aquantia-fix-system-side-protocol-mi.patch | 2 +- ...y-aquantia-Add-AQR113-driver-support.patch | 26 +-- ...ntia-add-PHY_IDs-for-AQR112-variants.patch | 26 +-- ...-aquantia-enable-AQR111-and-AQR111B0.patch | 28 ++-- 9 files changed, 348 insertions(+), 99 deletions(-) create mode 100644 target/linux/generic/backport-5.15/735-v6.0-0001-net-phy-Add-support-for-AQR113C-EPHY.patch create mode 100644 target/linux/generic/backport-5.15/736-v6.1-0001-net-phy-aquantia-Add-some-additional-phy-interfaces.patch create mode 100644 target/linux/generic/backport-5.15/736-v6.1-0002-net-phy-aquantia-Add-support-for-rate-matching.patch diff --git a/target/linux/generic/backport-5.15/735-v6.0-0001-net-phy-Add-support-for-AQR113C-EPHY.patch b/target/linux/generic/backport-5.15/735-v6.0-0001-net-phy-Add-support-for-AQR113C-EPHY.patch new file mode 100644 index 0000000000..6090a40eae --- /dev/null +++ b/target/linux/generic/backport-5.15/735-v6.0-0001-net-phy-Add-support-for-AQR113C-EPHY.patch @@ -0,0 +1,58 @@ +From 12cf1b89a66828719b2135891b65bd5d03eedea9 Mon Sep 17 00:00:00 2001 +From: Bhadram Varka +Date: Tue, 21 Jun 2022 09:10:27 +0530 +Subject: [PATCH] net: phy: Add support for AQR113C EPHY + +Add support multi-gigabit and single-port Ethernet +PHY transceiver (AQR113C). + +Signed-off-by: Bhadram Varka +Link: https://lore.kernel.org/r/20220621034027.56508-1-vbhadram@nvidia.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/aquantia_main.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/net/phy/aquantia_main.c ++++ b/drivers/net/phy/aquantia_main.c +@@ -22,6 +22,7 @@ + #define PHY_ID_AQR107 0x03a1b4e0 + #define PHY_ID_AQCS109 0x03a1b5c2 + #define PHY_ID_AQR405 0x03a1b4b0 ++#define PHY_ID_AQR113C 0x31c31c12 + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -744,6 +745,24 @@ static struct phy_driver aqr_driver[] = + .handle_interrupt = aqr_handle_interrupt, + .read_status = aqr_read_status, + }, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), ++ .name = "Aquantia AQR113C", ++ .probe = aqr107_probe, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, + }; + + module_phy_driver(aqr_driver); +@@ -756,6 +775,7 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { } + }; + diff --git a/target/linux/generic/backport-5.15/736-v6.1-0001-net-phy-aquantia-Add-some-additional-phy-interfaces.patch b/target/linux/generic/backport-5.15/736-v6.1-0001-net-phy-aquantia-Add-some-additional-phy-interfaces.patch new file mode 100644 index 0000000000..ec8485e0a7 --- /dev/null +++ b/target/linux/generic/backport-5.15/736-v6.1-0001-net-phy-aquantia-Add-some-additional-phy-interfaces.patch @@ -0,0 +1,71 @@ +From 7de26bf144f6a72858ab60afb2bd2b43265ee0ad Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Tue, 20 Sep 2022 18:12:34 -0400 +Subject: [PATCH] net: phy: aquantia: Add some additional phy interfaces + +These are documented in the AQR115 register reference. I haven't tested +them, but perhaps they'll be useful to someone. + +Signed-off-by: Sean Anderson +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia_main.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/aquantia_main.c ++++ b/drivers/net/phy/aquantia_main.c +@@ -27,9 +27,12 @@ + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX 1 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII 3 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10 + + #define MDIO_AN_VEND_PROV 0xc400 +@@ -401,15 +404,24 @@ static int aqr107_read_status(struct phy + case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: + phydev->interface = PHY_INTERFACE_MODE_10GKR; + break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX: ++ phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; ++ break; + case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: + phydev->interface = PHY_INTERFACE_MODE_10GBASER; + break; + case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: + phydev->interface = PHY_INTERFACE_MODE_USXGMII; + break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI: ++ phydev->interface = PHY_INTERFACE_MODE_XAUI; ++ break; + case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: + phydev->interface = PHY_INTERFACE_MODE_SGMII; + break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI: ++ phydev->interface = PHY_INTERFACE_MODE_RXAUI; ++ break; + case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: + phydev->interface = PHY_INTERFACE_MODE_2500BASEX; + break; +@@ -522,11 +534,14 @@ static int aqr107_config_init(struct phy + + /* Check that the PHY interface type is compatible */ + if (phydev->interface != PHY_INTERFACE_MODE_SGMII && ++ phydev->interface != PHY_INTERFACE_MODE_1000BASEKX && + phydev->interface != PHY_INTERFACE_MODE_2500BASEX && + phydev->interface != PHY_INTERFACE_MODE_XGMII && + phydev->interface != PHY_INTERFACE_MODE_USXGMII && + phydev->interface != PHY_INTERFACE_MODE_10GKR && +- phydev->interface != PHY_INTERFACE_MODE_10GBASER) ++ phydev->interface != PHY_INTERFACE_MODE_10GBASER && ++ phydev->interface != PHY_INTERFACE_MODE_XAUI && ++ phydev->interface != PHY_INTERFACE_MODE_RXAUI) + return -ENODEV; + + WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII, diff --git a/target/linux/generic/backport-5.15/736-v6.1-0002-net-phy-aquantia-Add-support-for-rate-matching.patch b/target/linux/generic/backport-5.15/736-v6.1-0002-net-phy-aquantia-Add-support-for-rate-matching.patch new file mode 100644 index 0000000000..d5d58762ce --- /dev/null +++ b/target/linux/generic/backport-5.15/736-v6.1-0002-net-phy-aquantia-Add-support-for-rate-matching.patch @@ -0,0 +1,148 @@ +From 3c42563b30417afc8855a3b4c1b38c2f36f78657 Mon Sep 17 00:00:00 2001 +From: Sean Anderson +Date: Tue, 20 Sep 2022 18:12:35 -0400 +Subject: [PATCH] net: phy: aquantia: Add support for rate matching + +This adds support for rate matching for phys similar to the AQR107. We +assume that all phys using aqr107_read_status support rate matching. +However, it could be possible to determine support based on the firmware +revision if there are phys discovered which do not support rate +matching. However, as rate matching is advertised in the datasheets for +these phys, I suspect it is supported most boards. + +Despite the name, the "config" registers are updated with the current +rate matching method (if any). Because they appear to be updated +automatically, I don't know if these registers can be used to disable +rate matching. + +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia_main.c | 51 ++++++++++++++++++++++++++++++--- + 1 file changed, 47 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/aquantia_main.c ++++ b/drivers/net/phy/aquantia_main.c +@@ -97,6 +97,19 @@ + #define VEND1_GLOBAL_GEN_STAT2 0xc831 + #define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) + ++/* The following registers all have similar layouts; first the registers... */ ++#define VEND1_GLOBAL_CFG_10M 0x0310 ++#define VEND1_GLOBAL_CFG_100M 0x031b ++#define VEND1_GLOBAL_CFG_1G 0x031c ++#define VEND1_GLOBAL_CFG_2_5G 0x031d ++#define VEND1_GLOBAL_CFG_5G 0x031e ++#define VEND1_GLOBAL_CFG_10G 0x031f ++/* ...and now the fields */ ++#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 ++ + #define VEND1_GLOBAL_RSVD_STAT1 0xc885 + #define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) + #define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) +@@ -347,40 +360,57 @@ static int aqr_read_status(struct phy_de + + static int aqr107_read_rate(struct phy_device *phydev) + { ++ u32 config_reg; + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); + if (val < 0) + return val; + ++ if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ + switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) { + case MDIO_AN_TX_VEND_STATUS1_10BASET: + phydev->speed = SPEED_10; ++ config_reg = VEND1_GLOBAL_CFG_10M; + break; + case MDIO_AN_TX_VEND_STATUS1_100BASETX: + phydev->speed = SPEED_100; ++ config_reg = VEND1_GLOBAL_CFG_100M; + break; + case MDIO_AN_TX_VEND_STATUS1_1000BASET: + phydev->speed = SPEED_1000; ++ config_reg = VEND1_GLOBAL_CFG_1G; + break; + case MDIO_AN_TX_VEND_STATUS1_2500BASET: + phydev->speed = SPEED_2500; ++ config_reg = VEND1_GLOBAL_CFG_2_5G; + break; + case MDIO_AN_TX_VEND_STATUS1_5000BASET: + phydev->speed = SPEED_5000; ++ config_reg = VEND1_GLOBAL_CFG_5G; + break; + case MDIO_AN_TX_VEND_STATUS1_10GBASET: + phydev->speed = SPEED_10000; ++ config_reg = VEND1_GLOBAL_CFG_10G; + break; + default: + phydev->speed = SPEED_UNKNOWN; +- break; ++ return 0; + } + +- if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) +- phydev->duplex = DUPLEX_FULL; ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg); ++ if (val < 0) ++ return val; ++ ++ if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) == ++ VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE) ++ phydev->rate_matching = RATE_MATCH_PAUSE; + else +- phydev->duplex = DUPLEX_HALF; ++ phydev->rate_matching = RATE_MATCH_NONE; + + return 0; + } +@@ -647,6 +677,16 @@ static int aqr107_wait_processor_intensi + return 0; + } + ++static int aqr107_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ if (iface == PHY_INTERFACE_MODE_10GBASER || ++ iface == PHY_INTERFACE_MODE_2500BASEX || ++ iface == PHY_INTERFACE_MODE_NA) ++ return RATE_MATCH_PAUSE; ++ return RATE_MATCH_NONE; ++} ++ + static int aqr107_suspend(struct phy_device *phydev) + { + int err; +@@ -720,6 +760,7 @@ static struct phy_driver aqr_driver[] = + PHY_ID_MATCH_MODEL(PHY_ID_AQR107), + .name = "Aquantia AQR107", + .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, + .config_init = aqr107_config_init, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, +@@ -738,6 +779,7 @@ static struct phy_driver aqr_driver[] = + PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), + .name = "Aquantia AQCS109", + .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, + .config_init = aqcs109_config_init, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, +@@ -764,6 +806,7 @@ static struct phy_driver aqr_driver[] = + PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), + .name = "Aquantia AQR113C", + .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, + .config_init = aqr107_config_init, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, diff --git a/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch index 29050d38ea..d8ec95b374 100644 --- a/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch +++ b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch @@ -9,18 +9,15 @@ Signed-off-by: Birger Koblitz --- a/drivers/net/phy/aquantia_main.c +++ b/drivers/net/phy/aquantia_main.c -@@ -20,8 +20,10 @@ - #define PHY_ID_AQR105 0x03a1b4a2 - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 -+#define PHY_ID_AQR113C 0x31c31c12 +@@ -23,6 +23,7 @@ #define PHY_ID_AQCS109 0x03a1b5c2 #define PHY_ID_AQR405 0x03a1b4b0 + #define PHY_ID_AQR113C 0x31c31c12 +#define PHY_ID_AQR813 0x31c31cb2 #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -381,6 +383,49 @@ static int aqr107_read_rate(struct phy_d +@@ -415,6 +416,49 @@ static int aqr107_read_rate(struct phy_d return 0; } @@ -70,7 +67,7 @@ Signed-off-by: Birger Koblitz static int aqr107_read_status(struct phy_device *phydev) { int val, ret; -@@ -511,7 +556,7 @@ static void aqr107_chip_info(struct phy_ +@@ -554,7 +598,7 @@ static void aqr107_chip_info(struct phy_ build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); @@ -79,35 +76,19 @@ Signed-off-by: Birger Koblitz fw_major, fw_minor, build_id, prov_id); } -@@ -719,6 +764,24 @@ static struct phy_driver aqr_driver[] = +@@ -811,7 +855,7 @@ static struct phy_driver aqr_driver[] = + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, ++ .read_status = aqr113c_read_status, + .get_tunable = aqr107_get_tunable, + .set_tunable = aqr107_set_tunable, + .suspend = aqr107_suspend, +@@ -821,6 +865,24 @@ static struct phy_driver aqr_driver[] = + .get_stats = aqr107_get_stats, .link_change_notify = aqr107_link_change_notify, }, - { -+ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), -+ .name = "Aquantia AQR113C", -+ .probe = aqr107_probe, -+ .config_init = aqr107_config_init, -+ .config_aneg = aqr_config_aneg, -+ .config_intr = aqr_config_intr, -+ .handle_interrupt = aqr_handle_interrupt, -+ .read_status = aqr113c_read_status, -+ .get_tunable = aqr107_get_tunable, -+ .set_tunable = aqr107_set_tunable, -+ .suspend = aqr107_suspend, -+ .resume = aqr107_resume, -+ .get_sset_count = aqr107_get_sset_count, -+ .get_strings = aqr107_get_strings, -+ .get_stats = aqr107_get_stats, -+ .link_change_notify = aqr107_link_change_notify, -+}, -+{ - PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), - .name = "Aquantia AQCS109", - .probe = aqr107_probe, -@@ -744,6 +807,24 @@ static struct phy_driver aqr_driver[] = - .handle_interrupt = aqr_handle_interrupt, - .read_status = aqr_read_status, - }, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR813), + .name = "Aquantia AQR813", @@ -129,13 +110,10 @@ Signed-off-by: Birger Koblitz }; module_phy_driver(aqr_driver); -@@ -754,8 +835,10 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, +@@ -834,6 +896,7 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, { } }; diff --git a/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch index 211696c568..f80757cae9 100644 --- a/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch +++ b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch @@ -15,19 +15,16 @@ Signed-off-by: Alex Marginean --- a/drivers/net/phy/aquantia_main.c +++ b/drivers/net/phy/aquantia_main.c -@@ -20,9 +20,11 @@ - #define PHY_ID_AQR105 0x03a1b4a2 - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 -+#define PHY_ID_AQR112 0x03a1b662 - #define PHY_ID_AQR113C 0x31c31c12 - #define PHY_ID_AQCS109 0x03a1b5c2 +@@ -24,6 +24,8 @@ #define PHY_ID_AQR405 0x03a1b4b0 -+#define PHY_ID_AQR412 0x03a1b712 + #define PHY_ID_AQR113C 0x31c31c12 #define PHY_ID_AQR813 0x31c31cb2 ++#define PHY_ID_AQR112 0x03a1b662 ++#define PHY_ID_AQR412 0x03a1b712 #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 -@@ -135,6 +137,29 @@ + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -151,6 +153,29 @@ #define AQR107_OP_IN_PROG_SLEEP 1000 #define AQR107_OP_IN_PROG_TIMEOUT 100000 @@ -57,7 +54,7 @@ Signed-off-by: Alex Marginean struct aqr107_hw_stat { const char *name; int reg; -@@ -266,6 +291,51 @@ static int aqr_config_aneg(struct phy_de +@@ -282,6 +307,51 @@ static int aqr_config_aneg(struct phy_de return genphy_c45_check_and_restart_aneg(phydev, changed); } @@ -109,7 +106,7 @@ Signed-off-by: Alex Marginean static int aqr_config_intr(struct phy_device *phydev) { bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; -@@ -825,6 +895,30 @@ static struct phy_driver aqr_driver[] = +@@ -883,6 +953,30 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, .link_change_notify = aqr107_link_change_notify, }, @@ -140,15 +137,12 @@ Signed-off-by: Alex Marginean }; module_phy_driver(aqr_driver); -@@ -835,9 +929,11 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, +@@ -897,6 +991,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, -+ { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, { } }; + diff --git a/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch b/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch index 7d16c8aa28..8e204cb146 100644 --- a/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch +++ b/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch @@ -14,7 +14,7 @@ Signed-off-by: Alex Marginean --- a/drivers/net/phy/aquantia_main.c +++ b/drivers/net/phy/aquantia_main.c -@@ -324,10 +324,16 @@ static int aqr_config_aneg_set_prot(stru +@@ -340,10 +340,16 @@ static int aqr_config_aneg_set_prot(stru phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, aquantia_syscfg[if_type].start_rate); diff --git a/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch index d03c3430fa..f30e65101a 100644 --- a/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch +++ b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch @@ -10,15 +10,15 @@ Add a new entry for AQR113 PHY_ID --- a/drivers/net/phy/aquantia_main.c +++ b/drivers/net/phy/aquantia_main.c -@@ -21,6 +21,7 @@ - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 +@@ -26,6 +26,7 @@ + #define PHY_ID_AQR813 0x31c31cb2 #define PHY_ID_AQR112 0x03a1b662 + #define PHY_ID_AQR412 0x03a1b712 +#define PHY_ID_AQR113 0x31c31c40 - #define PHY_ID_AQR113C 0x31c31c12 - #define PHY_ID_AQCS109 0x03a1b5c2 - #define PHY_ID_AQR405 0x03a1b4b0 -@@ -914,6 +915,14 @@ static struct phy_driver aqr_driver[] = + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -972,6 +973,14 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, }, { @@ -33,11 +33,11 @@ Add a new entry for AQR113 PHY_ID PHY_ID_MATCH_MODEL(PHY_ID_AQR412), .name = "Aquantia AQR412", .probe = aqr107_probe, -@@ -936,6 +945,7 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, +@@ -999,6 +1008,7 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, + { } + }; + diff --git a/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch index 9821c0c86e..ab674409d6 100644 --- a/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch +++ b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch @@ -12,16 +12,16 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/aquantia_main.c +++ b/drivers/net/phy/aquantia_main.c -@@ -21,6 +21,8 @@ - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 +@@ -27,6 +27,8 @@ #define PHY_ID_AQR112 0x03a1b662 + #define PHY_ID_AQR412 0x03a1b712 + #define PHY_ID_AQR113 0x31c31c40 +#define PHY_ID_AQR112C 0x03a1b790 +#define PHY_ID_AQR112R 0x31c31d12 - #define PHY_ID_AQR113 0x31c31c40 - #define PHY_ID_AQR113C 0x31c31c12 - #define PHY_ID_AQCS109 0x03a1b5c2 -@@ -915,6 +917,30 @@ static struct phy_driver aqr_driver[] = + + #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 + #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +@@ -973,6 +975,30 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, }, { @@ -52,12 +52,12 @@ Signed-off-by: Daniel Golle PHY_ID_MATCH_MODEL(PHY_ID_AQR113), .name = "Aquantia AQR113", .config_aneg = aqr_config_aneg, -@@ -945,6 +971,8 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, +@@ -1009,6 +1035,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR112R) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { } + }; + diff --git a/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch b/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch index e14a5f1747..ef274237c2 100644 --- a/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch +++ b/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch @@ -12,16 +12,16 @@ to set max speed to 5G. Signed-off-by: Thomas Kupper --- a/drivers/net/phy/aquantia_main.c +++ b/drivers/net/phy/aquantia_main.c -@@ -20,6 +20,8 @@ - #define PHY_ID_AQR105 0x03a1b4a2 - #define PHY_ID_AQR106 0x03a1b4d0 - #define PHY_ID_AQR107 0x03a1b4e0 +@@ -24,6 +24,8 @@ + #define PHY_ID_AQR405 0x03a1b4b0 + #define PHY_ID_AQR113C 0x31c31c12 + #define PHY_ID_AQR813 0x31c31cb2 +#define PHY_ID_AQR111 0x03a1b610 +#define PHY_ID_AQR111B0 0x03a1b612 #define PHY_ID_AQR112 0x03a1b662 - #define PHY_ID_AQR112C 0x03a1b790 - #define PHY_ID_AQR112R 0x31c31d12 -@@ -686,6 +688,33 @@ static int aqcs109_config_init(struct ph + #define PHY_ID_AQR412 0x03a1b712 + #define PHY_ID_AQR113 0x31c31c40 +@@ -731,6 +733,33 @@ static int aqcs109_config_init(struct ph return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); } @@ -55,7 +55,7 @@ Signed-off-by: Thomas Kupper static void aqr107_link_change_notify(struct phy_device *phydev) { u8 fw_major, fw_minor; -@@ -905,6 +934,42 @@ static struct phy_driver aqr_driver[] = +@@ -963,6 +992,42 @@ static struct phy_driver aqr_driver[] = .link_change_notify = aqr107_link_change_notify, }, { @@ -98,12 +98,12 @@ Signed-off-by: Thomas Kupper PHY_ID_MATCH_MODEL(PHY_ID_AQR112), .name = "Aquantia AQR112", .probe = aqr107_probe, -@@ -970,6 +1035,8 @@ static struct mdio_device_id __maybe_unu - { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, +@@ -1032,6 +1097,8 @@ static struct mdio_device_id __maybe_unu + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR112C) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR112R) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, From a1364fcd091c28d63bfe1d4947f2e21cc11c2b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Fri, 26 Jan 2024 09:52:35 +0100 Subject: [PATCH 209/222] bcm27xx: switch to bcm27xx-utils MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bcm27xx-userland is now deprecated and utils should be used instead. https://github.com/raspberrypi/userland/commit/96a7334ae9d5fc9db7ac92e59852377df63f1848 Signed-off-by: Álvaro Fernández Rojas --- package/utils/bcm27xx-userland/Makefile | 1 - target/linux/bcm27xx/Makefile | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package/utils/bcm27xx-userland/Makefile b/package/utils/bcm27xx-userland/Makefile index 402c3dcd64..461cf3e954 100644 --- a/package/utils/bcm27xx-userland/Makefile +++ b/package/utils/bcm27xx-userland/Makefile @@ -41,7 +41,6 @@ define Package/bcm27xx-userland CATEGORY:=Utilities DEPENDS:=@TARGET_bcm27xx TITLE:=BCM27xx userland tools - DEFAULT:=y if TARGET_bcm27xx endef define Package/bcm27xx-userland/description diff --git a/target/linux/bcm27xx/Makefile b/target/linux/bcm27xx/Makefile index 702a59ecb8..d7b56b23bc 100644 --- a/target/linux/bcm27xx/Makefile +++ b/target/linux/bcm27xx/Makefile @@ -22,7 +22,7 @@ include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES := $(filter-out urngd,$(DEFAULT_PACKAGES)) DEFAULT_PACKAGES += \ - bcm27xx-gpu-fw \ + bcm27xx-gpu-fw bcm27xx-utils \ kmod-usb-hid \ kmod-sound-core kmod-sound-arm-bcm2835 \ kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 \ From e617fa33b574528f5af6983a655d6df054d0345c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 26 Jan 2024 13:13:56 +0100 Subject: [PATCH 210/222] mac80211: fix typo in getting path from board.json Use json_get_vars in order to avoid getting bogus values when extra properties are present Signed-off-by: Felix Fietkau --- package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index ed52822568..49ffb219bc 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -559,7 +559,7 @@ get_board_phy_name() ( local ref_path="$3" json_select "$key" - json_get_values path + json_get_vars path json_select .. [ "${ref_path%+*}" = "$path" ] && fallback_phy=$key @@ -591,7 +591,7 @@ rename_board_phy_by_name() ( json_load_file /etc/board.json json_select wlan json_select "${phy%.*}" || return 0 - json_get_values path + json_get_vars path prev_phy="$(iwinfo nl80211 phyname "path=$path${suffix:++$suffix}")" [ -n "$prev_phy" ] || return 0 From 137694eaffaeba94f0524fe3f9a5148f54d3cb8a Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 19 Nov 2023 16:37:07 +0100 Subject: [PATCH 211/222] qualcommax: 301w: populate AQR firmware name Now that we have support for firmware loading via the kernel driver, it makes sense to populate the firmware name as well, so if its present the driver can load it. In later patches, loading the FW via NVMEM will be added as well. Signed-off-by: Robert Marko --- .../qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts index a7d398ee0f..8ce22c1c06 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts @@ -276,12 +276,14 @@ compatible ="ethernet-phy-ieee802.3-c45"; reg = <0>; reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + firmware-name = "marvell/AQR-G4_v5.4.C-AQR_CIG_WF-1945_0x0_ID44778_VER1630.cld"; }; aqr113c_8: ethernet-phy@8 { compatible ="ethernet-phy-ieee802.3-c45"; reg = <8>; reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + firmware-name = "marvell/AQR-G4_v5.4.C-AQR_CIG_WF-1945_0x8_ID44776_VER1630.cld"; }; qca8075_16: ethernet-phy@16 { From 845caa8d4688bf0901f3998fdc6ed3a75d2ce2d7 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 29 Nov 2023 19:24:18 +0100 Subject: [PATCH 212/222] qualcommax: 301w: correct AQR reset GPIO-s It seems that the reset GPIO-s defined for the two AQR PHY-s are actually reversed. Manually testing confirmed that GPIO44 is actually reset GPIO of AQR at 0, while GPIO59 is reset of AQR at 8: root@OpenWrt:~# mdio 9* DEV PHY-ID LINK 0x00 0x00000000 down 0x08 0x00000000 down 0x10 0x004dd0b1 down 0x11 0x004dd0b1 down 0x12 0x004dd0b1 down 0x13 0x004dd0b1 up 0x14 0x004dd0b1 down 0x15 0x04820a05 down root@OpenWrt:~# gpioset gpiochip0 44=0 root@OpenWrt:~# mdio 9* DEV PHY-ID LINK 0x08 0x00000000 down 0x10 0x004dd0b1 down 0x11 0x004dd0b1 down 0x12 0x004dd0b1 down 0x13 0x004dd0b1 up 0x14 0x004dd0b1 down 0x15 0x04820a05 down root@OpenWrt:~# gpioset gpiochip0 44=1 root@OpenWrt:~# mdio 9* DEV PHY-ID LINK 0x00 0x00000000 down 0x08 0x00000000 down 0x10 0x004dd0b1 down 0x11 0x004dd0b1 down 0x12 0x004dd0b1 down 0x13 0x004dd0b1 up 0x14 0x004dd0b1 down 0x15 0x04820a05 down root@OpenWrt:~# gpioset gpiochip0 59=0 root@OpenWrt:~# mdio 9* DEV PHY-ID LINK 0x00 0x00000000 down 0x10 0x004dd0b1 down 0x11 0x004dd0b1 down 0x12 0x004dd0b1 down 0x13 0x004dd0b1 up 0x14 0x004dd0b1 down 0x15 0x04820a05 down root@OpenWrt:~# gpioset gpiochip0 59=1 root@OpenWrt:~# mdio 9* DEV PHY-ID LINK 0x00 0x00000000 down 0x08 0x00000000 down 0x10 0x004dd0b1 down 0x11 0x004dd0b1 down 0x12 0x004dd0b1 down 0x13 0x004dd0b1 up 0x14 0x004dd0b1 down 0x15 0x04820a05 down Signed-off-by: Robert Marko --- .../files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts index 8ce22c1c06..8b392c0fba 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts @@ -275,14 +275,14 @@ aqr113c_0: ethernet-phy@0 { compatible ="ethernet-phy-ieee802.3-c45"; reg = <0>; - reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; firmware-name = "marvell/AQR-G4_v5.4.C-AQR_CIG_WF-1945_0x0_ID44778_VER1630.cld"; }; aqr113c_8: ethernet-phy@8 { compatible ="ethernet-phy-ieee802.3-c45"; reg = <8>; - reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; + reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; firmware-name = "marvell/AQR-G4_v5.4.C-AQR_CIG_WF-1945_0x8_ID44776_VER1630.cld"; }; From 652d72260d816fe493e9453c472ce5c0c85240f3 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 25 Jan 2024 22:19:58 +0100 Subject: [PATCH 213/222] qualcommax: 301w: provide AQR FW via NVMEM cells In order to get rid of having to modify U-boot bootcmd and having U-boot load the Aquantia PHY-s firmware lets use some of the free space on SPI-NOR to add a second ethphyfw partition and be able to load AQR FW via NVMEM cells. Signed-off-by: Robert Marko --- .../arch/arm64/boot/dts/qcom/ipq8072-301w.dts | 98 ++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts index 8b392c0fba..572812ec39 100644 --- a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8072-301w.dts @@ -260,7 +260,99 @@ spi-max-frequency = <50000000>; partitions { - compatible = "qcom,smem-part"; + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "0:sbl1"; + reg = <0x0 0x50000>; + read-only; + }; + + partition@50000 { + label = "0:mibib"; + reg = <0x50000 0x10000>; + read-only; + }; + + partition@60000 { + label = "0:qsee"; + reg = <0x60000 0x180000>; + read-only; + }; + + partition@1e0000 { + label = "0:devcfg"; + reg = <0x1e0000 0x10000>; + read-only; + }; + + partition@1f0000 { + label = "0:apdp"; + reg = <0x1f0000 0x10000>; + read-only; + }; + + partition@200000 { + label = "0:rpm"; + reg = <0x200000 0x40000>; + read-only; + }; + + partition@240000 { + label = "0:cdt"; + reg = <0x240000 0x10000>; + read-only; + }; + + partition@250000 { + label = "0:appsblenv"; + reg = <0x250000 0x20000>; + }; + + partition@270000 { + label = "0:appsbl"; + reg = <0x250000 0x100000>; + read-only; + }; + + partition@370000 { + label = "0:art"; + reg = <0x370000 0x40000>; + read-only; + }; + + partition@3b0000 { + label = "0:ethphyfw1"; + reg = <0x3b0000 0x80000>; + + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + aqr0_fw: firmware@0 { + reg = <0x0 0x5fc02>; + }; + }; + + partition@430000 { + label = "0:ethphyfw2"; + reg = <0x430000 0x80000>; + + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + aqr1_fw: firmware@0 { + reg = <0x0 0x5fc02>; + }; + }; + + partition@4b0000 { + label = "reserved"; + reg = <0x4b0000 0x350000>; + }; }; }; }; @@ -277,6 +369,8 @@ reg = <0>; reset-gpios = <&tlmm 44 GPIO_ACTIVE_LOW>; firmware-name = "marvell/AQR-G4_v5.4.C-AQR_CIG_WF-1945_0x0_ID44778_VER1630.cld"; + nvmem-cell-names = "firmware"; + nvmem-cells = <&aqr0_fw>; }; aqr113c_8: ethernet-phy@8 { @@ -284,6 +378,8 @@ reg = <8>; reset-gpios = <&tlmm 59 GPIO_ACTIVE_LOW>; firmware-name = "marvell/AQR-G4_v5.4.C-AQR_CIG_WF-1945_0x8_ID44776_VER1630.cld"; + nvmem-cell-names = "firmware"; + nvmem-cells = <&aqr1_fw>; }; qca8075_16: ethernet-phy@16 { From 1a392e7f2462f38255bc959821eba035b566e168 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Fri, 26 Jan 2024 15:49:12 +0100 Subject: [PATCH 214/222] layerscape: 5.15: refresh 2.5G-SGMII patch due to recent PHY backport Refresh 2.5G-SGMII patch due to recent PHY backport that cause compilation warning for case not handled in phy_interface_num_ports. Signed-off-by: Christian Marangi --- .../702-phy-Add-2.5G-SGMII-interface-mode.patch | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch index daf6cf3ce7..f1ce7cc0ad 100644 --- a/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch +++ b/target/linux/layerscape/patches-5.15/702-phy-Add-2.5G-SGMII-interface-mode.patch @@ -11,6 +11,16 @@ Signed-off-by: Bhaskar Upadhaya include/linux/phy.h | 3 +++ 1 file changed, 3 insertions(+) +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -136,6 +136,7 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_RXAUI: + case PHY_INTERFACE_MODE_XAUI: + case PHY_INTERFACE_MODE_1000BASEKX: ++ case PHY_INTERFACE_MODE_2500SGMII: + return 1; + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -400,6 +400,7 @@ void phylink_get_linkmodes(unsigned long From 0f09fd60fb8df1b5ea86b4a9e70163511b65d99c Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Fri, 26 Jan 2024 15:50:43 +0100 Subject: [PATCH 215/222] realtek: 5.15: refresh HSGMII patch due to recent PHY backport Refresh HSGMII patch due to recent PHY backport that cause compilation warning for case not handled in phy_interface_num_ports. Signed-off-by: Christian Marangi --- .../704-include-linux-add-phy-hsgmii-mode.patch | 10 ++++++++++ ...o-support-hardware-assisted-indirect-access.patch | 12 ++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch b/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch index 4c573e2bb0..700ec97be8 100644 --- a/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch +++ b/target/linux/realtek/patches-5.15/704-include-linux-add-phy-hsgmii-mode.patch @@ -13,6 +13,16 @@ Submitted-by: Birger Koblitz include/linux/phy.h | 3 +++ 2 file changed, 5 insertions(+) +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -124,6 +124,7 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_MOCA: + case PHY_INTERFACE_MODE_TRGMII: + case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_HSGMII: + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_SMII: + case PHY_INTERFACE_MODE_1000BASEX: --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -410,6 +410,7 @@ void phylink_get_linkmodes(unsigned long diff --git a/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch b/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch index 937e5d3161..188d68b121 100644 --- a/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch +++ b/target/linux/realtek/patches-5.15/800-net-mdio-support-hardware-assisted-indirect-access.patch @@ -443,7 +443,7 @@ Signed-off-by: Daniel Golle * @dev: target MDIO device --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c -@@ -556,10 +556,16 @@ int __phy_read_mmd(struct phy_device *ph +@@ -557,10 +557,16 @@ int __phy_read_mmd(struct phy_device *ph struct mii_bus *bus = phydev->mdio.bus; int phy_addr = phydev->mdio.addr; @@ -464,7 +464,7 @@ Signed-off-by: Daniel Golle } return val; } -@@ -612,12 +618,18 @@ int __phy_write_mmd(struct phy_device *p +@@ -613,12 +619,18 @@ int __phy_write_mmd(struct phy_device *p struct mii_bus *bus = phydev->mdio.bus; int phy_addr = phydev->mdio.addr; @@ -487,7 +487,7 @@ Signed-off-by: Daniel Golle } return ret; } -@@ -823,6 +835,13 @@ EXPORT_SYMBOL_GPL(phy_modify_mmd); +@@ -824,6 +836,13 @@ EXPORT_SYMBOL_GPL(phy_modify_mmd); static int __phy_read_page(struct phy_device *phydev) { @@ -501,7 +501,7 @@ Signed-off-by: Daniel Golle if (WARN_ONCE(!phydev->drv->read_page, "read_page callback not available, PHY driver not loaded?\n")) return -EOPNOTSUPP; -@@ -831,6 +850,13 @@ static int __phy_read_page(struct phy_de +@@ -832,6 +851,13 @@ static int __phy_read_page(struct phy_de static int __phy_write_page(struct phy_device *phydev, int page) { @@ -515,7 +515,7 @@ Signed-off-by: Daniel Golle if (WARN_ONCE(!phydev->drv->write_page, "write_page callback not available, PHY driver not loaded?\n")) return -EOPNOTSUPP; -@@ -932,6 +958,18 @@ int phy_read_paged(struct phy_device *ph +@@ -933,6 +959,18 @@ int phy_read_paged(struct phy_device *ph { int ret = 0, oldpage; @@ -534,7 +534,7 @@ Signed-off-by: Daniel Golle oldpage = phy_select_page(phydev, page); if (oldpage >= 0) ret = __phy_read(phydev, regnum); -@@ -953,6 +991,18 @@ int phy_write_paged(struct phy_device *p +@@ -954,6 +992,18 @@ int phy_write_paged(struct phy_device *p { int ret = 0, oldpage; From 4fb04e35c9382d9b8f43f6c42530af5b946fd922 Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Sat, 25 Nov 2023 23:47:08 +0100 Subject: [PATCH 216/222] ipq806x: drop swconfig leftovers They are unnecessary since ipq806x switched to DSA in the commit 337e36e0ef988d850105cfa5f7588e36d90aef2b. Signed-off-by: Aleksander Jan Bajkowski Reviewed-by: Robert Marko --- target/linux/ipq806x/image/generic.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index 824a95b157..98e74e5b11 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -240,7 +240,7 @@ define Device/meraki_mr42 BLOCKSIZE := 128k PAGESIZE := 2048 KERNEL_LOADADDR = 0x44208000 - DEVICE_PACKAGES := -swconfig -kmod-ata-ahci -kmod-ata-ahci-platform \ + DEVICE_PACKAGES := -kmod-ata-ahci -kmod-ata-ahci-platform \ -kmod-usb-ohci -kmod-usb2 -kmod-usb-ledtrig-usbport \ -kmod-phy-qcom-ipq806x-usb -kmod-usb3 -kmod-usb-dwc3-qcom \ -uboot-envtools ath10k-firmware-qca9887-ct \ @@ -258,7 +258,7 @@ define Device/meraki_mr52 PAGESIZE := 2048 KERNEL_LOADADDR = 0x44208000 DEVICE_DTS_CONFIG := config@2 - DEVICE_PACKAGES := -swconfig -kmod-ata-ahci -kmod-ata-ahci-platform \ + DEVICE_PACKAGES := -kmod-ata-ahci -kmod-ata-ahci-platform \ -kmod-usb-ohci -kmod-usb2 -kmod-usb-ledtrig-usbport \ -kmod-phy-qcom-ipq806x-usb -kmod-usb3 -kmod-usb-dwc3-qcom \ -uboot-envtools ath10k-firmware-qca9887-ct \ From 0fd3a6c6c6f079565f1f5de4709f3d4d71fc54c8 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Fri, 26 Jan 2024 16:14:20 +0100 Subject: [PATCH 217/222] CI: formal: use shared workflow in actions-shared-workflows Use shared workflow in actions-shared-workflows instead of keeping the workflow in openwrt main branch to make it easier to maintain and update without bloating the main repository commit history. Signed-off-by: Christian Marangi --- .github/workflows/formal.yml | 55 +----------------------------------- 1 file changed, 1 insertion(+), 54 deletions(-) diff --git a/.github/workflows/formal.yml b/.github/workflows/formal.yml index 1532591dfc..081129d6f0 100644 --- a/.github/workflows/formal.yml +++ b/.github/workflows/formal.yml @@ -9,57 +9,4 @@ permissions: jobs: build: name: Test Formalities - runs-on: ubuntu-latest - strategy: - fail-fast: false - - steps: - - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - - name: Determine branch name - run: | - BRANCH="${GITHUB_BASE_REF#refs/heads/}" - echo "Building for $BRANCH" - echo "BRANCH=$BRANCH" >> $GITHUB_ENV - - - name: Test formalities - run: | - source .github/workflows/scripts/ci_helpers.sh - - RET=0 - for commit in $(git rev-list HEAD ^origin/$BRANCH); do - info "=== Checking commit '$commit'" - if git show --format='%P' -s $commit | grep -qF ' '; then - err "Pull request should not include merge commits" - RET=1 - fi - - subject="$(git show -s --format=%s $commit)" - if echo "$subject" | grep -q -e '^[0-9A-Za-z,+/_\.-]\+: ' -e '^Revert '; then - success "Commit subject line seems ok ($subject)" - else - err "Commit subject line MUST start with ': ' ($subject)" - RET=1 - fi - - body="$(git show -s --format=%b $commit)" - sob="$(git show -s --format='Signed-off-by: %aN <%aE>' $commit)" - if echo "$body" | grep -qF "$sob"; then - success "Signed-off-by match author" - else - err "Signed-off-by is missing or doesn't match author (should be '$sob')" - RET=1 - fi - - if echo "$body" | grep -v "Signed-off-by:"; then - success "A commit message exists" - else - err "Missing commit message. Please describe your changes" - RET=1 - fi - done - - exit $RET + uses: openwrt/actions-shared-workflows/.github/workflows/formal.yml@main From 1b3259eb5cdcfecbfae7809b8a9febdbe22ac65f Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 19 Nov 2023 12:52:55 +0100 Subject: [PATCH 218/222] generic: 5.15: backport upstream Aquantia PHY firmware loader patches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backport merged upstream patch that adds support for firmware loader from NVMEM or attached filesystem for Aquantia PHYs. Refresh all kernel patches affected by this change. Also update the path for aquantia .ko that got moved to dedicated directory upstream. Signed-off-by: Christian Marangi [rmilecki: port to 5.15] Signed-off-by: Rafał Miłecki --- package/kernel/linux/modules/netdevices.mk | 4 +- ...-aquantia-move-to-separate-directory.patch | 2310 +++++++++++++++++ ...antia-move-MMD_VEND-define-to-header.patch | 183 ++ ...y-aquantia-add-firmware-load-support.patch | 504 ++++ ...or-Motorcomm-yt8521-gigabit-ethernet.patch | 2 +- ...net-phy-add-Motorcomm-YT8531S-phy-id.patch | 2 +- ...or-Motorcomm-yt8531-gigabit-ethernet.patch | 2 +- .../hack-5.15/720-net-phy-add-aqr-phys.patch | 14 +- ...hy-aquantia-enable-AQR112-and-AQR412.patch | 14 +- ...aquantia-fix-system-side-protocol-mi.patch | 8 +- ...y-aquantia-Add-AQR113-driver-support.patch | 10 +- ...ntia-add-PHY_IDs-for-AQR112-variants.patch | 10 +- ...-aquantia-enable-AQR111-and-AQR111B0.patch | 10 +- .../500-gsw-rtl8367s-mt7622-support.patch | 4 +- ...er-for-MediaTek-SoC-built-in-GE-PHYs.patch | 4 +- ...phy-add-driver-for-MediaTek-2.5G-PHY.patch | 4 +- .../patches-5.15/705-add-rtl-phy.patch | 4 +- 17 files changed, 3042 insertions(+), 47 deletions(-) create mode 100644 target/linux/generic/backport-5.15/737-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch create mode 100644 target/linux/generic/backport-5.15/737-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch create mode 100644 target/linux/generic/backport-5.15/737-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch diff --git a/package/kernel/linux/modules/netdevices.mk b/package/kernel/linux/modules/netdevices.mk index 46dcdfdef7..63f75e9591 100644 --- a/package/kernel/linux/modules/netdevices.mk +++ b/package/kernel/linux/modules/netdevices.mk @@ -380,9 +380,7 @@ define KernelPackage/phy-aquantia TITLE:=Aquantia Ethernet PHYs DEPENDS:=+kmod-libphy +kmod-hwmon-core +kmod-lib-crc-ccitt KCONFIG:=CONFIG_AQUANTIA_PHY - FILES:= \ - $(LINUX_DIR)/drivers/net/phy/aquantia.ko@lt6.1 \ - $(LINUX_DIR)/drivers/net/phy/aquantia/aquantia.ko@ge6.1 + FILES:=$(LINUX_DIR)/drivers/net/phy/aquantia/aquantia.ko AUTOLOAD:=$(call AutoLoad,18,aquantia,1) endef diff --git a/target/linux/generic/backport-5.15/737-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch b/target/linux/generic/backport-5.15/737-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch new file mode 100644 index 0000000000..4bb786e790 --- /dev/null +++ b/target/linux/generic/backport-5.15/737-01-v6.7-net-phy-aquantia-move-to-separate-directory.patch @@ -0,0 +1,2310 @@ +From d2213db3f49bce8e7a87c8de05b9a091f78f654e Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Nov 2023 15:08:41 +0100 +Subject: [PATCH 1/3] net: phy: aquantia: move to separate directory + +Move aquantia PHY driver to separate driectory in preparation for +firmware loading support to keep things tidy. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/Kconfig | 5 +---- + drivers/net/phy/Makefile | 6 +----- + drivers/net/phy/aquantia/Kconfig | 5 +++++ + drivers/net/phy/aquantia/Makefile | 6 ++++++ + drivers/net/phy/{ => aquantia}/aquantia.h | 0 + drivers/net/phy/{ => aquantia}/aquantia_hwmon.c | 0 + drivers/net/phy/{ => aquantia}/aquantia_main.c | 0 + 7 files changed, 13 insertions(+), 9 deletions(-) + create mode 100644 drivers/net/phy/aquantia/Kconfig + create mode 100644 drivers/net/phy/aquantia/Makefile + rename drivers/net/phy/{ => aquantia}/aquantia.h (100%) + rename drivers/net/phy/{ => aquantia}/aquantia_hwmon.c (100%) + rename drivers/net/phy/{ => aquantia}/aquantia_main.c (100%) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -83,10 +83,7 @@ config ADIN_PHY + - ADIN1300 - Robust,Industrial, Low Latency 10/100/1000 Gigabit + Ethernet PHY + +-config AQUANTIA_PHY +- tristate "Aquantia PHYs" +- help +- Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 ++source "drivers/net/phy/aquantia/Kconfig" + + config AX88796B_PHY + tristate "Asix PHYs" +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -32,11 +32,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) + + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_AMD_PHY) += amd.o +-aquantia-objs += aquantia_main.o +-ifdef CONFIG_HWMON +-aquantia-objs += aquantia_hwmon.o +-endif +-obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o ++obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ + obj-$(CONFIG_AT803X_PHY) += at803x.o + obj-$(CONFIG_AX88796B_PHY) += ax88796b.o + obj-$(CONFIG_BCM54140_PHY) += bcm54140.o +--- /dev/null ++++ b/drivers/net/phy/aquantia/Kconfig +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config AQUANTIA_PHY ++ tristate "Aquantia PHYs" ++ help ++ Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 +--- /dev/null ++++ b/drivers/net/phy/aquantia/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0 ++aquantia-objs += aquantia_main.o ++ifdef CONFIG_HWMON ++aquantia-objs += aquantia_hwmon.o ++endif ++obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o +--- a/drivers/net/phy/aquantia.h ++++ /dev/null +@@ -1,16 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-/* HWMON driver for Aquantia PHY +- * +- * Author: Nikita Yushchenko +- * Author: Andrew Lunn +- * Author: Heiner Kallweit +- */ +- +-#include +-#include +- +-#if IS_REACHABLE(CONFIG_HWMON) +-int aqr_hwmon_probe(struct phy_device *phydev); +-#else +-static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } +-#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -0,0 +1,16 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* HWMON driver for Aquantia PHY ++ * ++ * Author: Nikita Yushchenko ++ * Author: Andrew Lunn ++ * Author: Heiner Kallweit ++ */ ++ ++#include ++#include ++ ++#if IS_REACHABLE(CONFIG_HWMON) ++int aqr_hwmon_probe(struct phy_device *phydev); ++#else ++static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } ++#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_hwmon.c +@@ -0,0 +1,250 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* HWMON driver for Aquantia PHY ++ * ++ * Author: Nikita Yushchenko ++ * Author: Andrew Lunn ++ * Author: Heiner Kallweit ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "aquantia.h" ++ ++/* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 ++#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 ++#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 ++#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 ++#define VEND1_THERMAL_STAT1 0xc820 ++#define VEND1_THERMAL_STAT2 0xc821 ++#define VEND1_THERMAL_STAT2_VALID BIT(0) ++#define VEND1_GENERAL_STAT1 0xc830 ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) ++ ++#if IS_REACHABLE(CONFIG_HWMON) ++ ++static umode_t aqr_hwmon_is_visible(const void *data, ++ enum hwmon_sensor_types type, ++ u32 attr, int channel) ++{ ++ if (type != hwmon_temp) ++ return 0; ++ ++ switch (attr) { ++ case hwmon_temp_input: ++ case hwmon_temp_min_alarm: ++ case hwmon_temp_max_alarm: ++ case hwmon_temp_lcrit_alarm: ++ case hwmon_temp_crit_alarm: ++ return 0444; ++ case hwmon_temp_min: ++ case hwmon_temp_max: ++ case hwmon_temp_lcrit: ++ case hwmon_temp_crit: ++ return 0644; ++ default: ++ return 0; ++ } ++} ++ ++static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value) ++{ ++ int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); ++ ++ if (temp < 0) ++ return temp; ++ ++ /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */ ++ *value = (s16)temp * 1000 / 256; ++ ++ return 0; ++} ++ ++static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value) ++{ ++ int temp; ++ ++ if (value >= 128000 || value < -128000) ++ return -ERANGE; ++ ++ temp = value * 256 / 1000; ++ ++ /* temp is in s16 range and we're interested in lower 16 bits only */ ++ return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp); ++} ++ ++static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit) ++{ ++ int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); ++ ++ if (val < 0) ++ return val; ++ ++ return !!(val & bit); ++} ++ ++static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value) ++{ ++ int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit); ++ ++ if (val < 0) ++ return val; ++ ++ *value = val; ++ ++ return 0; ++} ++ ++static int aqr_hwmon_read(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long *value) ++{ ++ struct phy_device *phydev = dev_get_drvdata(dev); ++ int reg; ++ ++ if (type != hwmon_temp) ++ return -EOPNOTSUPP; ++ ++ switch (attr) { ++ case hwmon_temp_input: ++ reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2, ++ VEND1_THERMAL_STAT2_VALID); ++ if (reg < 0) ++ return reg; ++ if (!reg) ++ return -EBUSY; ++ ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value); ++ ++ case hwmon_temp_lcrit: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit: ++ return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, ++ value); ++ case hwmon_temp_lcrit_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit_alarm: ++ return aqr_hwmon_status1(phydev, ++ VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL, ++ value); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long value) ++{ ++ struct phy_device *phydev = dev_get_drvdata(dev); ++ ++ if (type != hwmon_temp) ++ return -EOPNOTSUPP; ++ ++ switch (attr) { ++ case hwmon_temp_lcrit: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, ++ value); ++ case hwmon_temp_min: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, ++ value); ++ case hwmon_temp_max: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, ++ value); ++ case hwmon_temp_crit: ++ return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, ++ value); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static const struct hwmon_ops aqr_hwmon_ops = { ++ .is_visible = aqr_hwmon_is_visible, ++ .read = aqr_hwmon_read, ++ .write = aqr_hwmon_write, ++}; ++ ++static u32 aqr_hwmon_chip_config[] = { ++ HWMON_C_REGISTER_TZ, ++ 0, ++}; ++ ++static const struct hwmon_channel_info aqr_hwmon_chip = { ++ .type = hwmon_chip, ++ .config = aqr_hwmon_chip_config, ++}; ++ ++static u32 aqr_hwmon_temp_config[] = { ++ HWMON_T_INPUT | ++ HWMON_T_MAX | HWMON_T_MIN | ++ HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM | ++ HWMON_T_CRIT | HWMON_T_LCRIT | ++ HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM, ++ 0, ++}; ++ ++static const struct hwmon_channel_info aqr_hwmon_temp = { ++ .type = hwmon_temp, ++ .config = aqr_hwmon_temp_config, ++}; ++ ++static const struct hwmon_channel_info *aqr_hwmon_info[] = { ++ &aqr_hwmon_chip, ++ &aqr_hwmon_temp, ++ NULL, ++}; ++ ++static const struct hwmon_chip_info aqr_hwmon_chip_info = { ++ .ops = &aqr_hwmon_ops, ++ .info = aqr_hwmon_info, ++}; ++ ++int aqr_hwmon_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct device *hwmon_dev; ++ char *hwmon_name; ++ int i, j; ++ ++ hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); ++ if (!hwmon_name) ++ return -ENOMEM; ++ ++ for (i = j = 0; hwmon_name[i]; i++) { ++ if (isalnum(hwmon_name[i])) { ++ if (i != j) ++ hwmon_name[j] = hwmon_name[i]; ++ j++; ++ } ++ } ++ hwmon_name[j] = '\0'; ++ ++ hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name, ++ phydev, &aqr_hwmon_chip_info, NULL); ++ ++ return PTR_ERR_OR_ZERO(hwmon_dev); ++} ++ ++#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -0,0 +1,844 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Driver for Aquantia PHY ++ * ++ * Author: Shaohui Xie ++ * ++ * Copyright 2015 Freescale Semiconductor, Inc. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aquantia.h" ++ ++#define PHY_ID_AQ1202 0x03a1b445 ++#define PHY_ID_AQ2104 0x03a1b460 ++#define PHY_ID_AQR105 0x03a1b4a2 ++#define PHY_ID_AQR106 0x03a1b4d0 ++#define PHY_ID_AQR107 0x03a1b4e0 ++#define PHY_ID_AQCS109 0x03a1b5c2 ++#define PHY_ID_AQR405 0x03a1b4b0 ++#define PHY_ID_AQR113C 0x31c31c12 ++ ++#define MDIO_PHYXS_VEND_IF_STATUS 0xe812 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX 1 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII 3 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7 ++#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10 ++ ++#define MDIO_AN_VEND_PROV 0xc400 ++#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) ++#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) ++#define MDIO_AN_VEND_PROV_5000BASET_FULL BIT(11) ++#define MDIO_AN_VEND_PROV_2500BASET_FULL BIT(10) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_EN BIT(4) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK GENMASK(3, 0) ++#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT 4 ++ ++#define MDIO_AN_TX_VEND_STATUS1 0xc800 ++#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK GENMASK(3, 1) ++#define MDIO_AN_TX_VEND_STATUS1_10BASET 0 ++#define MDIO_AN_TX_VEND_STATUS1_100BASETX 1 ++#define MDIO_AN_TX_VEND_STATUS1_1000BASET 2 ++#define MDIO_AN_TX_VEND_STATUS1_10GBASET 3 ++#define MDIO_AN_TX_VEND_STATUS1_2500BASET 4 ++#define MDIO_AN_TX_VEND_STATUS1_5000BASET 5 ++#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0) ++ ++#define MDIO_AN_TX_VEND_INT_STATUS1 0xcc00 ++#define MDIO_AN_TX_VEND_INT_STATUS1_DOWNSHIFT BIT(1) ++ ++#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01 ++#define MDIO_AN_TX_VEND_INT_STATUS2_MASK BIT(0) ++ ++#define MDIO_AN_TX_VEND_INT_MASK2 0xd401 ++#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) ++ ++#define MDIO_AN_RX_LP_STAT1 0xe820 ++#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) ++#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) ++#define MDIO_AN_RX_LP_STAT1_SHORT_REACH BIT(13) ++#define MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT BIT(12) ++#define MDIO_AN_RX_LP_STAT1_AQ_PHY BIT(2) ++ ++#define MDIO_AN_RX_LP_STAT4 0xe823 ++#define MDIO_AN_RX_LP_STAT4_FW_MAJOR GENMASK(15, 8) ++#define MDIO_AN_RX_LP_STAT4_FW_MINOR GENMASK(7, 0) ++ ++#define MDIO_AN_RX_VEND_STAT3 0xe832 ++#define MDIO_AN_RX_VEND_STAT3_AFR BIT(0) ++ ++/* MDIO_MMD_C22EXT */ ++#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292 ++#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294 ++#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297 ++#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313 ++#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315 ++#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317 ++#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318 ++#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319 ++#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a ++#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b ++ ++/* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_FW_ID 0x0020 ++#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) ++#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) ++ ++#define VEND1_GLOBAL_GEN_STAT2 0xc831 ++#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) ++ ++/* The following registers all have similar layouts; first the registers... */ ++#define VEND1_GLOBAL_CFG_10M 0x0310 ++#define VEND1_GLOBAL_CFG_100M 0x031b ++#define VEND1_GLOBAL_CFG_1G 0x031c ++#define VEND1_GLOBAL_CFG_2_5G 0x031d ++#define VEND1_GLOBAL_CFG_5G 0x031e ++#define VEND1_GLOBAL_CFG_10G 0x031f ++/* ...and now the fields */ ++#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 ++ ++#define VEND1_GLOBAL_RSVD_STAT1 0xc885 ++#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) ++#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) ++ ++#define VEND1_GLOBAL_RSVD_STAT9 0xc88d ++#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) ++#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 ++ ++#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 ++#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 ++ ++#define VEND1_GLOBAL_INT_STD_MASK 0xff00 ++#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) ++#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) ++#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) ++#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) ++#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) ++#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) ++ ++#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 ++#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) ++#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) ++#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) ++#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) ++#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) ++ ++/* Sleep and timeout for checking if the Processor-Intensive ++ * MDIO operation is finished ++ */ ++#define AQR107_OP_IN_PROG_SLEEP 1000 ++#define AQR107_OP_IN_PROG_TIMEOUT 100000 ++ ++struct aqr107_hw_stat { ++ const char *name; ++ int reg; ++ int size; ++}; ++ ++#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s } ++static const struct aqr107_hw_stat aqr107_hw_stats[] = { ++ SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26), ++ SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26), ++ SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8), ++ SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26), ++ SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26), ++ SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8), ++ SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8), ++ SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8), ++ SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16), ++ SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22), ++}; ++#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats) ++ ++struct aqr107_priv { ++ u64 sgmii_stats[AQR107_SGMII_STAT_SZ]; ++}; ++ ++static int aqr107_get_sset_count(struct phy_device *phydev) ++{ ++ return AQR107_SGMII_STAT_SZ; ++} ++ ++static void aqr107_get_strings(struct phy_device *phydev, u8 *data) ++{ ++ int i; ++ ++ for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) ++ strscpy(data + i * ETH_GSTRING_LEN, aqr107_hw_stats[i].name, ++ ETH_GSTRING_LEN); ++} ++ ++static u64 aqr107_get_stat(struct phy_device *phydev, int index) ++{ ++ const struct aqr107_hw_stat *stat = aqr107_hw_stats + index; ++ int len_l = min(stat->size, 16); ++ int len_h = stat->size - len_l; ++ u64 ret; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg); ++ if (val < 0) ++ return U64_MAX; ++ ++ ret = val & GENMASK(len_l - 1, 0); ++ if (len_h) { ++ val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg + 1); ++ if (val < 0) ++ return U64_MAX; ++ ++ ret += (val & GENMASK(len_h - 1, 0)) << 16; ++ } ++ ++ return ret; ++} ++ ++static void aqr107_get_stats(struct phy_device *phydev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ struct aqr107_priv *priv = phydev->priv; ++ u64 val; ++ int i; ++ ++ for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) { ++ val = aqr107_get_stat(phydev, i); ++ if (val == U64_MAX) ++ phydev_err(phydev, "Reading HW Statistics failed for %s\n", ++ aqr107_hw_stats[i].name); ++ else ++ priv->sgmii_stats[i] += val; ++ ++ data[i] = priv->sgmii_stats[i]; ++ } ++} ++ ++static int aqr_config_aneg(struct phy_device *phydev) ++{ ++ bool changed = false; ++ u16 reg; ++ int ret; ++ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ return genphy_c45_pma_setup_forced(phydev); ++ ++ ret = genphy_c45_an_config_aneg(phydev); ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ changed = true; ++ ++ /* Clause 45 has no standardized support for 1000BaseT, therefore ++ * use vendor registers for this mode. ++ */ ++ reg = 0; ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_1000BASET_FULL; ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_1000BASET_HALF; ++ ++ /* Handle the case when the 2.5G and 5G speeds are not advertised */ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_2500BASET_FULL; ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, ++ phydev->advertising)) ++ reg |= MDIO_AN_VEND_PROV_5000BASET_FULL; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, ++ MDIO_AN_VEND_PROV_1000BASET_HALF | ++ MDIO_AN_VEND_PROV_1000BASET_FULL | ++ MDIO_AN_VEND_PROV_2500BASET_FULL | ++ MDIO_AN_VEND_PROV_5000BASET_FULL, reg); ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ changed = true; ++ ++ return genphy_c45_check_and_restart_aneg(phydev, changed); ++} ++ ++static int aqr_config_intr(struct phy_device *phydev) ++{ ++ bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; ++ int err; ++ ++ if (en) { ++ /* Clear any pending interrupts before enabling them */ ++ err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); ++ if (err < 0) ++ return err; ++ } ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_MASK2, ++ en ? MDIO_AN_TX_VEND_INT_MASK2_LINK : 0); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_STD_MASK, ++ en ? VEND1_GLOBAL_INT_STD_MASK_ALL : 0); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_VEND_MASK, ++ en ? VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 | ++ VEND1_GLOBAL_INT_VEND_MASK_AN : 0); ++ if (err < 0) ++ return err; ++ ++ if (!en) { ++ /* Clear any pending interrupts after we have disabled them */ ++ err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static irqreturn_t aqr_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status; ++ ++ irq_status = phy_read_mmd(phydev, MDIO_MMD_AN, ++ MDIO_AN_TX_VEND_INT_STATUS2); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ if (!(irq_status & MDIO_AN_TX_VEND_INT_STATUS2_MASK)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static int aqr_read_status(struct phy_device *phydev) ++{ ++ int val; ++ ++ if (phydev->autoneg == AUTONEG_ENABLE) { ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); ++ if (val < 0) ++ return val; ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, ++ phydev->lp_advertising, ++ val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ++ phydev->lp_advertising, ++ val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF); ++ } ++ ++ return genphy_c45_read_status(phydev); ++} ++ ++static int aqr107_read_rate(struct phy_device *phydev) ++{ ++ u32 config_reg; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); ++ if (val < 0) ++ return val; ++ ++ if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ ++ switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) { ++ case MDIO_AN_TX_VEND_STATUS1_10BASET: ++ phydev->speed = SPEED_10; ++ config_reg = VEND1_GLOBAL_CFG_10M; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_100BASETX: ++ phydev->speed = SPEED_100; ++ config_reg = VEND1_GLOBAL_CFG_100M; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_1000BASET: ++ phydev->speed = SPEED_1000; ++ config_reg = VEND1_GLOBAL_CFG_1G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_2500BASET: ++ phydev->speed = SPEED_2500; ++ config_reg = VEND1_GLOBAL_CFG_2_5G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_5000BASET: ++ phydev->speed = SPEED_5000; ++ config_reg = VEND1_GLOBAL_CFG_5G; ++ break; ++ case MDIO_AN_TX_VEND_STATUS1_10GBASET: ++ phydev->speed = SPEED_10000; ++ config_reg = VEND1_GLOBAL_CFG_10G; ++ break; ++ default: ++ phydev->speed = SPEED_UNKNOWN; ++ return 0; ++ } ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg); ++ if (val < 0) ++ return val; ++ ++ if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) == ++ VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE) ++ phydev->rate_matching = RATE_MATCH_PAUSE; ++ else ++ phydev->rate_matching = RATE_MATCH_NONE; ++ ++ return 0; ++} ++ ++static int aqr107_read_status(struct phy_device *phydev) ++{ ++ int val, ret; ++ ++ ret = aqr_read_status(phydev); ++ if (ret) ++ return ret; ++ ++ if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) ++ return 0; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS); ++ if (val < 0) ++ return val; ++ ++ switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: ++ phydev->interface = PHY_INTERFACE_MODE_10GKR; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX: ++ phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: ++ phydev->interface = PHY_INTERFACE_MODE_10GBASER; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: ++ phydev->interface = PHY_INTERFACE_MODE_USXGMII; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI: ++ phydev->interface = PHY_INTERFACE_MODE_XAUI; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI: ++ phydev->interface = PHY_INTERFACE_MODE_RXAUI; ++ break; ++ case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ break; ++ default: ++ phydev->interface = PHY_INTERFACE_MODE_NA; ++ break; ++ } ++ ++ /* Read possibly downshifted rate from vendor register */ ++ return aqr107_read_rate(phydev); ++} ++ ++static int aqr107_get_downshift(struct phy_device *phydev, u8 *data) ++{ ++ int val, cnt, enable; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV); ++ if (val < 0) ++ return val; ++ ++ enable = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_EN, val); ++ cnt = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); ++ ++ *data = enable && cnt ? cnt : DOWNSHIFT_DEV_DISABLE; ++ ++ return 0; ++} ++ ++static int aqr107_set_downshift(struct phy_device *phydev, u8 cnt) ++{ ++ int val = 0; ++ ++ if (!FIELD_FIT(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt)) ++ return -E2BIG; ++ ++ if (cnt != DOWNSHIFT_DEV_DISABLE) { ++ val = MDIO_AN_VEND_PROV_DOWNSHIFT_EN; ++ val |= FIELD_PREP(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt); ++ } ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, ++ MDIO_AN_VEND_PROV_DOWNSHIFT_EN | ++ MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); ++} ++ ++static int aqr107_get_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return aqr107_get_downshift(phydev, data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int aqr107_set_tunable(struct phy_device *phydev, ++ struct ethtool_tunable *tuna, const void *data) ++{ ++ switch (tuna->id) { ++ case ETHTOOL_PHY_DOWNSHIFT: ++ return aqr107_set_downshift(phydev, *(const u8 *)data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++/* If we configure settings whilst firmware is still initializing the chip, ++ * then these settings may be overwritten. Therefore make sure chip ++ * initialization has completed. Use presence of the firmware ID as ++ * indicator for initialization having completed. ++ * The chip also provides a "reset completed" bit, but it's cleared after ++ * read. Therefore function would time out if called again. ++ */ ++static int aqr107_wait_reset_complete(struct phy_device *phydev) ++{ ++ int val; ++ ++ return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_FW_ID, val, val != 0, ++ 20000, 2000000, false); ++} ++ ++static void aqr107_chip_info(struct phy_device *phydev) ++{ ++ u8 fw_major, fw_minor, build_id, prov_id; ++ int val; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); ++ if (val < 0) ++ return; ++ ++ fw_major = FIELD_GET(VEND1_GLOBAL_FW_ID_MAJOR, val); ++ fw_minor = FIELD_GET(VEND1_GLOBAL_FW_ID_MINOR, val); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT1); ++ if (val < 0) ++ return; ++ ++ build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); ++ prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); ++ ++ phydev_dbg(phydev, "FW %u.%u, Build %u, Provisioning %u\n", ++ fw_major, fw_minor, build_id, prov_id); ++} ++ ++static int aqr107_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check that the PHY interface type is compatible */ ++ if (phydev->interface != PHY_INTERFACE_MODE_SGMII && ++ phydev->interface != PHY_INTERFACE_MODE_1000BASEKX && ++ phydev->interface != PHY_INTERFACE_MODE_2500BASEX && ++ phydev->interface != PHY_INTERFACE_MODE_XGMII && ++ phydev->interface != PHY_INTERFACE_MODE_USXGMII && ++ phydev->interface != PHY_INTERFACE_MODE_10GKR && ++ phydev->interface != PHY_INTERFACE_MODE_10GBASER && ++ phydev->interface != PHY_INTERFACE_MODE_XAUI && ++ phydev->interface != PHY_INTERFACE_MODE_RXAUI) ++ return -ENODEV; ++ ++ WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII, ++ "Your devicetree is out of date, please update it. The AQR107 family doesn't support XGMII, maybe you mean USXGMII.\n"); ++ ++ ret = aqr107_wait_reset_complete(phydev); ++ if (!ret) ++ aqr107_chip_info(phydev); ++ ++ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); ++} ++ ++static int aqcs109_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check that the PHY interface type is compatible */ ++ if (phydev->interface != PHY_INTERFACE_MODE_SGMII && ++ phydev->interface != PHY_INTERFACE_MODE_2500BASEX) ++ return -ENODEV; ++ ++ ret = aqr107_wait_reset_complete(phydev); ++ if (!ret) ++ aqr107_chip_info(phydev); ++ ++ /* AQCS109 belongs to a chip family partially supporting 10G and 5G. ++ * PMA speed ability bits are the same for all members of the family, ++ * AQCS109 however supports speeds up to 2.5G only. ++ */ ++ ret = phy_set_max_speed(phydev, SPEED_2500); ++ if (ret) ++ return ret; ++ ++ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); ++} ++ ++static void aqr107_link_change_notify(struct phy_device *phydev) ++{ ++ u8 fw_major, fw_minor; ++ bool downshift, short_reach, afr; ++ int mode, val; ++ ++ if (phydev->state != PHY_RUNNING || phydev->autoneg == AUTONEG_DISABLE) ++ return; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); ++ /* call failed or link partner is no Aquantia PHY */ ++ if (val < 0 || !(val & MDIO_AN_RX_LP_STAT1_AQ_PHY)) ++ return; ++ ++ short_reach = val & MDIO_AN_RX_LP_STAT1_SHORT_REACH; ++ downshift = val & MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT4); ++ if (val < 0) ++ return; ++ ++ fw_major = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MAJOR, val); ++ fw_minor = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MINOR, val); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_VEND_STAT3); ++ if (val < 0) ++ return; ++ ++ afr = val & MDIO_AN_RX_VEND_STAT3_AFR; ++ ++ phydev_dbg(phydev, "Link partner is Aquantia PHY, FW %u.%u%s%s%s\n", ++ fw_major, fw_minor, ++ short_reach ? ", short reach mode" : "", ++ downshift ? ", fast-retrain downshift advertised" : "", ++ afr ? ", fast reframe advertised" : ""); ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT9); ++ if (val < 0) ++ return; ++ ++ mode = FIELD_GET(VEND1_GLOBAL_RSVD_STAT9_MODE, val); ++ if (mode == VEND1_GLOBAL_RSVD_STAT9_1000BT2) ++ phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n"); ++} ++ ++static int aqr107_wait_processor_intensive_op(struct phy_device *phydev) ++{ ++ int val, err; ++ ++ /* The datasheet notes to wait at least 1ms after issuing a ++ * processor intensive operation before checking. ++ * We cannot use the 'sleep_before_read' parameter of read_poll_timeout ++ * because that just determines the maximum time slept, not the minimum. ++ */ ++ usleep_range(1000, 5000); ++ ++ err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_GEN_STAT2, val, ++ !(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG), ++ AQR107_OP_IN_PROG_SLEEP, ++ AQR107_OP_IN_PROG_TIMEOUT, false); ++ if (err) { ++ phydev_err(phydev, "timeout: processor-intensive MDIO operation\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int aqr107_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ if (iface == PHY_INTERFACE_MODE_10GBASER || ++ iface == PHY_INTERFACE_MODE_2500BASEX || ++ iface == PHY_INTERFACE_MODE_NA) ++ return RATE_MATCH_PAUSE; ++ return RATE_MATCH_NONE; ++} ++ ++static int aqr107_suspend(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, ++ MDIO_CTRL1_LPOWER); ++ if (err) ++ return err; ++ ++ return aqr107_wait_processor_intensive_op(phydev); ++} ++ ++static int aqr107_resume(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, ++ MDIO_CTRL1_LPOWER); ++ if (err) ++ return err; ++ ++ return aqr107_wait_processor_intensive_op(phydev); ++} ++ ++static int aqr107_probe(struct phy_device *phydev) ++{ ++ phydev->priv = devm_kzalloc(&phydev->mdio.dev, ++ sizeof(struct aqr107_priv), GFP_KERNEL); ++ if (!phydev->priv) ++ return -ENOMEM; ++ ++ return aqr_hwmon_probe(phydev); ++} ++ ++static struct phy_driver aqr_driver[] = { ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), ++ .name = "Aquantia AQ1202", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), ++ .name = "Aquantia AQ2104", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR105), ++ .name = "Aquantia AQR105", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR106), ++ .name = "Aquantia AQR106", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR107), ++ .name = "Aquantia AQR107", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), ++ .name = "Aquantia AQCS109", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqcs109_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR405), ++ .name = "Aquantia AQR405", ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr_read_status, ++}, ++{ ++ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), ++ .name = "Aquantia AQR113C", ++ .probe = aqr107_probe, ++ .get_rate_matching = aqr107_get_rate_matching, ++ .config_init = aqr107_config_init, ++ .config_aneg = aqr_config_aneg, ++ .config_intr = aqr_config_intr, ++ .handle_interrupt = aqr_handle_interrupt, ++ .read_status = aqr107_read_status, ++ .get_tunable = aqr107_get_tunable, ++ .set_tunable = aqr107_set_tunable, ++ .suspend = aqr107_suspend, ++ .resume = aqr107_resume, ++ .get_sset_count = aqr107_get_sset_count, ++ .get_strings = aqr107_get_strings, ++ .get_stats = aqr107_get_stats, ++ .link_change_notify = aqr107_link_change_notify, ++}, ++}; ++ ++module_phy_driver(aqr_driver); ++ ++static struct mdio_device_id __maybe_unused aqr_tbl[] = { ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, ++ { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, aqr_tbl); ++ ++MODULE_DESCRIPTION("Aquantia PHY driver"); ++MODULE_AUTHOR("Shaohui Xie "); ++MODULE_LICENSE("GPL v2"); +--- a/drivers/net/phy/aquantia_hwmon.c ++++ /dev/null +@@ -1,250 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* HWMON driver for Aquantia PHY +- * +- * Author: Nikita Yushchenko +- * Author: Andrew Lunn +- * Author: Heiner Kallweit +- */ +- +-#include +-#include +-#include +-#include +- +-#include "aquantia.h" +- +-/* Vendor specific 1, MDIO_MMD_VEND2 */ +-#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 +-#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 +-#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +-#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 +-#define VEND1_THERMAL_STAT1 0xc820 +-#define VEND1_THERMAL_STAT2 0xc821 +-#define VEND1_THERMAL_STAT2_VALID BIT(0) +-#define VEND1_GENERAL_STAT1 0xc830 +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) +- +-#if IS_REACHABLE(CONFIG_HWMON) +- +-static umode_t aqr_hwmon_is_visible(const void *data, +- enum hwmon_sensor_types type, +- u32 attr, int channel) +-{ +- if (type != hwmon_temp) +- return 0; +- +- switch (attr) { +- case hwmon_temp_input: +- case hwmon_temp_min_alarm: +- case hwmon_temp_max_alarm: +- case hwmon_temp_lcrit_alarm: +- case hwmon_temp_crit_alarm: +- return 0444; +- case hwmon_temp_min: +- case hwmon_temp_max: +- case hwmon_temp_lcrit: +- case hwmon_temp_crit: +- return 0644; +- default: +- return 0; +- } +-} +- +-static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value) +-{ +- int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); +- +- if (temp < 0) +- return temp; +- +- /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */ +- *value = (s16)temp * 1000 / 256; +- +- return 0; +-} +- +-static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value) +-{ +- int temp; +- +- if (value >= 128000 || value < -128000) +- return -ERANGE; +- +- temp = value * 256 / 1000; +- +- /* temp is in s16 range and we're interested in lower 16 bits only */ +- return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp); +-} +- +-static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit) +-{ +- int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); +- +- if (val < 0) +- return val; +- +- return !!(val & bit); +-} +- +-static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value) +-{ +- int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit); +- +- if (val < 0) +- return val; +- +- *value = val; +- +- return 0; +-} +- +-static int aqr_hwmon_read(struct device *dev, enum hwmon_sensor_types type, +- u32 attr, int channel, long *value) +-{ +- struct phy_device *phydev = dev_get_drvdata(dev); +- int reg; +- +- if (type != hwmon_temp) +- return -EOPNOTSUPP; +- +- switch (attr) { +- case hwmon_temp_input: +- reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2, +- VEND1_THERMAL_STAT2_VALID); +- if (reg < 0) +- return reg; +- if (!reg) +- return -EBUSY; +- +- return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value); +- +- case hwmon_temp_lcrit: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit: +- return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, +- value); +- case hwmon_temp_lcrit_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit_alarm: +- return aqr_hwmon_status1(phydev, +- VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL, +- value); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type, +- u32 attr, int channel, long value) +-{ +- struct phy_device *phydev = dev_get_drvdata(dev); +- +- if (type != hwmon_temp) +- return -EOPNOTSUPP; +- +- switch (attr) { +- case hwmon_temp_lcrit: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, +- value); +- case hwmon_temp_min: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, +- value); +- case hwmon_temp_max: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, +- value); +- case hwmon_temp_crit: +- return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, +- value); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static const struct hwmon_ops aqr_hwmon_ops = { +- .is_visible = aqr_hwmon_is_visible, +- .read = aqr_hwmon_read, +- .write = aqr_hwmon_write, +-}; +- +-static u32 aqr_hwmon_chip_config[] = { +- HWMON_C_REGISTER_TZ, +- 0, +-}; +- +-static const struct hwmon_channel_info aqr_hwmon_chip = { +- .type = hwmon_chip, +- .config = aqr_hwmon_chip_config, +-}; +- +-static u32 aqr_hwmon_temp_config[] = { +- HWMON_T_INPUT | +- HWMON_T_MAX | HWMON_T_MIN | +- HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM | +- HWMON_T_CRIT | HWMON_T_LCRIT | +- HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM, +- 0, +-}; +- +-static const struct hwmon_channel_info aqr_hwmon_temp = { +- .type = hwmon_temp, +- .config = aqr_hwmon_temp_config, +-}; +- +-static const struct hwmon_channel_info *aqr_hwmon_info[] = { +- &aqr_hwmon_chip, +- &aqr_hwmon_temp, +- NULL, +-}; +- +-static const struct hwmon_chip_info aqr_hwmon_chip_info = { +- .ops = &aqr_hwmon_ops, +- .info = aqr_hwmon_info, +-}; +- +-int aqr_hwmon_probe(struct phy_device *phydev) +-{ +- struct device *dev = &phydev->mdio.dev; +- struct device *hwmon_dev; +- char *hwmon_name; +- int i, j; +- +- hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); +- if (!hwmon_name) +- return -ENOMEM; +- +- for (i = j = 0; hwmon_name[i]; i++) { +- if (isalnum(hwmon_name[i])) { +- if (i != j) +- hwmon_name[j] = hwmon_name[i]; +- j++; +- } +- } +- hwmon_name[j] = '\0'; +- +- hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name, +- phydev, &aqr_hwmon_chip_info, NULL); +- +- return PTR_ERR_OR_ZERO(hwmon_dev); +-} +- +-#endif +--- a/drivers/net/phy/aquantia_main.c ++++ /dev/null +@@ -1,844 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * Driver for Aquantia PHY +- * +- * Author: Shaohui Xie +- * +- * Copyright 2015 Freescale Semiconductor, Inc. +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include "aquantia.h" +- +-#define PHY_ID_AQ1202 0x03a1b445 +-#define PHY_ID_AQ2104 0x03a1b460 +-#define PHY_ID_AQR105 0x03a1b4a2 +-#define PHY_ID_AQR106 0x03a1b4d0 +-#define PHY_ID_AQR107 0x03a1b4e0 +-#define PHY_ID_AQCS109 0x03a1b5c2 +-#define PHY_ID_AQR405 0x03a1b4b0 +-#define PHY_ID_AQR113C 0x31c31c12 +- +-#define MDIO_PHYXS_VEND_IF_STATUS 0xe812 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR 0 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX 1 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI 2 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII 3 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7 +-#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10 +- +-#define MDIO_AN_VEND_PROV 0xc400 +-#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) +-#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) +-#define MDIO_AN_VEND_PROV_5000BASET_FULL BIT(11) +-#define MDIO_AN_VEND_PROV_2500BASET_FULL BIT(10) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_EN BIT(4) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK GENMASK(3, 0) +-#define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT 4 +- +-#define MDIO_AN_TX_VEND_STATUS1 0xc800 +-#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK GENMASK(3, 1) +-#define MDIO_AN_TX_VEND_STATUS1_10BASET 0 +-#define MDIO_AN_TX_VEND_STATUS1_100BASETX 1 +-#define MDIO_AN_TX_VEND_STATUS1_1000BASET 2 +-#define MDIO_AN_TX_VEND_STATUS1_10GBASET 3 +-#define MDIO_AN_TX_VEND_STATUS1_2500BASET 4 +-#define MDIO_AN_TX_VEND_STATUS1_5000BASET 5 +-#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0) +- +-#define MDIO_AN_TX_VEND_INT_STATUS1 0xcc00 +-#define MDIO_AN_TX_VEND_INT_STATUS1_DOWNSHIFT BIT(1) +- +-#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01 +-#define MDIO_AN_TX_VEND_INT_STATUS2_MASK BIT(0) +- +-#define MDIO_AN_TX_VEND_INT_MASK2 0xd401 +-#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) +- +-#define MDIO_AN_RX_LP_STAT1 0xe820 +-#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) +-#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) +-#define MDIO_AN_RX_LP_STAT1_SHORT_REACH BIT(13) +-#define MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT BIT(12) +-#define MDIO_AN_RX_LP_STAT1_AQ_PHY BIT(2) +- +-#define MDIO_AN_RX_LP_STAT4 0xe823 +-#define MDIO_AN_RX_LP_STAT4_FW_MAJOR GENMASK(15, 8) +-#define MDIO_AN_RX_LP_STAT4_FW_MINOR GENMASK(7, 0) +- +-#define MDIO_AN_RX_VEND_STAT3 0xe832 +-#define MDIO_AN_RX_VEND_STAT3_AFR BIT(0) +- +-/* MDIO_MMD_C22EXT */ +-#define MDIO_C22EXT_STAT_SGMII_RX_GOOD_FRAMES 0xd292 +-#define MDIO_C22EXT_STAT_SGMII_RX_BAD_FRAMES 0xd294 +-#define MDIO_C22EXT_STAT_SGMII_RX_FALSE_CARRIER 0xd297 +-#define MDIO_C22EXT_STAT_SGMII_TX_GOOD_FRAMES 0xd313 +-#define MDIO_C22EXT_STAT_SGMII_TX_BAD_FRAMES 0xd315 +-#define MDIO_C22EXT_STAT_SGMII_TX_FALSE_CARRIER 0xd317 +-#define MDIO_C22EXT_STAT_SGMII_TX_COLLISIONS 0xd318 +-#define MDIO_C22EXT_STAT_SGMII_TX_LINE_COLLISIONS 0xd319 +-#define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a +-#define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b +- +-/* Vendor specific 1, MDIO_MMD_VEND1 */ +-#define VEND1_GLOBAL_FW_ID 0x0020 +-#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) +-#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) +- +-#define VEND1_GLOBAL_GEN_STAT2 0xc831 +-#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) +- +-/* The following registers all have similar layouts; first the registers... */ +-#define VEND1_GLOBAL_CFG_10M 0x0310 +-#define VEND1_GLOBAL_CFG_100M 0x031b +-#define VEND1_GLOBAL_CFG_1G 0x031c +-#define VEND1_GLOBAL_CFG_2_5G 0x031d +-#define VEND1_GLOBAL_CFG_5G 0x031e +-#define VEND1_GLOBAL_CFG_10G 0x031f +-/* ...and now the fields */ +-#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 +- +-#define VEND1_GLOBAL_RSVD_STAT1 0xc885 +-#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) +-#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) +- +-#define VEND1_GLOBAL_RSVD_STAT9 0xc88d +-#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) +-#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 +- +-#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 +-#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 +- +-#define VEND1_GLOBAL_INT_STD_MASK 0xff00 +-#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) +-#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) +-#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) +-#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) +-#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) +-#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) +- +-#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 +-#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) +-#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) +-#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) +-#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) +-#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) +- +-/* Sleep and timeout for checking if the Processor-Intensive +- * MDIO operation is finished +- */ +-#define AQR107_OP_IN_PROG_SLEEP 1000 +-#define AQR107_OP_IN_PROG_TIMEOUT 100000 +- +-struct aqr107_hw_stat { +- const char *name; +- int reg; +- int size; +-}; +- +-#define SGMII_STAT(n, r, s) { n, MDIO_C22EXT_STAT_SGMII_ ## r, s } +-static const struct aqr107_hw_stat aqr107_hw_stats[] = { +- SGMII_STAT("sgmii_rx_good_frames", RX_GOOD_FRAMES, 26), +- SGMII_STAT("sgmii_rx_bad_frames", RX_BAD_FRAMES, 26), +- SGMII_STAT("sgmii_rx_false_carrier_events", RX_FALSE_CARRIER, 8), +- SGMII_STAT("sgmii_tx_good_frames", TX_GOOD_FRAMES, 26), +- SGMII_STAT("sgmii_tx_bad_frames", TX_BAD_FRAMES, 26), +- SGMII_STAT("sgmii_tx_false_carrier_events", TX_FALSE_CARRIER, 8), +- SGMII_STAT("sgmii_tx_collisions", TX_COLLISIONS, 8), +- SGMII_STAT("sgmii_tx_line_collisions", TX_LINE_COLLISIONS, 8), +- SGMII_STAT("sgmii_tx_frame_alignment_err", TX_FRAME_ALIGN_ERR, 16), +- SGMII_STAT("sgmii_tx_runt_frames", TX_RUNT_FRAMES, 22), +-}; +-#define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats) +- +-struct aqr107_priv { +- u64 sgmii_stats[AQR107_SGMII_STAT_SZ]; +-}; +- +-static int aqr107_get_sset_count(struct phy_device *phydev) +-{ +- return AQR107_SGMII_STAT_SZ; +-} +- +-static void aqr107_get_strings(struct phy_device *phydev, u8 *data) +-{ +- int i; +- +- for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) +- strscpy(data + i * ETH_GSTRING_LEN, aqr107_hw_stats[i].name, +- ETH_GSTRING_LEN); +-} +- +-static u64 aqr107_get_stat(struct phy_device *phydev, int index) +-{ +- const struct aqr107_hw_stat *stat = aqr107_hw_stats + index; +- int len_l = min(stat->size, 16); +- int len_h = stat->size - len_l; +- u64 ret; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg); +- if (val < 0) +- return U64_MAX; +- +- ret = val & GENMASK(len_l - 1, 0); +- if (len_h) { +- val = phy_read_mmd(phydev, MDIO_MMD_C22EXT, stat->reg + 1); +- if (val < 0) +- return U64_MAX; +- +- ret += (val & GENMASK(len_h - 1, 0)) << 16; +- } +- +- return ret; +-} +- +-static void aqr107_get_stats(struct phy_device *phydev, +- struct ethtool_stats *stats, u64 *data) +-{ +- struct aqr107_priv *priv = phydev->priv; +- u64 val; +- int i; +- +- for (i = 0; i < AQR107_SGMII_STAT_SZ; i++) { +- val = aqr107_get_stat(phydev, i); +- if (val == U64_MAX) +- phydev_err(phydev, "Reading HW Statistics failed for %s\n", +- aqr107_hw_stats[i].name); +- else +- priv->sgmii_stats[i] += val; +- +- data[i] = priv->sgmii_stats[i]; +- } +-} +- +-static int aqr_config_aneg(struct phy_device *phydev) +-{ +- bool changed = false; +- u16 reg; +- int ret; +- +- if (phydev->autoneg == AUTONEG_DISABLE) +- return genphy_c45_pma_setup_forced(phydev); +- +- ret = genphy_c45_an_config_aneg(phydev); +- if (ret < 0) +- return ret; +- if (ret > 0) +- changed = true; +- +- /* Clause 45 has no standardized support for 1000BaseT, therefore +- * use vendor registers for this mode. +- */ +- reg = 0; +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_1000BASET_FULL; +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_1000BASET_HALF; +- +- /* Handle the case when the 2.5G and 5G speeds are not advertised */ +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_2500BASET_FULL; +- +- if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, +- phydev->advertising)) +- reg |= MDIO_AN_VEND_PROV_5000BASET_FULL; +- +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, +- MDIO_AN_VEND_PROV_1000BASET_HALF | +- MDIO_AN_VEND_PROV_1000BASET_FULL | +- MDIO_AN_VEND_PROV_2500BASET_FULL | +- MDIO_AN_VEND_PROV_5000BASET_FULL, reg); +- if (ret < 0) +- return ret; +- if (ret > 0) +- changed = true; +- +- return genphy_c45_check_and_restart_aneg(phydev, changed); +-} +- +-static int aqr_config_intr(struct phy_device *phydev) +-{ +- bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; +- int err; +- +- if (en) { +- /* Clear any pending interrupts before enabling them */ +- err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); +- if (err < 0) +- return err; +- } +- +- err = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_MASK2, +- en ? MDIO_AN_TX_VEND_INT_MASK2_LINK : 0); +- if (err < 0) +- return err; +- +- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_STD_MASK, +- en ? VEND1_GLOBAL_INT_STD_MASK_ALL : 0); +- if (err < 0) +- return err; +- +- err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_INT_VEND_MASK, +- en ? VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 | +- VEND1_GLOBAL_INT_VEND_MASK_AN : 0); +- if (err < 0) +- return err; +- +- if (!en) { +- /* Clear any pending interrupts after we have disabled them */ +- err = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS2); +- if (err < 0) +- return err; +- } +- +- return 0; +-} +- +-static irqreturn_t aqr_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status; +- +- irq_status = phy_read_mmd(phydev, MDIO_MMD_AN, +- MDIO_AN_TX_VEND_INT_STATUS2); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- if (!(irq_status & MDIO_AN_TX_VEND_INT_STATUS2_MASK)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- +-static int aqr_read_status(struct phy_device *phydev) +-{ +- int val; +- +- if (phydev->autoneg == AUTONEG_ENABLE) { +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); +- if (val < 0) +- return val; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, +- phydev->lp_advertising, +- val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL); +- linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, +- phydev->lp_advertising, +- val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF); +- } +- +- return genphy_c45_read_status(phydev); +-} +- +-static int aqr107_read_rate(struct phy_device *phydev) +-{ +- u32 config_reg; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); +- if (val < 0) +- return val; +- +- if (val & MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX) +- phydev->duplex = DUPLEX_FULL; +- else +- phydev->duplex = DUPLEX_HALF; +- +- switch (FIELD_GET(MDIO_AN_TX_VEND_STATUS1_RATE_MASK, val)) { +- case MDIO_AN_TX_VEND_STATUS1_10BASET: +- phydev->speed = SPEED_10; +- config_reg = VEND1_GLOBAL_CFG_10M; +- break; +- case MDIO_AN_TX_VEND_STATUS1_100BASETX: +- phydev->speed = SPEED_100; +- config_reg = VEND1_GLOBAL_CFG_100M; +- break; +- case MDIO_AN_TX_VEND_STATUS1_1000BASET: +- phydev->speed = SPEED_1000; +- config_reg = VEND1_GLOBAL_CFG_1G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_2500BASET: +- phydev->speed = SPEED_2500; +- config_reg = VEND1_GLOBAL_CFG_2_5G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_5000BASET: +- phydev->speed = SPEED_5000; +- config_reg = VEND1_GLOBAL_CFG_5G; +- break; +- case MDIO_AN_TX_VEND_STATUS1_10GBASET: +- phydev->speed = SPEED_10000; +- config_reg = VEND1_GLOBAL_CFG_10G; +- break; +- default: +- phydev->speed = SPEED_UNKNOWN; +- return 0; +- } +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, config_reg); +- if (val < 0) +- return val; +- +- if (FIELD_GET(VEND1_GLOBAL_CFG_RATE_ADAPT, val) == +- VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE) +- phydev->rate_matching = RATE_MATCH_PAUSE; +- else +- phydev->rate_matching = RATE_MATCH_NONE; +- +- return 0; +-} +- +-static int aqr107_read_status(struct phy_device *phydev) +-{ +- int val, ret; +- +- ret = aqr_read_status(phydev); +- if (ret) +- return ret; +- +- if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE) +- return 0; +- +- val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS); +- if (val < 0) +- return val; +- +- switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) { +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR: +- phydev->interface = PHY_INTERFACE_MODE_10GKR; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KX: +- phydev->interface = PHY_INTERFACE_MODE_1000BASEKX; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XFI: +- phydev->interface = PHY_INTERFACE_MODE_10GBASER; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII: +- phydev->interface = PHY_INTERFACE_MODE_USXGMII; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI: +- phydev->interface = PHY_INTERFACE_MODE_XAUI; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII: +- phydev->interface = PHY_INTERFACE_MODE_SGMII; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI: +- phydev->interface = PHY_INTERFACE_MODE_RXAUI; +- break; +- case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII: +- phydev->interface = PHY_INTERFACE_MODE_2500BASEX; +- break; +- default: +- phydev->interface = PHY_INTERFACE_MODE_NA; +- break; +- } +- +- /* Read possibly downshifted rate from vendor register */ +- return aqr107_read_rate(phydev); +-} +- +-static int aqr107_get_downshift(struct phy_device *phydev, u8 *data) +-{ +- int val, cnt, enable; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV); +- if (val < 0) +- return val; +- +- enable = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_EN, val); +- cnt = FIELD_GET(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); +- +- *data = enable && cnt ? cnt : DOWNSHIFT_DEV_DISABLE; +- +- return 0; +-} +- +-static int aqr107_set_downshift(struct phy_device *phydev, u8 cnt) +-{ +- int val = 0; +- +- if (!FIELD_FIT(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt)) +- return -E2BIG; +- +- if (cnt != DOWNSHIFT_DEV_DISABLE) { +- val = MDIO_AN_VEND_PROV_DOWNSHIFT_EN; +- val |= FIELD_PREP(MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, cnt); +- } +- +- return phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, +- MDIO_AN_VEND_PROV_DOWNSHIFT_EN | +- MDIO_AN_VEND_PROV_DOWNSHIFT_MASK, val); +-} +- +-static int aqr107_get_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return aqr107_get_downshift(phydev, data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int aqr107_set_tunable(struct phy_device *phydev, +- struct ethtool_tunable *tuna, const void *data) +-{ +- switch (tuna->id) { +- case ETHTOOL_PHY_DOWNSHIFT: +- return aqr107_set_downshift(phydev, *(const u8 *)data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-/* If we configure settings whilst firmware is still initializing the chip, +- * then these settings may be overwritten. Therefore make sure chip +- * initialization has completed. Use presence of the firmware ID as +- * indicator for initialization having completed. +- * The chip also provides a "reset completed" bit, but it's cleared after +- * read. Therefore function would time out if called again. +- */ +-static int aqr107_wait_reset_complete(struct phy_device *phydev) +-{ +- int val; +- +- return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, +- VEND1_GLOBAL_FW_ID, val, val != 0, +- 20000, 2000000, false); +-} +- +-static void aqr107_chip_info(struct phy_device *phydev) +-{ +- u8 fw_major, fw_minor, build_id, prov_id; +- int val; +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); +- if (val < 0) +- return; +- +- fw_major = FIELD_GET(VEND1_GLOBAL_FW_ID_MAJOR, val); +- fw_minor = FIELD_GET(VEND1_GLOBAL_FW_ID_MINOR, val); +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT1); +- if (val < 0) +- return; +- +- build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); +- prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); +- +- phydev_dbg(phydev, "FW %u.%u, Build %u, Provisioning %u\n", +- fw_major, fw_minor, build_id, prov_id); +-} +- +-static int aqr107_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Check that the PHY interface type is compatible */ +- if (phydev->interface != PHY_INTERFACE_MODE_SGMII && +- phydev->interface != PHY_INTERFACE_MODE_1000BASEKX && +- phydev->interface != PHY_INTERFACE_MODE_2500BASEX && +- phydev->interface != PHY_INTERFACE_MODE_XGMII && +- phydev->interface != PHY_INTERFACE_MODE_USXGMII && +- phydev->interface != PHY_INTERFACE_MODE_10GKR && +- phydev->interface != PHY_INTERFACE_MODE_10GBASER && +- phydev->interface != PHY_INTERFACE_MODE_XAUI && +- phydev->interface != PHY_INTERFACE_MODE_RXAUI) +- return -ENODEV; +- +- WARN(phydev->interface == PHY_INTERFACE_MODE_XGMII, +- "Your devicetree is out of date, please update it. The AQR107 family doesn't support XGMII, maybe you mean USXGMII.\n"); +- +- ret = aqr107_wait_reset_complete(phydev); +- if (!ret) +- aqr107_chip_info(phydev); +- +- return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); +-} +- +-static int aqcs109_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- /* Check that the PHY interface type is compatible */ +- if (phydev->interface != PHY_INTERFACE_MODE_SGMII && +- phydev->interface != PHY_INTERFACE_MODE_2500BASEX) +- return -ENODEV; +- +- ret = aqr107_wait_reset_complete(phydev); +- if (!ret) +- aqr107_chip_info(phydev); +- +- /* AQCS109 belongs to a chip family partially supporting 10G and 5G. +- * PMA speed ability bits are the same for all members of the family, +- * AQCS109 however supports speeds up to 2.5G only. +- */ +- ret = phy_set_max_speed(phydev, SPEED_2500); +- if (ret) +- return ret; +- +- return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); +-} +- +-static void aqr107_link_change_notify(struct phy_device *phydev) +-{ +- u8 fw_major, fw_minor; +- bool downshift, short_reach, afr; +- int mode, val; +- +- if (phydev->state != PHY_RUNNING || phydev->autoneg == AUTONEG_DISABLE) +- return; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); +- /* call failed or link partner is no Aquantia PHY */ +- if (val < 0 || !(val & MDIO_AN_RX_LP_STAT1_AQ_PHY)) +- return; +- +- short_reach = val & MDIO_AN_RX_LP_STAT1_SHORT_REACH; +- downshift = val & MDIO_AN_RX_LP_STAT1_AQRATE_DOWNSHIFT; +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT4); +- if (val < 0) +- return; +- +- fw_major = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MAJOR, val); +- fw_minor = FIELD_GET(MDIO_AN_RX_LP_STAT4_FW_MINOR, val); +- +- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_VEND_STAT3); +- if (val < 0) +- return; +- +- afr = val & MDIO_AN_RX_VEND_STAT3_AFR; +- +- phydev_dbg(phydev, "Link partner is Aquantia PHY, FW %u.%u%s%s%s\n", +- fw_major, fw_minor, +- short_reach ? ", short reach mode" : "", +- downshift ? ", fast-retrain downshift advertised" : "", +- afr ? ", fast reframe advertised" : ""); +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_RSVD_STAT9); +- if (val < 0) +- return; +- +- mode = FIELD_GET(VEND1_GLOBAL_RSVD_STAT9_MODE, val); +- if (mode == VEND1_GLOBAL_RSVD_STAT9_1000BT2) +- phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n"); +-} +- +-static int aqr107_wait_processor_intensive_op(struct phy_device *phydev) +-{ +- int val, err; +- +- /* The datasheet notes to wait at least 1ms after issuing a +- * processor intensive operation before checking. +- * We cannot use the 'sleep_before_read' parameter of read_poll_timeout +- * because that just determines the maximum time slept, not the minimum. +- */ +- usleep_range(1000, 5000); +- +- err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, +- VEND1_GLOBAL_GEN_STAT2, val, +- !(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG), +- AQR107_OP_IN_PROG_SLEEP, +- AQR107_OP_IN_PROG_TIMEOUT, false); +- if (err) { +- phydev_err(phydev, "timeout: processor-intensive MDIO operation\n"); +- return err; +- } +- +- return 0; +-} +- +-static int aqr107_get_rate_matching(struct phy_device *phydev, +- phy_interface_t iface) +-{ +- if (iface == PHY_INTERFACE_MODE_10GBASER || +- iface == PHY_INTERFACE_MODE_2500BASEX || +- iface == PHY_INTERFACE_MODE_NA) +- return RATE_MATCH_PAUSE; +- return RATE_MATCH_NONE; +-} +- +-static int aqr107_suspend(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, +- MDIO_CTRL1_LPOWER); +- if (err) +- return err; +- +- return aqr107_wait_processor_intensive_op(phydev); +-} +- +-static int aqr107_resume(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, +- MDIO_CTRL1_LPOWER); +- if (err) +- return err; +- +- return aqr107_wait_processor_intensive_op(phydev); +-} +- +-static int aqr107_probe(struct phy_device *phydev) +-{ +- phydev->priv = devm_kzalloc(&phydev->mdio.dev, +- sizeof(struct aqr107_priv), GFP_KERNEL); +- if (!phydev->priv) +- return -ENOMEM; +- +- return aqr_hwmon_probe(phydev); +-} +- +-static struct phy_driver aqr_driver[] = { +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), +- .name = "Aquantia AQ1202", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), +- .name = "Aquantia AQ2104", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR105), +- .name = "Aquantia AQR105", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR106), +- .name = "Aquantia AQR106", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR107), +- .name = "Aquantia AQR107", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqr107_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), +- .name = "Aquantia AQCS109", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqcs109_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR405), +- .name = "Aquantia AQR405", +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr_read_status, +-}, +-{ +- PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), +- .name = "Aquantia AQR113C", +- .probe = aqr107_probe, +- .get_rate_matching = aqr107_get_rate_matching, +- .config_init = aqr107_config_init, +- .config_aneg = aqr_config_aneg, +- .config_intr = aqr_config_intr, +- .handle_interrupt = aqr_handle_interrupt, +- .read_status = aqr107_read_status, +- .get_tunable = aqr107_get_tunable, +- .set_tunable = aqr107_set_tunable, +- .suspend = aqr107_suspend, +- .resume = aqr107_resume, +- .get_sset_count = aqr107_get_sset_count, +- .get_strings = aqr107_get_strings, +- .get_stats = aqr107_get_stats, +- .link_change_notify = aqr107_link_change_notify, +-}, +-}; +- +-module_phy_driver(aqr_driver); +- +-static struct mdio_device_id __maybe_unused aqr_tbl[] = { +- { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, +- { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, +- { } +-}; +- +-MODULE_DEVICE_TABLE(mdio, aqr_tbl); +- +-MODULE_DESCRIPTION("Aquantia PHY driver"); +-MODULE_AUTHOR("Shaohui Xie "); +-MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/backport-5.15/737-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch b/target/linux/generic/backport-5.15/737-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch new file mode 100644 index 0000000000..2b94522723 --- /dev/null +++ b/target/linux/generic/backport-5.15/737-02-v6.7-net-phy-aquantia-move-MMD_VEND-define-to-header.patch @@ -0,0 +1,183 @@ +From e1fbfa4a995d42e02e22b0dff2f8b4fdee1504b3 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Nov 2023 15:08:42 +0100 +Subject: [PATCH 2/3] net: phy: aquantia: move MMD_VEND define to header + +Move MMD_VEND define to header to clean things up and in preparation for +firmware loading support that require some define placed in +aquantia_main. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/aquantia.h | 69 +++++++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_hwmon.c | 14 ----- + drivers/net/phy/aquantia/aquantia_main.c | 55 ------------------ + 3 files changed, 69 insertions(+), 69 deletions(-) + +--- a/drivers/net/phy/aquantia/aquantia.h ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -9,6 +9,75 @@ + #include + #include + ++/* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_FW_ID 0x0020 ++#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) ++#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) ++ ++/* The following registers all have similar layouts; first the registers... */ ++#define VEND1_GLOBAL_CFG_10M 0x0310 ++#define VEND1_GLOBAL_CFG_100M 0x031b ++#define VEND1_GLOBAL_CFG_1G 0x031c ++#define VEND1_GLOBAL_CFG_2_5G 0x031d ++#define VEND1_GLOBAL_CFG_5G 0x031e ++#define VEND1_GLOBAL_CFG_10G 0x031f ++/* ...and now the fields */ ++#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 ++#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 ++ ++/* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 ++#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 ++#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 ++#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 ++#define VEND1_THERMAL_STAT1 0xc820 ++#define VEND1_THERMAL_STAT2 0xc821 ++#define VEND1_THERMAL_STAT2_VALID BIT(0) ++#define VEND1_GENERAL_STAT1 0xc830 ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) ++#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) ++#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) ++ ++#define VEND1_GLOBAL_GEN_STAT2 0xc831 ++#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) ++ ++#define VEND1_GLOBAL_RSVD_STAT1 0xc885 ++#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) ++#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) ++ ++#define VEND1_GLOBAL_RSVD_STAT9 0xc88d ++#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) ++#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 ++ ++#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 ++#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 ++ ++#define VEND1_GLOBAL_INT_STD_MASK 0xff00 ++#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) ++#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) ++#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) ++#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) ++#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) ++#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) ++#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) ++#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) ++ ++#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 ++#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) ++#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) ++#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) ++#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) ++#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) ++#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) ++ + #if IS_REACHABLE(CONFIG_HWMON) + int aqr_hwmon_probe(struct phy_device *phydev); + #else +--- a/drivers/net/phy/aquantia/aquantia_hwmon.c ++++ b/drivers/net/phy/aquantia/aquantia_hwmon.c +@@ -13,20 +13,6 @@ + + #include "aquantia.h" + +-/* Vendor specific 1, MDIO_MMD_VEND2 */ +-#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 +-#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 +-#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +-#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 +-#define VEND1_THERMAL_STAT1 0xc820 +-#define VEND1_THERMAL_STAT2 0xc821 +-#define VEND1_THERMAL_STAT2_VALID BIT(0) +-#define VEND1_GENERAL_STAT1 0xc830 +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) +-#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) +-#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) +- + #if IS_REACHABLE(CONFIG_HWMON) + + static umode_t aqr_hwmon_is_visible(const void *data, +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -89,61 +89,6 @@ + #define MDIO_C22EXT_STAT_SGMII_TX_FRAME_ALIGN_ERR 0xd31a + #define MDIO_C22EXT_STAT_SGMII_TX_RUNT_FRAMES 0xd31b + +-/* Vendor specific 1, MDIO_MMD_VEND1 */ +-#define VEND1_GLOBAL_FW_ID 0x0020 +-#define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) +-#define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) +- +-#define VEND1_GLOBAL_GEN_STAT2 0xc831 +-#define VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG BIT(15) +- +-/* The following registers all have similar layouts; first the registers... */ +-#define VEND1_GLOBAL_CFG_10M 0x0310 +-#define VEND1_GLOBAL_CFG_100M 0x031b +-#define VEND1_GLOBAL_CFG_1G 0x031c +-#define VEND1_GLOBAL_CFG_2_5G 0x031d +-#define VEND1_GLOBAL_CFG_5G 0x031e +-#define VEND1_GLOBAL_CFG_10G 0x031f +-/* ...and now the fields */ +-#define VEND1_GLOBAL_CFG_RATE_ADAPT GENMASK(8, 7) +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE 0 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_USX 1 +-#define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 +- +-#define VEND1_GLOBAL_RSVD_STAT1 0xc885 +-#define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID GENMASK(7, 4) +-#define VEND1_GLOBAL_RSVD_STAT1_PROV_ID GENMASK(3, 0) +- +-#define VEND1_GLOBAL_RSVD_STAT9 0xc88d +-#define VEND1_GLOBAL_RSVD_STAT9_MODE GENMASK(7, 0) +-#define VEND1_GLOBAL_RSVD_STAT9_1000BT2 0x23 +- +-#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 +-#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 +- +-#define VEND1_GLOBAL_INT_STD_MASK 0xff00 +-#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) +-#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) +-#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) +-#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) +-#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) +-#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) +-#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) +-#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) +- +-#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 +-#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) +-#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) +-#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) +-#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) +-#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) +-#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) +- + /* Sleep and timeout for checking if the Processor-Intensive + * MDIO operation is finished + */ diff --git a/target/linux/generic/backport-5.15/737-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch b/target/linux/generic/backport-5.15/737-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch new file mode 100644 index 0000000000..1ae5966df6 --- /dev/null +++ b/target/linux/generic/backport-5.15/737-03-v6.7-net-phy-aquantia-add-firmware-load-support.patch @@ -0,0 +1,504 @@ +From e93984ebc1c82bd34f7a1b3391efaceee0a8ae96 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 14 Nov 2023 15:08:43 +0100 +Subject: [PATCH 3/3] net: phy: aquantia: add firmware load support + +Aquantia PHY-s require firmware to be loaded before they start operating. +It can be automatically loaded in case when there is a SPI-NOR connected +to Aquantia PHY-s or can be loaded from the host via MDIO. + +This patch adds support for loading the firmware via MDIO as in most cases +there is no SPI-NOR being used to save on cost. +Firmware loading code itself is ported from mainline U-boot with cleanups. + +The firmware has mixed values both in big and little endian. +PHY core itself is big-endian but it expects values to be in little-endian. +The firmware is little-endian but CRC-16 value for it is stored at the end +of firmware in big-endian. + +It seems the PHY does the conversion internally from firmware that is +little-endian to the PHY that is big-endian on using the mailbox +but mailbox returns a big-endian CRC-16 to verify the written data +integrity. + +Co-developed-by: Christian Marangi +Signed-off-by: Robert Marko +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia/Kconfig | 1 + + drivers/net/phy/aquantia/Makefile | 2 +- + drivers/net/phy/aquantia/aquantia.h | 32 ++ + drivers/net/phy/aquantia/aquantia_firmware.c | 370 +++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 6 + + 5 files changed, 410 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/phy/aquantia/aquantia_firmware.c + +--- a/drivers/net/phy/aquantia/Kconfig ++++ b/drivers/net/phy/aquantia/Kconfig +@@ -1,5 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + config AQUANTIA_PHY + tristate "Aquantia PHYs" ++ select CRC_CCITT + help + Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 +--- a/drivers/net/phy/aquantia/Makefile ++++ b/drivers/net/phy/aquantia/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 +-aquantia-objs += aquantia_main.o ++aquantia-objs += aquantia_main.o aquantia_firmware.o + ifdef CONFIG_HWMON + aquantia-objs += aquantia_hwmon.o + endif +--- a/drivers/net/phy/aquantia/aquantia.h ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -10,10 +10,35 @@ + #include + + /* Vendor specific 1, MDIO_MMD_VEND1 */ ++#define VEND1_GLOBAL_SC 0x0 ++#define VEND1_GLOBAL_SC_SOFT_RESET BIT(15) ++#define VEND1_GLOBAL_SC_LOW_POWER BIT(11) ++ + #define VEND1_GLOBAL_FW_ID 0x0020 + #define VEND1_GLOBAL_FW_ID_MAJOR GENMASK(15, 8) + #define VEND1_GLOBAL_FW_ID_MINOR GENMASK(7, 0) + ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1 0x0200 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE BIT(15) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE BIT(14) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET BIT(12) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE1_BUSY BIT(8) ++ ++#define VEND1_GLOBAL_MAILBOX_INTERFACE2 0x0201 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3 0x0202 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR_MASK, (u16)((x) >> 16)) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4 0x0203 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK GENMASK(15, 2) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR_MASK, (u16)(x)) ++ ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5 0x0204 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA_MASK, (u16)((x) >> 16)) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6 0x0205 ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK GENMASK(15, 0) ++#define VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(x) FIELD_PREP(VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA_MASK, (u16)(x)) ++ + /* The following registers all have similar layouts; first the registers... */ + #define VEND1_GLOBAL_CFG_10M 0x0310 + #define VEND1_GLOBAL_CFG_100M 0x031b +@@ -28,6 +53,11 @@ + #define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE 2 + + /* Vendor specific 1, MDIO_MMD_VEND2 */ ++#define VEND1_GLOBAL_CONTROL2 0xc001 ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST BIT(15) ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD BIT(6) ++#define VEND1_GLOBAL_CONTROL2_UP_RUN_STALL BIT(0) ++ + #define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 + #define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 + #define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +@@ -83,3 +113,5 @@ int aqr_hwmon_probe(struct phy_device *p + #else + static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } + #endif ++ ++int aqr_firmware_load(struct phy_device *phydev); +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_firmware.c +@@ -0,0 +1,370 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "aquantia.h" ++ ++#define UP_RESET_SLEEP 100 ++ ++/* addresses of memory segments in the phy */ ++#define DRAM_BASE_ADDR 0x3FFE0000 ++#define IRAM_BASE_ADDR 0x40000000 ++ ++/* firmware image format constants */ ++#define VERSION_STRING_SIZE 0x40 ++#define VERSION_STRING_OFFSET 0x0200 ++/* primary offset is written at an offset from the start of the fw blob */ ++#define PRIMARY_OFFSET_OFFSET 0x8 ++/* primary offset needs to be then added to a base offset */ ++#define PRIMARY_OFFSET_SHIFT 12 ++#define PRIMARY_OFFSET(x) ((x) << PRIMARY_OFFSET_SHIFT) ++#define HEADER_OFFSET 0x300 ++ ++struct aqr_fw_header { ++ u32 padding; ++ u8 iram_offset[3]; ++ u8 iram_size[3]; ++ u8 dram_offset[3]; ++ u8 dram_size[3]; ++} __packed; ++ ++enum aqr_fw_src { ++ AQR_FW_SRC_NVMEM = 0, ++ AQR_FW_SRC_FS, ++}; ++ ++static const char * const aqr_fw_src_string[] = { ++ [AQR_FW_SRC_NVMEM] = "NVMEM", ++ [AQR_FW_SRC_FS] = "FS", ++}; ++ ++/* AQR firmware doesn't have fixed offsets for iram and dram section ++ * but instead provide an header with the offset to use on reading ++ * and parsing the firmware. ++ * ++ * AQR firmware can't be trusted and each offset is validated to be ++ * not negative and be in the size of the firmware itself. ++ */ ++static bool aqr_fw_validate_get(size_t size, size_t offset, size_t get_size) ++{ ++ return offset + get_size <= size; ++} ++ ++static int aqr_fw_get_be16(const u8 *data, size_t offset, size_t size, u16 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u16))) ++ return -EINVAL; ++ ++ *value = get_unaligned_be16(data + offset); ++ ++ return 0; ++} ++ ++static int aqr_fw_get_le16(const u8 *data, size_t offset, size_t size, u16 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u16))) ++ return -EINVAL; ++ ++ *value = get_unaligned_le16(data + offset); ++ ++ return 0; ++} ++ ++static int aqr_fw_get_le24(const u8 *data, size_t offset, size_t size, u32 *value) ++{ ++ if (!aqr_fw_validate_get(size, offset, sizeof(u8) * 3)) ++ return -EINVAL; ++ ++ *value = get_unaligned_le24(data + offset); ++ ++ return 0; ++} ++ ++/* load data into the phy's memory */ ++static int aqr_fw_load_memory(struct phy_device *phydev, u32 addr, ++ const u8 *data, size_t len) ++{ ++ u16 crc = 0, up_crc; ++ size_t pos; ++ ++ /* PHY expect addr in LE */ ++ addr = (__force u32)cpu_to_le32(addr); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE3, ++ VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(addr)); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE4, ++ VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(addr)); ++ ++ /* We assume and enforce the size to be word aligned. ++ * If a firmware that is not word aligned is found, please report upstream. ++ */ ++ for (pos = 0; pos < len; pos += sizeof(u32)) { ++ u32 word; ++ ++ /* FW data is always stored in little-endian */ ++ word = get_unaligned((const u32 *)(data + pos)); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE5, ++ VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(word)); ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE6, ++ VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(word)); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE1, ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE | ++ VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE); ++ ++ /* calculate CRC as we load data to the mailbox. ++ * We convert word to big-endian as PHY is BE and mailbox will ++ * return a BE CRC. ++ */ ++ word = (__force u32)cpu_to_be32(word); ++ crc = crc_ccitt_false(crc, (u8 *)&word, sizeof(word)); ++ } ++ ++ up_crc = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE2); ++ if (crc != up_crc) { ++ phydev_err(phydev, "CRC mismatch: calculated 0x%04x PHY 0x%04x\n", ++ crc, up_crc); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int aqr_fw_boot(struct phy_device *phydev, const u8 *data, size_t size, ++ enum aqr_fw_src fw_src) ++{ ++ u16 calculated_crc, read_crc, read_primary_offset; ++ u32 iram_offset = 0, iram_size = 0; ++ u32 dram_offset = 0, dram_size = 0; ++ char version[VERSION_STRING_SIZE]; ++ u32 primary_offset = 0; ++ int ret; ++ ++ /* extract saved CRC at the end of the fw ++ * CRC is saved in big-endian as PHY is BE ++ */ ++ ret = aqr_fw_get_be16(data, size - sizeof(u16), size, &read_crc); ++ if (ret) { ++ phydev_err(phydev, "bad firmware CRC in firmware\n"); ++ return ret; ++ } ++ calculated_crc = crc_ccitt_false(0, data, size - sizeof(u16)); ++ if (read_crc != calculated_crc) { ++ phydev_err(phydev, "bad firmware CRC: file 0x%04x calculated 0x%04x\n", ++ read_crc, calculated_crc); ++ return -EINVAL; ++ } ++ ++ /* Get the primary offset to extract DRAM and IRAM sections. */ ++ ret = aqr_fw_get_le16(data, PRIMARY_OFFSET_OFFSET, size, &read_primary_offset); ++ if (ret) { ++ phydev_err(phydev, "bad primary offset in firmware\n"); ++ return ret; ++ } ++ primary_offset = PRIMARY_OFFSET(read_primary_offset); ++ ++ /* Find the DRAM and IRAM sections within the firmware file. ++ * Make sure the fw_header is correctly in the firmware. ++ */ ++ if (!aqr_fw_validate_get(size, primary_offset + HEADER_OFFSET, ++ sizeof(struct aqr_fw_header))) { ++ phydev_err(phydev, "bad fw_header in firmware\n"); ++ return -EINVAL; ++ } ++ ++ /* offset are in LE and values needs to be converted to cpu endian */ ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, iram_offset), ++ size, &iram_offset); ++ if (ret) { ++ phydev_err(phydev, "bad iram offset in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, iram_size), ++ size, &iram_size); ++ if (ret) { ++ phydev_err(phydev, "invalid iram size in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, dram_offset), ++ size, &dram_offset); ++ if (ret) { ++ phydev_err(phydev, "bad dram offset in firmware\n"); ++ return ret; ++ } ++ ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + ++ offsetof(struct aqr_fw_header, dram_size), ++ size, &dram_size); ++ if (ret) { ++ phydev_err(phydev, "invalid dram size in firmware\n"); ++ return ret; ++ } ++ ++ /* Increment the offset with the primary offset. ++ * Validate iram/dram offset and size. ++ */ ++ iram_offset += primary_offset; ++ if (iram_size % sizeof(u32)) { ++ phydev_err(phydev, "iram size if not aligned to word size. Please report this upstream!\n"); ++ return -EINVAL; ++ } ++ if (!aqr_fw_validate_get(size, iram_offset, iram_size)) { ++ phydev_err(phydev, "invalid iram offset for iram size\n"); ++ return -EINVAL; ++ } ++ ++ dram_offset += primary_offset; ++ if (dram_size % sizeof(u32)) { ++ phydev_err(phydev, "dram size if not aligned to word size. Please report this upstream!\n"); ++ return -EINVAL; ++ } ++ if (!aqr_fw_validate_get(size, dram_offset, dram_size)) { ++ phydev_err(phydev, "invalid iram offset for iram size\n"); ++ return -EINVAL; ++ } ++ ++ phydev_dbg(phydev, "primary %d IRAM offset=%d size=%d DRAM offset=%d size=%d\n", ++ primary_offset, iram_offset, iram_size, dram_offset, dram_size); ++ ++ if (!aqr_fw_validate_get(size, dram_offset + VERSION_STRING_OFFSET, ++ VERSION_STRING_SIZE)) { ++ phydev_err(phydev, "invalid version in firmware\n"); ++ return -EINVAL; ++ } ++ strscpy(version, (char *)data + dram_offset + VERSION_STRING_OFFSET, ++ VERSION_STRING_SIZE); ++ if (version[0] == '\0') { ++ phydev_err(phydev, "invalid version in firmware\n"); ++ return -EINVAL; ++ } ++ phydev_info(phydev, "loading firmware version '%s' from '%s'\n", version, ++ aqr_fw_src_string[fw_src]); ++ ++ /* stall the microcprocessor */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD); ++ ++ phydev_dbg(phydev, "loading DRAM 0x%08x from offset=%d size=%d\n", ++ DRAM_BASE_ADDR, dram_offset, dram_size); ++ ret = aqr_fw_load_memory(phydev, DRAM_BASE_ADDR, data + dram_offset, ++ dram_size); ++ if (ret) ++ return ret; ++ ++ phydev_dbg(phydev, "loading IRAM 0x%08x from offset=%d size=%d\n", ++ IRAM_BASE_ADDR, iram_offset, iram_size); ++ ret = aqr_fw_load_memory(phydev, IRAM_BASE_ADDR, data + iram_offset, ++ iram_size); ++ if (ret) ++ return ret; ++ ++ /* make sure soft reset and low power mode are clear */ ++ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_SC, ++ VEND1_GLOBAL_SC_SOFT_RESET | VEND1_GLOBAL_SC_LOW_POWER); ++ ++ /* Release the microprocessor. UP_RESET must be held for 100 usec. */ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD | ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST); ++ usleep_range(UP_RESET_SLEEP, UP_RESET_SLEEP * 2); ++ ++ phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, ++ VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD); ++ ++ return 0; ++} ++ ++static int aqr_firmware_load_nvmem(struct phy_device *phydev) ++{ ++ struct nvmem_cell *cell; ++ size_t size; ++ u8 *buf; ++ int ret; ++ ++ cell = nvmem_cell_get(&phydev->mdio.dev, "firmware"); ++ if (IS_ERR(cell)) ++ return PTR_ERR(cell); ++ ++ buf = nvmem_cell_read(cell, &size); ++ if (IS_ERR(buf)) { ++ ret = PTR_ERR(buf); ++ goto exit; ++ } ++ ++ ret = aqr_fw_boot(phydev, buf, size, AQR_FW_SRC_NVMEM); ++ if (ret) ++ phydev_err(phydev, "firmware loading failed: %d\n", ret); ++ ++ kfree(buf); ++exit: ++ nvmem_cell_put(cell); ++ ++ return ret; ++} ++ ++static int aqr_firmware_load_fs(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ const struct firmware *fw; ++ const char *fw_name; ++ int ret; ++ ++ ret = of_property_read_string(dev->of_node, "firmware-name", ++ &fw_name); ++ if (ret) ++ return ret; ++ ++ ret = request_firmware(&fw, fw_name, dev); ++ if (ret) { ++ phydev_err(phydev, "failed to find FW file %s (%d)\n", ++ fw_name, ret); ++ return ret; ++ } ++ ++ ret = aqr_fw_boot(phydev, fw->data, fw->size, AQR_FW_SRC_FS); ++ if (ret) ++ phydev_err(phydev, "firmware loading failed: %d\n", ret); ++ ++ release_firmware(fw); ++ ++ return ret; ++} ++ ++int aqr_firmware_load(struct phy_device *phydev) ++{ ++ int ret; ++ ++ /* Check if the firmware is not already loaded by pooling ++ * the current version returned by the PHY. If 0 is returned, ++ * no firmware is loaded. ++ */ ++ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); ++ if (ret > 0) ++ goto exit; ++ ++ ret = aqr_firmware_load_nvmem(phydev); ++ if (!ret) ++ goto exit; ++ ++ ret = aqr_firmware_load_fs(phydev); ++ if (ret) ++ return ret; ++ ++exit: ++ return 0; ++} +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -658,11 +658,17 @@ static int aqr107_resume(struct phy_devi + + static int aqr107_probe(struct phy_device *phydev) + { ++ int ret; ++ + phydev->priv = devm_kzalloc(&phydev->mdio.dev, + sizeof(struct aqr107_priv), GFP_KERNEL); + if (!phydev->priv) + return -ENOMEM; + ++ ret = aqr_firmware_load(phydev); ++ if (ret) ++ return ret; ++ + return aqr_hwmon_probe(phydev); + } + diff --git a/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch b/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch index 7eb097f86d..7c0a490695 100644 --- a/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch +++ b/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch @@ -31,7 +31,7 @@ Signed-off-by: David S. Miller F: drivers/net/phy/motorcomm.c --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -245,7 +245,7 @@ config MOTORCOMM_PHY +@@ -242,7 +242,7 @@ config MOTORCOMM_PHY tristate "Motorcomm PHYs" help Enables support for Motorcomm network PHYs. diff --git a/target/linux/generic/backport-5.15/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch b/target/linux/generic/backport-5.15/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch index da60c63905..94d09092cf 100644 --- a/target/linux/generic/backport-5.15/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch +++ b/target/linux/generic/backport-5.15/791-v6.2-03-net-phy-add-Motorcomm-YT8531S-phy-id.patch @@ -22,7 +22,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -245,7 +245,7 @@ config MOTORCOMM_PHY +@@ -242,7 +242,7 @@ config MOTORCOMM_PHY tristate "Motorcomm PHYs" help Enables support for Motorcomm network PHYs. diff --git a/target/linux/generic/backport-5.15/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch b/target/linux/generic/backport-5.15/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch index 9dce5a8add..a8b9e3d13b 100644 --- a/target/linux/generic/backport-5.15/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch +++ b/target/linux/generic/backport-5.15/791-v6.3-09-net-phy-Add-driver-for-Motorcomm-yt8531-gigabit-ethernet.patch @@ -19,7 +19,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -245,7 +245,7 @@ config MOTORCOMM_PHY +@@ -242,7 +242,7 @@ config MOTORCOMM_PHY tristate "Motorcomm PHYs" help Enables support for Motorcomm network PHYs. diff --git a/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch index d8ec95b374..c4a915956e 100644 --- a/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch +++ b/target/linux/generic/hack-5.15/720-net-phy-add-aqr-phys.patch @@ -7,8 +7,8 @@ PHYs AQR113C and AQR813. Signed-off-by: Birger Koblitz ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c @@ -23,6 +23,7 @@ #define PHY_ID_AQCS109 0x03a1b5c2 #define PHY_ID_AQR405 0x03a1b4b0 @@ -17,7 +17,7 @@ Signed-off-by: Birger Koblitz #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -415,6 +416,49 @@ static int aqr107_read_rate(struct phy_d +@@ -360,6 +361,49 @@ static int aqr107_read_rate(struct phy_d return 0; } @@ -67,7 +67,7 @@ Signed-off-by: Birger Koblitz static int aqr107_read_status(struct phy_device *phydev) { int val, ret; -@@ -554,7 +598,7 @@ static void aqr107_chip_info(struct phy_ +@@ -499,7 +543,7 @@ static void aqr107_chip_info(struct phy_ build_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID, val); prov_id = FIELD_GET(VEND1_GLOBAL_RSVD_STAT1_PROV_ID, val); @@ -76,7 +76,7 @@ Signed-off-by: Birger Koblitz fw_major, fw_minor, build_id, prov_id); } -@@ -811,7 +855,7 @@ static struct phy_driver aqr_driver[] = +@@ -762,7 +806,7 @@ static struct phy_driver aqr_driver[] = .config_aneg = aqr_config_aneg, .config_intr = aqr_config_intr, .handle_interrupt = aqr_handle_interrupt, @@ -85,7 +85,7 @@ Signed-off-by: Birger Koblitz .get_tunable = aqr107_get_tunable, .set_tunable = aqr107_set_tunable, .suspend = aqr107_suspend, -@@ -821,6 +865,24 @@ static struct phy_driver aqr_driver[] = +@@ -772,6 +816,24 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, .link_change_notify = aqr107_link_change_notify, }, @@ -110,7 +110,7 @@ Signed-off-by: Birger Koblitz }; module_phy_driver(aqr_driver); -@@ -834,6 +896,7 @@ static struct mdio_device_id __maybe_unu +@@ -785,6 +847,7 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, diff --git a/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch index f80757cae9..6ec0db2526 100644 --- a/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch +++ b/target/linux/generic/hack-5.15/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch @@ -10,11 +10,11 @@ different firmware on the PHY. Signed-off-by: Alex Marginean --- - drivers/net/phy/aquantia_main.c | 88 +++++++++++++++++++++++++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 88 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c @@ -24,6 +24,8 @@ #define PHY_ID_AQR405 0x03a1b4b0 #define PHY_ID_AQR113C 0x31c31c12 @@ -24,7 +24,7 @@ Signed-off-by: Alex Marginean #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -151,6 +153,29 @@ +@@ -96,6 +98,29 @@ #define AQR107_OP_IN_PROG_SLEEP 1000 #define AQR107_OP_IN_PROG_TIMEOUT 100000 @@ -54,7 +54,7 @@ Signed-off-by: Alex Marginean struct aqr107_hw_stat { const char *name; int reg; -@@ -282,6 +307,51 @@ static int aqr_config_aneg(struct phy_de +@@ -227,6 +252,51 @@ static int aqr_config_aneg(struct phy_de return genphy_c45_check_and_restart_aneg(phydev, changed); } @@ -106,7 +106,7 @@ Signed-off-by: Alex Marginean static int aqr_config_intr(struct phy_device *phydev) { bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; -@@ -883,6 +953,30 @@ static struct phy_driver aqr_driver[] = +@@ -834,6 +904,30 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, .link_change_notify = aqr107_link_change_notify, }, @@ -137,7 +137,7 @@ Signed-off-by: Alex Marginean }; module_phy_driver(aqr_driver); -@@ -897,6 +991,8 @@ static struct mdio_device_id __maybe_unu +@@ -848,6 +942,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, diff --git a/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch b/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch index 8e204cb146..33b182eab9 100644 --- a/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch +++ b/target/linux/generic/hack-5.15/723-net-phy-aquantia-fix-system-side-protocol-mi.patch @@ -9,12 +9,12 @@ these protocols leads to link issues on system side. Signed-off-by: Alex Marginean --- - drivers/net/phy/aquantia_main.c | 8 +++++++- + drivers/net/phy/aquantia/aquantia_main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c -@@ -340,10 +340,16 @@ static int aqr_config_aneg_set_prot(stru +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -285,10 +285,16 @@ static int aqr_config_aneg_set_prot(stru phy_write_mmd(phydev, MDIO_MMD_VEND1, AQUANTIA_VND1_GSTART_RATE, aquantia_syscfg[if_type].start_rate); diff --git a/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch index f30e65101a..a31b327f9e 100644 --- a/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch +++ b/target/linux/generic/hack-5.15/724-net-phy-aquantia-Add-AQR113-driver-support.patch @@ -5,11 +5,11 @@ Subject: [PATCH] PONRTSYS-8842: aquantia: Add AQR113 driver support Add a new entry for AQR113 PHY_ID --- - drivers/net/phy/aquantia_main.c | 10 ++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c @@ -26,6 +26,7 @@ #define PHY_ID_AQR813 0x31c31cb2 #define PHY_ID_AQR112 0x03a1b662 @@ -18,7 +18,7 @@ Add a new entry for AQR113 PHY_ID #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -972,6 +973,14 @@ static struct phy_driver aqr_driver[] = +@@ -923,6 +924,14 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, }, { @@ -33,7 +33,7 @@ Add a new entry for AQR113 PHY_ID PHY_ID_MATCH_MODEL(PHY_ID_AQR412), .name = "Aquantia AQR412", .probe = aqr107_probe, -@@ -999,6 +1008,7 @@ static struct mdio_device_id __maybe_unu +@@ -950,6 +959,7 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, diff --git a/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch index ab674409d6..b2f79f4d58 100644 --- a/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch +++ b/target/linux/generic/hack-5.15/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch @@ -7,11 +7,11 @@ As advised by Ian Chang this PHY is used in Puzzle devices. Signed-off-by: Daniel Golle --- - drivers/net/phy/aquantia_main.c | 10 ++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c @@ -27,6 +27,8 @@ #define PHY_ID_AQR112 0x03a1b662 #define PHY_ID_AQR412 0x03a1b712 @@ -21,7 +21,7 @@ Signed-off-by: Daniel Golle #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -973,6 +975,30 @@ static struct phy_driver aqr_driver[] = +@@ -924,6 +926,30 @@ static struct phy_driver aqr_driver[] = .get_stats = aqr107_get_stats, }, { @@ -52,7 +52,7 @@ Signed-off-by: Daniel Golle PHY_ID_MATCH_MODEL(PHY_ID_AQR113), .name = "Aquantia AQR113", .config_aneg = aqr_config_aneg, -@@ -1009,6 +1035,8 @@ static struct mdio_device_id __maybe_unu +@@ -960,6 +986,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR112) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR412) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113) }, diff --git a/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch b/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch index ef274237c2..3d2c86169b 100644 --- a/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch +++ b/target/linux/generic/hack-5.15/726-net-phy-aquantia-enable-AQR111-and-AQR111B0.patch @@ -10,8 +10,8 @@ This is a 5GbE chip but it reports support for 10G. Implement config_init() to set max speed to 5G. Signed-off-by: Thomas Kupper ---- a/drivers/net/phy/aquantia_main.c -+++ b/drivers/net/phy/aquantia_main.c +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c @@ -24,6 +24,8 @@ #define PHY_ID_AQR405 0x03a1b4b0 #define PHY_ID_AQR113C 0x31c31c12 @@ -21,7 +21,7 @@ Signed-off-by: Thomas Kupper #define PHY_ID_AQR112 0x03a1b662 #define PHY_ID_AQR412 0x03a1b712 #define PHY_ID_AQR113 0x31c31c40 -@@ -731,6 +733,33 @@ static int aqcs109_config_init(struct ph +@@ -676,6 +678,33 @@ static int aqcs109_config_init(struct ph return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT); } @@ -55,7 +55,7 @@ Signed-off-by: Thomas Kupper static void aqr107_link_change_notify(struct phy_device *phydev) { u8 fw_major, fw_minor; -@@ -963,6 +992,42 @@ static struct phy_driver aqr_driver[] = +@@ -914,6 +943,42 @@ static struct phy_driver aqr_driver[] = .link_change_notify = aqr107_link_change_notify, }, { @@ -98,7 +98,7 @@ Signed-off-by: Thomas Kupper PHY_ID_MATCH_MODEL(PHY_ID_AQR112), .name = "Aquantia AQR112", .probe = aqr107_probe, -@@ -1032,6 +1097,8 @@ static struct mdio_device_id __maybe_unu +@@ -983,6 +1048,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, diff --git a/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch b/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch index b8964f4e76..977bdeb5b1 100644 --- a/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch +++ b/target/linux/mediatek/patches-5.15/500-gsw-rtl8367s-mt7622-support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -367,6 +367,12 @@ config ROCKCHIP_PHY +@@ -364,6 +364,12 @@ config ROCKCHIP_PHY help Currently supports the integrated Ethernet PHY. @@ -15,7 +15,7 @@ help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -95,6 +95,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o +@@ -91,6 +91,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_REALTEK_PHY) += realtek.o obj-$(CONFIG_RENESAS_PHY) += uPD60620.o obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch b/target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch index 9da2975582..72ad2a9846 100644 --- a/target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch +++ b/target/linux/mediatek/patches-5.15/730-v6.5-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch @@ -42,7 +42,7 @@ Signed-off-by: David S. Miller L: linux-i2c@vger.kernel.org --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -293,6 +293,18 @@ config MEDIATEK_GE_PHY +@@ -290,6 +290,18 @@ config MEDIATEK_GE_PHY help Supports the MediaTek Gigabit Ethernet PHYs. @@ -63,7 +63,7 @@ Signed-off-by: David S. Miller help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -81,6 +81,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o +@@ -77,6 +77,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o diff --git a/target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch b/target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch index 7151eb35cc..7600819246 100644 --- a/target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch +++ b/target/linux/mediatek/patches-5.15/733-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch @@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -305,6 +305,13 @@ config MEDIATEK_GE_SOC_PHY +@@ -302,6 +302,13 @@ config MEDIATEK_GE_SOC_PHY present in the SoCs efuse and will dynamically calibrate VCM (common-mode voltage) during startup. @@ -29,7 +29,7 @@ Signed-off-by: Daniel Golle help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -80,6 +80,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell +@@ -76,6 +76,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell obj-$(CONFIG_MARVELL_PHY) += marvell.o obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o diff --git a/target/linux/realtek/patches-5.15/705-add-rtl-phy.patch b/target/linux/realtek/patches-5.15/705-add-rtl-phy.patch index 98c5e714b1..c6f8e6508b 100644 --- a/target/linux/realtek/patches-5.15/705-add-rtl-phy.patch +++ b/target/linux/realtek/patches-5.15/705-add-rtl-phy.patch @@ -14,7 +14,7 @@ Submitted-by: Birger Koblitz --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -357,6 +357,12 @@ config REALTEK_PHY +@@ -354,6 +354,12 @@ config REALTEK_PHY help Supports the Realtek 821x PHY. @@ -29,7 +29,7 @@ Submitted-by: Birger Koblitz help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -93,6 +93,7 @@ obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp +@@ -89,6 +89,7 @@ obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_REALTEK_PHY) += realtek.o From 8dcc695633034adcbcb6a05d922c108eee7e7ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Fri, 26 Jan 2024 17:10:31 +0100 Subject: [PATCH 219/222] mac80211: brcm: remove alternative DT firmware names patch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch has been reverted in the Raspberry Pi linux repository. Also refresh the rest of the patches. Signed-off-by: Álvaro Fernández Rojas --- .../ath9k/512-ath9k_channelbw_debugfs.patch | 2 +- .../ath9k/542-ath9k_debugfs_diag.patch | 8 +- .../ath9k/543-ath9k_entropy_from_adc.patch | 6 +- .../ath9k/553-ath9k_of_gpio_mask.patch | 2 +- ...d-alternative-firmware-names-from-DT.patch | 191 ------------------ .../780-avoid-crashing-missing-band.patch | 2 +- 6 files changed, 10 insertions(+), 201 deletions(-) delete mode 100644 package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch diff --git a/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch index 54abb4d425..474fb3fdbe 100644 --- a/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch +++ b/package/kernel/mac80211/patches/ath9k/512-ath9k_channelbw_debugfs.patch @@ -79,7 +79,7 @@ } --- a/drivers/net/wireless/ath/ath9k/common-debug.c +++ b/drivers/net/wireless/ath/ath9k/common-debug.c -@@ -316,3 +316,55 @@ void ath9k_cmn_debug_eeprom(struct dentr +@@ -315,3 +315,55 @@ void ath9k_cmn_debug_eeprom(struct dentr &fops_eeprom); } EXPORT_SYMBOL(ath9k_cmn_debug_eeprom); diff --git a/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch index e09bbc08ea..c54dbbb188 100644 --- a/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch +++ b/package/kernel/mac80211/patches/ath9k/542-ath9k_debugfs_diag.patch @@ -1,8 +1,8 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1562,6 +1562,50 @@ static const struct file_operations fops - #endif - +@@ -1468,6 +1468,50 @@ void ath9k_deinit_debug(struct ath_softc + ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); + } +static ssize_t read_file_diag(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) @@ -51,7 +51,7 @@ int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); -@@ -1589,6 +1633,8 @@ int ath9k_init_debug(struct ath_hw *ah) +@@ -1491,6 +1535,8 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("gpio_led", S_IWUSR, sc->debug.debugfs_phy, sc, &fops_gpio_led); #endif diff --git a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch index 00451061f2..8b399f4b4c 100644 --- a/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch +++ b/package/kernel/mac80211/patches/ath9k/543-ath9k_entropy_from_adc.patch @@ -55,7 +55,7 @@ ops->spectral_scan_config = ar9003_hw_spectral_scan_config; --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -870,7 +870,8 @@ static void ath9k_init_txpower_limits(st +@@ -871,7 +871,8 @@ static void ath9k_init_txpower_limits(st if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ); @@ -65,7 +65,7 @@ } static const struct ieee80211_iface_limit if_limits[] = { -@@ -1048,6 +1049,18 @@ static void ath9k_set_hw_capab(struct at +@@ -1049,6 +1050,18 @@ static void ath9k_set_hw_capab(struct at wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); } @@ -84,7 +84,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -1095,6 +1108,8 @@ int ath9k_init_device(u16 devid, struct +@@ -1096,6 +1109,8 @@ int ath9k_init_device(u16 devid, struct wiphy_read_of_freq_limits(hw->wiphy); diff --git a/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch index 6d1820ecb7..752a4980a4 100644 --- a/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch +++ b/package/kernel/mac80211/patches/ath9k/553-ath9k_of_gpio_mask.patch @@ -13,7 +13,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { -@@ -803,6 +809,9 @@ static int ath9k_init_softc(u16 devid, s +@@ -804,6 +810,9 @@ static int ath9k_init_softc(u16 devid, s if (ret) goto err_hw; diff --git a/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch b/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch deleted file mode 100644 index 22e26e7698..0000000000 --- a/package/kernel/mac80211/patches/brcm/865-brcmfmac-Read-alternative-firmware-names-from-DT.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 4e32024cbb14230af3048e249e84f8c2b25ce45a Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 Oct 2021 15:03:16 +0100 -Subject: [PATCH] brcmfmac: Read alternative firmware names from DT - -Add the ability to load the names of alternative firmwares from the -Device Tree node. This permits separate firmwares for 43436s and 43438 -and allows downstream firmwares to coexist with upstream. - -Signed-off-by: Phil Elwell ---- - .../wireless/broadcom/brcm80211/brcmfmac/of.c | 36 ++++++++++++++ - .../wireless/broadcom/brcm80211/brcmfmac/of.h | 7 +++ - .../broadcom/brcm80211/brcmfmac/sdio.c | 47 +++++++++++++++++-- - 3 files changed, 87 insertions(+), 3 deletions(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c -@@ -11,6 +11,7 @@ - #include "debug.h" - #include "core.h" - #include "common.h" -+#include "firmware.h" - #include "of.h" - - static int brcmf_of_get_country_codes(struct device *dev, -@@ -175,3 +176,38 @@ void brcmf_of_probe(struct device *dev, - sdio->oob_irq_nr = irq; - sdio->oob_irq_flags = irqf; - } -+ -+struct brcmf_firmware_mapping * -+brcmf_of_fwnames(struct device *dev, u32 *fwname_count) -+{ -+ struct device_node *np = dev->of_node; -+ struct brcmf_firmware_mapping *fwnames; -+ struct device_node *map_np, *fw_np; -+ int of_count; -+ int count = 0; -+ -+ map_np = of_get_child_by_name(np, "firmwares"); -+ of_count = of_get_child_count(map_np); -+ if (!of_count) -+ return NULL; -+ -+ fwnames = devm_kcalloc(dev, of_count, -+ sizeof(struct brcmf_firmware_mapping), -+ GFP_KERNEL); -+ -+ for_each_child_of_node(map_np, fw_np) -+ { -+ struct brcmf_firmware_mapping *cur = &fwnames[count]; -+ -+ if (of_property_read_u32(fw_np, "chipid", &cur->chipid) || -+ of_property_read_u32(fw_np, "revmask", &cur->revmask)) -+ continue; -+ cur->fw_base = of_get_property(fw_np, "fw_base", NULL); -+ if (cur->fw_base) -+ count++; -+ } -+ -+ *fwname_count = count; -+ -+ return count ? fwnames : NULL; -+} ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h -@@ -5,9 +5,20 @@ - #ifdef CONFIG_OF - void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, - struct brcmf_mp_device *settings); -+#ifdef CPTCFG_BRCMFMAC_SDIO -+struct brcmf_firmware_mapping * -+brcmf_of_fwnames(struct device *dev, u32 *map_count); -+#endif - #else - static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, - struct brcmf_mp_device *settings) - { - } -+#ifdef CPTCFG_BRCMFMAC_SDIO -+static struct brcmf_firmware_mapping * -+brcmf_of_fwnames(struct device *dev, u32 *map_count) -+{ -+ return NULL; -+} -+#endif - #endif /* CONFIG_OF */ ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -@@ -35,6 +35,7 @@ - #include "core.h" - #include "common.h" - #include "bcdc.h" -+#include "of.h" - - #define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500) - #define CTL_DONE_TIMEOUT msecs_to_jiffies(2500) -@@ -632,7 +633,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "b - /* per-board firmware binaries */ - MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-sdio.*.bin"); - --static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { -+static const struct brcmf_firmware_mapping sdio_fwnames[] = { - BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143), - BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0), - BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4), -@@ -660,6 +661,9 @@ static const struct brcmf_firmware_mappi - BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752) - }; - -+static const struct brcmf_firmware_mapping *brcmf_sdio_fwnames = sdio_fwnames; -+static u32 brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames); -+ - #define TXCTL_CREDITS 2 - - static void pkt_align(struct sk_buff *p, int len, int align) -@@ -4201,6 +4205,9 @@ static const struct brcmf_bus_ops brcmf_ - #define BRCMF_SDIO_FW_NVRAM 1 - #define BRCMF_SDIO_FW_CLM 2 - -+static struct brcmf_fw_request * -+brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus); -+ - static void brcmf_sdio_firmware_callback(struct device *dev, int err, - struct brcmf_fw_request *fwreq) - { -@@ -4216,6 +4223,22 @@ static void brcmf_sdio_firmware_callback - - brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); - -+ if (err && brcmf_sdio_fwnames != sdio_fwnames) { -+ /* Try again with the standard firmware names */ -+ brcmf_sdio_fwnames = sdio_fwnames; -+ brcmf_sdio_fwnames_count = ARRAY_SIZE(sdio_fwnames); -+ kfree(fwreq); -+ fwreq = brcmf_sdio_prepare_fw_request(bus); -+ if (!fwreq) { -+ err = -ENOMEM; -+ goto fail; -+ } -+ err = brcmf_fw_get_firmwares(dev, fwreq, -+ brcmf_sdio_firmware_callback); -+ if (!err) -+ return; -+ } -+ - if (err) - goto fail; - -@@ -4426,7 +4449,7 @@ brcmf_sdio_prepare_fw_request(struct brc - - fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev, - brcmf_sdio_fwnames, -- ARRAY_SIZE(brcmf_sdio_fwnames), -+ brcmf_sdio_fwnames_count, - fwnames, ARRAY_SIZE(fwnames)); - if (!fwreq) - return NULL; -@@ -4446,6 +4469,9 @@ struct brcmf_sdio *brcmf_sdio_probe(stru - struct brcmf_sdio *bus; - struct workqueue_struct *wq; - struct brcmf_fw_request *fwreq; -+ struct brcmf_firmware_mapping *of_fwnames, *fwnames = NULL; -+ const int fwname_size = sizeof(struct brcmf_firmware_mapping); -+ u32 of_fw_count; - - brcmf_dbg(TRACE, "Enter\n"); - -@@ -4528,6 +4554,21 @@ struct brcmf_sdio *brcmf_sdio_probe(stru - - brcmf_dbg(INFO, "completed!!\n"); - -+ of_fwnames = brcmf_of_fwnames(sdiodev->dev, &of_fw_count); -+ if (of_fwnames) -+ fwnames = devm_kcalloc(sdiodev->dev, -+ of_fw_count + brcmf_sdio_fwnames_count, -+ fwname_size, GFP_KERNEL); -+ -+ if (fwnames) { -+ /* The array is scanned in order, so overrides come first */ -+ memcpy(fwnames, of_fwnames, of_fw_count * fwname_size); -+ memcpy(fwnames + of_fw_count, sdio_fwnames, -+ brcmf_sdio_fwnames_count * fwname_size); -+ brcmf_sdio_fwnames = fwnames; -+ brcmf_sdio_fwnames_count += of_fw_count; -+ } -+ - fwreq = brcmf_sdio_prepare_fw_request(bus); - if (!fwreq) { - ret = -ENOMEM; diff --git a/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch b/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch index 2bc11efd00..4bbd786043 100644 --- a/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch +++ b/package/kernel/mac80211/patches/subsys/780-avoid-crashing-missing-band.patch @@ -18,7 +18,7 @@ Signed-off-by: David Bauer --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c -@@ -2422,6 +2422,13 @@ static void sta_stats_decode_rate(struct +@@ -2423,6 +2423,13 @@ static void sta_stats_decode_rate(struct sband = local->hw.wiphy->bands[band]; From 512b762ddbb602b744f0e7a443cf4ac7422155c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Fri, 26 Jan 2024 17:16:29 +0100 Subject: [PATCH 220/222] mac80211: brcm: disable dump_survey on Raspberry Pi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enabling this causes slow iwinfo calls on Raspberry Pi and LuCI slows down when wireless is enabled. Fixes: https://github.com/openwrt/openwrt/issues/14013 Signed-off-by: Álvaro Fernández Rojas --- ...mfmac-disable-dump_survey-on-bcm2835.patch | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 package/kernel/mac80211/patches/brcm/865-brcmfmac-disable-dump_survey-on-bcm2835.patch diff --git a/package/kernel/mac80211/patches/brcm/865-brcmfmac-disable-dump_survey-on-bcm2835.patch b/package/kernel/mac80211/patches/brcm/865-brcmfmac-disable-dump_survey-on-bcm2835.patch new file mode 100644 index 0000000000..e4d9270ce8 --- /dev/null +++ b/package/kernel/mac80211/patches/brcm/865-brcmfmac-disable-dump_survey-on-bcm2835.patch @@ -0,0 +1,22 @@ +brcmfmac: disable dump_survey on Raspberry Pi + +Enabling this causes slow iwinfo calls on Raspberry Pi and LuCI slows down +when wireless is enabled. +https://github.com/openwrt/openwrt/issues/14013 + +Signed-off-by: Álvaro Fernández Rojas +--- + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -8361,8 +8361,10 @@ struct brcmf_cfg80211_info *brcmf_cfg802 + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) + ops->set_rekey_data = brcmf_cfg80211_set_rekey_data; + #endif ++#if !defined(CONFIG_ARCH_BCM2835) + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_DUMP_OBSS)) + ops->dump_survey = brcmf_cfg80211_dump_survey; ++#endif /* CONFIG_ARCH_BCM2835 */ + + err = wiphy_register(wiphy); + if (err < 0) { From e5efc638a7d68f363718bd4fee99fbb70671bbe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Fri, 26 Jan 2024 17:28:19 +0100 Subject: [PATCH 221/222] iwinfo: update to latest git HEAD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds MediaTek MT7916AN and Cypress CYW43455 (Raspberry Pi 5) devices. a34977c devices: add device id for Cypress CYW43455 3eb34df devices: add device id for MediaTek MT7916AN There are no ABI changes. Signed-off-by: Álvaro Fernández Rojas --- package/network/utils/iwinfo/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/utils/iwinfo/Makefile b/package/network/utils/iwinfo/Makefile index c6a14956fd..4fef2babbb 100644 --- a/package/network/utils/iwinfo/Makefile +++ b/package/network/utils/iwinfo/Makefile @@ -11,9 +11,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/iwinfo.git -PKG_SOURCE_DATE:=2023-07-01 -PKG_SOURCE_VERSION:=ca79f64154b107f192ec3c1ba631816cb8b07922 -PKG_MIRROR_HASH:=5eddf584a1c3ed5637162d6bfc573ed1ce3691fcb38bdd55bf9f1e11e82ccc46 +PKG_SOURCE_DATE:=2023-11-19 +PKG_SOURCE_VERSION:=a34977c0760c93480491c8eb94da656b57d7f4cc +PKG_MIRROR_HASH:=cb01671a2a9155f8ba55751ab1fe28488c5821212dd97ba5b79653640abb787e PKG_MAINTAINER:=Jo-Philipp Wich PKG_LICENSE:=GPL-2.0 From 5485d27f4df9fe973ea797887d5381af3aa40ded Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 26 Jan 2024 21:02:21 +0100 Subject: [PATCH 222/222] libubox: update to Git HEAD (2024-01-26) 6339204c212b CMakeLists.txt: bump minimum cmake version c1be505732e6 udebug: fix crash in udebug_entry_vprintf with longer strings Signed-off-by: Felix Fietkau --- package/libs/libubox/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/libs/libubox/Makefile b/package/libs/libubox/Makefile index 1ea886e6ac..a987304ba1 100644 --- a/package/libs/libubox/Makefile +++ b/package/libs/libubox/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/libubox.git -PKG_MIRROR_HASH:=daf411244a7f87c09c383c6fb69636a038c85f351bba93e80cc9aa530301199e -PKG_SOURCE_DATE:=2023-12-04.1 -PKG_SOURCE_VERSION:=ca3f6d0cdb1e588283c42d039779ceab303ceef2 +PKG_MIRROR_HASH:=071139fed757bea240d4ba8f55a0ff5a81862d23e16b39fc871ae07da78ae6a4 +PKG_SOURCE_DATE:=2024-01-26 +PKG_SOURCE_VERSION:=c1be505732e6d254464973bdeacb955214c76c46 PKG_ABI_VERSION:=$(call abi_version_str,$(PKG_SOURCE_DATE)) CMAKE_INSTALL:=1